lunes, 16 de julio de 2018
// CIwPiCBDlkxSEh5KBf8+nSpl7VadMyVTMETDNQKBtn3emJ2ejerSx6/pnARYFvdOqmLh5XUDfmh3acu30t8ct17Y91oEsDF0yQbKokjuXsIqCY7D1gLUh1UXndMbDG4IiMRq79Ya7nKD4qiSVXX7rhk+DUmThu34jHowHV7oNPj5qTqSYxLcIinqGOkn/HyuoVcXltmRkyPqRub8+SdXVwJneyvNTTTvjDZrldcSXrxybh0NguD4nO+u9cvUL5mPJAcNfg2toho2KpZVPmjYLLuYUJ7ezhNLZMQUdHG9JKDOZiWlqhAMa4S9PULpPBPdWY/TEiUFKspANpQjfgBFkg==
/**
** Copyright (C) 2000-2017 Opera Software AS. All rights reserved.
**
** This file is part of the Opera web browser.
**
** This script patches sites to work better with Opera
** For more information see http://www.opera.com/docs/browserjs/
**
** If you have comments on these patches (for example if you are the webmaster
** and want to inform us about a fixed site that no longer needs patching)
** please report issues through the bug tracking system
** https://bugs.opera.com/
**
** DO NOT EDIT THIS FILE! It will not be used by Opera if edited.
**
** BROWSERJS_TIMESTAMP = '201804231700'; // for versioning; see DNA-54964
**/
'use strict';
if (!location.href.includes('operabrowserjs=no')) {
(function(document) {
const {href, pathname, hostname} = location;
/*
We make references to the following functions to not get version that
users
have overwritten.
*/
const setTimeout = window.setTimeout;
const call = Function.prototype.call;
const copyMethod = (method, ...defaultArgs) => {
method.call = call;
return (...args) => {
if (defaultArgs.length) {
args = defaultArgs.concat(args);
}
return method.call(...args);
};
};
const addEventListener = copyMethod(Window.prototype.addEventListener);
const appendChild = copyMethod(Node.prototype.appendChild);
const createElement = copyMethod(Document.prototype.createElement);
const createTextNode =
copyMethod(Document.prototype.createTextNode, document);
const setAttribute = copyMethod(Element.prototype.setAttribute);
const querySelector = copyMethod(Document.prototype.querySelector);
const version = () => {
const total = Object.keys(PATCHES).length;
/* eslint-disable max-len */
return `Opera OPRDesktop 28.0 core 1750.0, January 09, 2018. Active patches: ${total}`;
/* eslint-enable max-len */
};
const log = text => {
/* eslint-disable max-len, no-console */
console.log(
`Opera has modified script or content on ${hostname} (${text}). See browser.js for details`);
/* eslint-enable max-len, no-console */
};
const isPartOfDomain = host =>
hostname.endsWith(`.${host}`) || hostname === host;
const hideOperaUserAgent = () => {
const newUA = navigator.userAgent.replace(/ ?OPR.[0-9.]*/, '');
Object.defineProperty(window.navigator, 'userAgent', {get: () => newUA});
};
const addCssToDocument = (cssText, doc = document, mediaType = '') => {
addCssToDocument.styleObj = addCssToDocument.styleObj || {};
let styles = addCssToDocument.styleObj[mediaType];
if (!styles) {
const head = querySelector(doc, 'head');
if (!head) {
// head always present in html5-parsers, assume document not ready
addEventListener(doc, 'DOMContentLoaded', () => {
addCssToDocument(cssText, doc, mediaType);
}, false);
return;
}
styles = createElement(doc, 'style');
addCssToDocument.styleObj[mediaType] = styles;
setAttribute(styles, 'type', 'text/css');
if (mediaType) {
setAttribute(styles, 'media', mediaType);
}
appendChild(styles, createTextNode(' '));
appendChild(head, styles);
}
styles.firstChild.nodeValue += `${cssText}\n`;
return true;
};
const PATCHES = {
'PATCH-1173': {
description: 'ssc[online][2].{nic,gov}.in - ' +
'Netscape not supported message - workaround browser sniffing',
isMatching: () => {
if ((hostname.endsWith('.nic.in') || hostname.endsWith('.gov.in')) &&
hostname.includes('ssc')) {
if (hostname.match(/ssc(?:online)?2?\.(?:nic|gov)\.in/)) {
return true;
}
}
return false;
},
applyOnDOMReady: true,
apply: () => {
Object.defineProperty(
window.navigator, 'appName', {get: () => 'Opera'});
},
},
'PATCH-1218': {
description: 'pretend to be Chrome on lufthansa.com',
isMatching: () => isPartOfDomain('lufthansa.com'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1228': {
description: 'block for delta-homes com spam site',
isMatching: () => isPartOfDomain('delta-homes.com'),
apply: () => location.reload('https://google.com'),
},
'PATCH-1227': {
description: 'Mock as Chrome on popular American Bank Sites',
isMatching: () => isPartOfDomain('bankofamerica.com') ||
isPartOfDomain('chase.com'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1289': {
description: 'Mock as Chrome on popular polish bank BGZ Optima',
isMatching: () => isPartOfDomain('bgzoptima.pl'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1207': {
description: 'Bluejeans web app doesn\'t work with Opera',
isMatching: () => {
if (!isPartOfDomain('bluejeans.com')) {
return false;
}
if (!window.chrome.runtime || !window.chrome.runtime.sendMessage) {
return true;
}
return false;
},
apply: () => window.chrome.runtime = {'sendMessage': () => {}},
},
'PATCH-1221': {
description: 'Redirect Blue Jeans meeting URL to the one ending with ' +
'/browser to avoid an issue that prevents joining a meeting.',
isMatching: () => {
if (!isPartOfDomain('bluejeans.com')) {
return false;
}
// Bluejeans is hanging on https://*.bluejeans.com/123456789/ urls's.
// It expects to have the special extension installed. Not a case on
// https://*.bluejeans.com/123456789/browser url's.
// Also urls with password should be handled :
// https://*.bluejeans.com/123456789/1234
const meetingPattern = /^[\d/]{8,}$/;
return meetingPattern.test(location.pathname);
},
apply: () => {
const finalURL = new URL(location);
if (location.pathname.endsWith('/')) {
finalURL.pathname += 'browser';
} else {
finalURL.pathname += '/browser';
}
location.replace(finalURL);
},
},
'PATCH-1190': {
description: 'Delta.com shows browser warning to Opera 25',
isMatching: () => isPartOfDomain('delta.com'),
apply: () => {
let value;
Object.defineProperty(window, 'UnsupportedBrowser', {
get: () => value,
set: arg => {
arg.badBrowser = () => false;
value = arg;
},
});
},
},
'PATCH-1195': {
description: 'Facebook - block first character in the comment field ' +
'from triggering a single key keyboard shortcut',
isMatching: () => isPartOfDomain('facebook.com'),
apply: () => {
addEventListener(document, 'keypress', e => {
// check if it's first character here
const target = e.target;
if (target.closest('.UFIAddCommentInput') &&
target.textContent === '') {
e.preventDefault();
const newEvent =
new Event('textInput', {bubbles: true, cancelable: true});
newEvent.data = String.fromCharCode(e.charCode);
target.dispatchEvent(newEvent);
}
});
},
},
'PATCH-1194': {
description: 'remove topbanner on www.hao123.com',
isMatching: () => isPartOfDomain('hao123.com'),
apply: () => {
const expires = new Date();
expires.setDate(expires.getDate() + 14);
const date = expires.toGMTString();
document.cookie =
`toptip=100;expires=${date};domain=.hao123.com;path=/`;
const topBanner = querySelector(document, '.widget-topbanner');
if (topBanner) {
topBanner.style.display = 'none';
}
},
},
'PATCH-1174': {
description:
'iCloud iWork new document stays blank - camouflage as Chrome',
isMatching: () => isPartOfDomain('icloud.com'),
apply: () => {
Object.defineProperty(window, 'SC', {
get: function() { return this.__SC__; },
set: function(arg) {
if (!arg.hasOwnProperty('browser')) {
Object.defineProperty(arg, 'browser', {
get: function() { return this.__browser__; },
set: function(arg) {
arg.isChrome = true;
arg.current = 'chrome';
arg.chrome = arg.version;
this.__browser__ = arg;
},
});
}
this.__SC__ = arg;
},
});
},
},
'OTWK-21': {
description: 'stanserhorn.ch - fix UDM sniffing',
isMatching: () => isPartOfDomain('stanserhorn.ch'),
apply: () => {
Object.defineProperty(
navigator, 'vendor', {get: () => 'Google Inc.'});
},
},
'PATCH-1187': {
description: 'iTunes U Course Manager - hide Opera tag',
isMatching: () => isPartOfDomain('itunesu.itunes.apple.com'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1156': {
description: 'my.tnt.com - fix empty printout',
isMatching: () => isPartOfDomain('my.tnt.com'),
applyOnDOMReady: true,
apply: () => {
const mpl = window.matchMedia('print');
let origClearPrintBlock;
mpl.addListener(mql => {
if (mql.matches) {
if (typeof clearPrintBlock === 'function') {
origClearPrintBlock = clearPrintBlock;
clearPrintBlock = () => {};
}
} else {
if (typeof origClearPrintBlock === 'function') {
setTimeout(origClearPrintBlock, 500);
}
}
});
},
},
'PATCH-1251': {
description: 'Avoid requiring Flash player on pandora.com',
isMatching: () => isPartOfDomain('pandora.com'),
apply: () => {
if (!document.cookie.includes('pwc-2016')) {
const expires = new Date();
expires.setDate(expires.getDate() + 14);
const date = expires.toGMTString();
document.cookie =
`pwc-2016=true;domain=.pandora.com;secure;expires=${date}`;
document.location.reload();
}
},
},
'PATCH-1252': {
description: 'hide first-run overlay on read.amazon.com',
isMatching: () => isPartOfDomain('read.amazon.com'),
apply: () => {
addCssToDocument([
'.ui-dialog.firstRunDialog, ',
'.ui-dialog.firstRunDialog + .ui-widget-overlay ',
'{visibility:hidden}',
].join(''));
},
},
'PATCH-1263': {
description: 'hide Unsupported Browser dialog on clarks.co.uk',
isMatching: () => isPartOfDomain('clarks.co.uk'),
apply: () => {
addCssToDocument('#unsupportedBrowser {visibility:hidden}');
},
},
'1': {
description: 'Browser.js status and version reported on browser.js ' +
'documentation page',
isMatching: () => isPartOfDomain('opera.com') &&
pathname.startsWith('/docs/browserjs/'),
applyOnDOMReady: true,
apply: () => {
const bjElement = querySelector(document, '#browserjs_active');
const bjMessage =
querySelector(document, '#browserjs_status_message');
if (bjElement) {
const bjElementChild = querySelector(bjElement, 'span');
if (bjElementChild) {
bjElement.style.display = '';
appendChild(bjElementChild, createTextNode(version()));
if (bjMessage) {
bjMessage.style.display = 'none';
}
}
}
},
},
'PATCH-221': {
description: 'Include browser.js timestamp in bug reports',
isMatching:
() => href.startsWith('https://bugs.opera.com/wizarddesktop/'),
applyOnDOMReady: true,
apply: () => {
const form = querySelector(document, '#bug');
if (form instanceof HTMLFormElement && form.auto) {
form.auto.value += `\n\nBrowser JavaScript: \n${version()}`;
}
},
},
'PATCH-555': {
description: 'Analytix: add missing end quote',
isMatching: () => pathname.startsWith('/AnalyticalReporting/'),
apply: () => {
if (pathname.includes('AnalyticalReporting/WebiModify.do') ||
pathname.includes('AnalyticalReporting/WebiCreate.do')) {
Object.defineProperty(window, 'embed_size_attr', {
get: function() { return this.__embed_size_attr__; },
set: function(arg) {
if (arg.split('"').length === 2) {
arg += '"';
}
this.__embed_size_attr__ = arg;
},
});
}
},
},
'PATCH-1217': {
description: 'pretend to be Chrome on Google Spreadsheets',
isMatching: () => hostname.startsWith('docs.google.') &&
pathname.startsWith('/spreadsheets/'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1213': {
description: 'pretend to be Chrome on Gmail',
isMatching: () => hostname.startsWith('mail.google.'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1214': {
description: 'Google Hangouts does not work without plugin',
isMatching: () => hostname.startsWith('plus.google.'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1220': {
description: 'pretend to be Chrome on talkgadget to not force ' +
'plugin download.',
isMatching: () => hostname.includes('.google.') &&
hostname.startsWith('talkgadget'),
apply: () => hideOperaUserAgent(),
},
'PATCH-1261': {
description: 'remove class to enable keyboard shortcut "copy"',
isMatching: () => hostname.startsWith('drive.google.') &&
pathname.startsWith('/file/'),
applyOnDOMReady: true,
apply: () => {
const text = querySelector(document, '.drive-viewer-text-content');
addEventListener(text, 'DOMNodeInserted', () => {
const textPage =
querySelector(document, '.drive-viewer-text-page');
if (textPage) {
textPage.classList.remove('drive-viewer-focus-to-default');
}
}, false);
},
},
'PATCH-1148': {
description: 'Google Translate: use flash instead of mp3-audio',
isMatching: () => hostname.startsWith('translate.google.'),
applyOnDOMReady: true,
apply: () => {
const obj = `
`;
const aud = querySelector(document, '#tts');
if (aud && aud instanceof HTMLAudioElement &&
aud.parentNode.childNodes.length === 1) {
aud.parentNode.innerHTML = obj;
}
},
},
'PATCH-1265': {
description: 'Hide Chrome ad from Translate Google page',
isMatching: () => hostname.startsWith('translate.google.'),
applyOnDOMReady: true,
apply: () => {
const res = document.evaluate(
'//a[contains(., "get Chrome")]', document, null,
XPathResult.ANY_TYPE, null);
if (res) {
const el = res.iterateNext();
if (el && el.parentNode && el.parentNode.parentNode) {
const ad = el.parentNode.parentNode;
ad.style.display = 'none';
}
}
},
},
'PATCH-1269': {
description: 'Hide Chrome ad from Google pages',
isMatching: () => hostname.startsWith('images.google.') ||
hostname.startsWith('www.google.'),
applyOnDOMReady: true,
apply: () => {
const href =
'https://www.google.com/url?q=/chrome/browser/desktop/';
const res = document.evaluate(
`//a[contains(@href, "${href}")]`, document, null,
XPathResult.ANY_TYPE, null);
const downloadLink = res.iterateNext();
if (downloadLink) {
const ad = downloadLink.closest('div[role="dialog"]');
if (ad) {
ad.style.display = 'none';
}
}
},
},
'PATCH-1275': {
description: 'Hide Edge ad from Microsoft pages',
isMatching: () =>
(window.navigator.appVersion.indexOf('Windows NT 10.0') > -1) && (
[
'www.microsoft.com', 'developer.microsoft.com',
'office.com', 'www.xbox.com', 'skype.com', 'onedrive.live.com',
].some(str => hostname.includes(str))),
applyOnDOMReady: true,
apply: () => {
addCssToDocument('#epb {display:none}');
},
},
'PATCH-1286': {
description: 'Hide notification about unsupported browser',
isMatching: () => isPartOfDomain('adidas.com'),
apply: () => {
addCssToDocument('#badBrowserModal {display:none !important}');
},
},
'PATCH-1287': {
description: 'Pretend to be Chrome on Amazon Alexa',
isMatching: () => isPartOfDomain('alexa.amazon.com'),
apply: () => hideOperaUserAgent(),
},
'DNA-69435': {
description: 'Hide Yandex ad from yandex search results',
isMatching: () => hostname.startsWith('yandex') &&
pathname.startsWith('/search/'),
apply: () => {
addCssToDocument('.popup2.distr-popup {visibility: hidden;}');
},
},
};
for (let key in PATCHES) {
const {isMatching, apply, description, applyOnDOMReady} = PATCHES[key];
if (isMatching()) {
const run = () => {
apply();
log(`${key}, ${description}`);
};
if (applyOnDOMReady) {
addEventListener(document, 'DOMContentLoaded', run, false);
} else {
run();
}
}
}
})(document);
}