// ==UserScript==
// @name Youtube Downloader By Jeffery
// @description Download every YouTube video you want and you can download them as Full-HD MP4, FLV, 3GP, MP3 128kbps and 192kbps, M4A and AAC formats.
// @author Jeffery
// @version 1.7
// @namespace Jeffery
// @include http://www.youtube.com/*
// @include https://www.youtube.com/*
// @exclude http://www.youtube.com/embed/*
// @exclude https://www.youtube.com/embed/*
// @match http://www.youtube.com/*
// @match https://www.youtube.com/*
// @match http://manifest.googlevideo.com/*
// @match https://manifest.googlevideo.com/*
// @match http://*.googlevideo.com/videoplayback*
// @match https://*.googlevideo.com/videoplayback*
// @match http://*.youtube.com/videoplayback*
// @match https://*.youtube.com/videoplayback*
// @connect googlevideo.com
// @connect bvd2.nl
// @connect ytimg.com
// @grant GM_xmlhttpRequest
// @grant GM_getValu
// @grant GM_setValue
// @run-at document-end
// @license MIT License
// ==/UserScript==
alert("The download button is below the video.-Jeffery")
(function() {
var FORMAT_LABEL = {
'18': 'MP4 360p',
'22': 'MP4 720p',
'43': 'WebM 360p',
'44': 'WebM 480p',
'45': 'WebM 720p',
'46': 'WebM 1080p',
'135': 'MP4 480p - no audio',
'137': 'MP4 1080p - no audio',
'138': 'MP4 2160p - no audio',
'140': 'M4A 128kbps - audio',
'264': 'MP4 1440p - no audio',
'266': 'MP4 2160p - no audio',
'298': 'MP4 720p60 - no audio',
'13': '3GP',
'17': '3GP 144p',
'36': '3GP 240p',
'5': 'FLV 240p',
'34': 'FLV 360p',
'35': 'FLV 480p',
'299': 'MP4 1080p60 - no audio'
};
var FORMAT_TYPE = {
'5': 'flv',
'34': 'flv',
'35': 'flv',
'13': '3gp',
'17': '3gp',
'36': '3gp',
'18': 'mp4',
'22': 'mp4',
'43': 'webm',
'44': 'webm',
'45': 'webm',
'46': 'webm',
'135': 'mp4',
'137': 'mp4',
'138': 'mp4',
'140': 'm4a',
'264': 'mp4',
'266': 'mp4',
'298': 'mp4',
'299': 'mp4'
};
var FORMAT_ORDER = ['5', '13', '17', '34', '35', '36', '18', '43', '135', '44', '22', '298', '45', '137', '299', '46', '264', '138', '266', '140'];
var FORMAT_RULE = {
'flv': 'all',
'3gp': 'all',
'mp4': 'all',
'webm': 'none',
'm4a': 'max'
};
var SHOW_DASH_FORMATS = false;
var BUTTON_TOOLTIP = {
'ar': 'تنزيل هذا الفيديو',
'cs': 'Stáhnout toto video',
'de': 'Dieses Video herunterladen',
'en': 'Download this video',
'nl': 'Download deze video',
'es': 'Descargar este vídeo',
'fr': 'Télécharger cette vidéo',
'hi': 'वीडियो डाउनलोड करें',
'hu': 'Videó letöltése',
'id': 'Unduh video ini',
'it': 'Scarica questo video',
'ja': 'このビデオをダウンロードする',
'ko': '이 비디오를 내려받기',
'pl': 'Pobierz plik wideo',
'pt': 'Baixar este vídeo',
'ro': 'Descărcați acest videoclip',
'ru': 'Скачать это видео',
'tr': 'Bu videoyu indir',
'zh': '下载此视频'
};
var DECODE_RULE = [];
var RANDOM = 4789239175;
var CONTAINER_ID = 'download-youtube-video' + RANDOM;
var LISTITEM_ID = 'download-youtube-video-fmt' + RANDOM;
var BUTTON_ID = 'download-youtube-video-button' + RANDOM;
var DEBUG_ID = 'download-youtube-video-debug-info';
var STORAGE_URL = 'download-youtube-script-url';
var STORAGE_CODE = 'download-youtube-signature-code';
var STORAGE_DASH = 'download-youtube-dash-enabled';
var isDecodeRuleUpdated = false;
var version = '7.70';
start();
document.addEventListener("spfdone", start, false);
function start() {
//CHECK NEW DESIGN
function isMaterial() {
var temp;
temp = document.querySelector("ytd-app, [src*='polymer'],link[href*='polymer']");
if (temp && !document.getElementById("material-notice")) {
temp = document.createElement("template");
temp.innerHTML = //
`<div id='material-notice' style='border-radius:2px;color:#FFF;padding:10px;background-color:#ff0000;box-shadow:0 0 3px rgba(0,0,0,.5);font-size:12px;position:fixed;bottom:20px;right:50px;z-index:99999'>
<strong><ins>WARNING : </ins></strong>'Best Video Downloader 2' is not compatible with the experimental YouTube Material Layout<br/> which is under BETA testing.<br><br>
<a href='https://bvd2.nl/newdesign' target='_blank' style='color:#FFF;font-weight:bold;'>Click here</a> for instructions on how to continue using the video downloading features.<br>This addon will get migrated to the new layout if Youtube makes the BETA design as default.
</div>`;
document.documentElement.appendChild(temp.content.firstChild);
document.documentElement.removeAttribute("data-user_settings");
return true;
}
}
isMaterial();
//END
var pagecontainer = document.getElementById('page-container');
if (!pagecontainer) return;
if (/^https?:\/\/www\.youtube.com\/watch\?/.test(window.location.href)) run();
var isAjax = /class[\w\s"'-=]+spf\-link/.test(pagecontainer.innerHTML);
var logocontainer = document.getElementById('logo-container');
if (logocontainer && !isAjax) {
isAjax = (' ' + logocontainer.className + ' ').indexOf(' spf-link ') >= 0;
}
var content = document.getElementById('content');
if (isAjax && content) {
var mo = window.MutationObserver || window.WebKitMutationObserver;
if (typeof mo !== 'undefined') {
var observer = new mo(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes !== null) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
if (mutation.addedNodes[i].id == 'watch7-container' ||
mutation.addedNodes[i].id == 'watch7-main-container') {
run();
break;
}
}
}
});
});
observer.observe(content, {
childList: true,
subtree: true
});
} else {
pagecontainer.addEventListener('DOMNodeInserted', onNodeInserted, false);
}
}
}
function onNodeInserted(e) {
if (e && e.target && (e.target.id == 'watch7-container' ||
e.target.id == 'watch7-main-container')) {
run();
}
}
function run() {
if (document.getElementById(CONTAINER_ID)) return;
if (document.getElementById('p') && document.getElementById('vo')) return;
var videoID, videoFormats, videoAdaptFormats, videoManifestURL, scriptURL = null;
var isSignatureUpdatingStarted = false;
var operaTable = new Array();
var language = document.documentElement.getAttribute('lang');
var textDirection = 'left';
if (document.body.getAttribute('dir') == 'rtl') {
textDirection = 'right';
}
if (document.getElementById('watch7-action-buttons')) {
fixTranslations(language, textDirection);
}
var args = null;
var usw = (typeof this.unsafeWindow !== 'undefined') ? this.unsafeWindow : window;
if (usw.ytplayer && usw.ytplayer.config && usw.ytplayer.config.args) {
args = usw.ytplayer.config.args;
}
if (args) {
videoID = args['video_id'];
videoFormats = args['url_encoded_fmt_stream_map'];
videoAdaptFormats = args['adaptive_fmts'];
videoManifestURL = args['dashmpd'];
debug('DYVAM - Info: Standard mode. videoID ' + (videoID ? videoID : 'none') + '; ');
}
if (usw.ytplayer && usw.ytplayer.config && usw.ytplayer.config.assets) {
scriptURL = usw.ytplayer.config.assets.js;
}
if (videoID == null) {
var buffer = document.getElementById(DEBUG_ID + '2');
if (buffer) {
while (buffer.firstChild) {
buffer.removeChild(buffer.firstChild);
}
} else {
buffer = createHiddenElem('pre', DEBUG_ID + '2');
}
injectScript('if(ytplayer&&ytplayer.config&&ytplayer.config.args){document.getElementById("' + DEBUG_ID + '2").appendChild(document.createTextNode(\'"video_id":"\'+ytplayer.config.args.video_id+\'", "js":"\'+ytplayer.config.assets.js+\'", "dashmpd":"\'+ytplayer.config.args.dashmpd+\'", "url_encoded_fmt_stream_map":"\'+ytplayer.config.args.url_encoded_fmt_stream_map+\'", "adaptive_fmts":"\'+ytplayer.config.args.adaptive_fmts+\'"\'));}');
var code = buffer.innerHTML;
if (code) {
videoID = findMatch(code, /\"video_id\":\s*\"([^\"]+)\"/);
videoFormats = findMatch(code, /\"url_encoded_fmt_stream_map\":\s*\"([^\"]+)\"/);
videoFormats = videoFormats.replace(/&/g, '\\u0026');
videoAdaptFormats = findMatch(code, /\"adaptive_fmts\":\s*\"([^\"]+)\"/);
videoAdaptFormats = videoAdaptFormats.replace(/&/g, '\\u0026');
videoManifestURL = findMatch(code, /\"dashmpd\":\s*\"([^\"]+)\"/);
scriptURL = findMatch(code, /\"js\":\s*\"([^\"]+)\"/);
}
debug('DYVAM - Info: Injection mode. videoID ' + (videoID ? videoID : 'none') + '; ');
}
if (videoID == null) {
var bodyContent = document.body.innerHTML;
if (bodyContent != null) {
videoID = findMatch(bodyContent, /\"video_id\":\s*\"([^\"]+)\"/);
videoFormats = findMatch(bodyContent, /\"url_encoded_fmt_stream_map\":\s*\"([^\"]+)\"/);
videoAdaptFormats = findMatch(bodyContent, /\"adaptive_fmts\":\s*\"([^\"]+)\"/);
videoManifestURL = findMatch(bodyContent, /\"dashmpd\":\s*\"([^\"]+)\"/);
if (scriptURL == null) {
scriptURL = findMatch(bodyContent, /\"js\":\s*\"([^\"]+)\"/);
if (scriptURL) {
scriptURL = scriptURL.replace(/\\/g, '');
}
}
}
debug('DYVAM - Info: Brute mode. videoID ' + (videoID ? videoID : 'none') + '; ');
}
debug('DYVAM - Info: url ' + window.location.href + '; useragent ' + window.navigator.userAgent);
if (videoID == null || videoFormats == null || videoID.length == 0 || videoFormats.length == 0) {
debug('DYVAM - Error: No config information found. YouTube must have changed the code.');
return;
}
if (typeof window.opera !== 'undefined' && window.opera && typeof opera.extension !== 'undefined') {
opera.extension.onmessage = function(event) {
var index = findMatch(event.data.action, /xhr\-([0-9]+)\-response/);
if (index && operaTable[parseInt(index, 10)]) {
index = parseInt(index, 10);
var trigger = (operaTable[index])['onload'];
if (typeof trigger === 'function' && event.data.readyState == 4) {
if (trigger) {
trigger(event.data);
}
}
}
}
}
if (!isDecodeRuleUpdated) {
DECODE_RULE = getDecodeRules(DECODE_RULE);
isDecodeRuleUpdated = true;
}
if (scriptURL) {
scriptURL = absoluteURL(scriptURL);
fetchSignatureScript(scriptURL);
}
var videoTitle = document.title || 'video';
videoTitle = videoTitle.replace(/\s*\-\s*YouTube$/i, '').replace(/'/g, '\'').replace(/^\s+|\s+$/g, '').replace(/\.+$/g, '');
videoTitle = videoTitle.replace(/[:"\?\*]/g, '').replace(/[\|\\\/]/g, '_');
if (((window.navigator.userAgent || '').toLowerCase()).indexOf('windows') >= 0) {
videoTitle = videoTitle.replace(/#/g, '').replace(/&/g, '_');
} else {
videoTitle = videoTitle.replace(/#/g, '%23').replace(/&/g, '%26');
}
var sep1 = '%2C',
sep2 = '%26',
sep3 = '%3D';
if (videoFormats.indexOf(',') > -1) {
sep1 = ',';
sep2 = (videoFormats.indexOf('&') > -1) ? '&' : '\\u0026';
sep3 = '=';
}
var videoURL = new Array();
var videoSignature = new Array();
if (videoAdaptFormats) {
videoFormats = videoFormats + sep1 + videoAdaptFormats;
}
var videoFormatsGroup = videoFormats.split(sep1);
for (var i = 0; i < videoFormatsGroup.length; i++) {
var videoFormatsElem = videoFormatsGroup[i].split(sep2);
var videoFormatsPair = new Array();
for (var j = 0; j < videoFormatsElem.length; j++) {
var pair = videoFormatsElem[j].split(sep3);
if (pair.length == 2) {
videoFormatsPair[pair[0]] = pair[1];
}
}
if (videoFormatsPair['url'] == null) continue;
var url = unescape(unescape(videoFormatsPair['url'])).replace(/\\\//g, '/').replace(/\\u0026/g, '&');
if (videoFormatsPair['itag'] == null) continue;
var itag = videoFormatsPair['itag'];
var sig = videoFormatsPair['sig'] || videoFormatsPair['signature'];
if (sig) {
url = url + '&signature=' + sig;
videoSignature[itag] = null;
} else if (videoFormatsPair['s']) {
url = url + '&signature=' + decryptSignature(videoFormatsPair['s']);
videoSignature[itag] = videoFormatsPair['s'];
}
if (url.toLowerCase().indexOf('ratebypass') == -1) {
url = url + '&ratebypass=yes';
}
if (url.toLowerCase().indexOf('http') == 0) {
videoURL[itag] = url + '&title=' + videoTitle;
}
}
var showFormat = new Array();
for (var category in FORMAT_RULE) {
var rule = FORMAT_RULE[category];
for (var index in FORMAT_TYPE) {
if (FORMAT_TYPE[index] == category) {
showFormat[index] = (rule == 'all');
}
}
if (rule == 'max') {
for (var i = FORMAT_ORDER.length - 1; i >= 0; i--) {
var format = FORMAT_ORDER[i];
if (FORMAT_TYPE[format] == category && videoURL[format] != undefined) {
showFormat[format] = true;
break;
}
}
}
}
var dashPref = getPref(STORAGE_DASH);
if (dashPref == '1') {
SHOW_DASH_FORMATS = true;
} else if (dashPref != '0') {
setPref(STORAGE_DASH, '0');
}
var downloadCodeList = [];
for (var i = 0; i < FORMAT_ORDER.length; i++) {
var format = FORMAT_ORDER[i];
if (format == '37' && videoURL[format] == undefined) {
if (videoURL['137']) {
format = '137';
}
showFormat[format] = showFormat['37'];
} else if (format == '38' && videoURL[format] == undefined) {
if (videoURL['138'] && !videoURL['266']) {
format = '138';
}
showFormat[format] = showFormat['38'];
}
if (!SHOW_DASH_FORMATS && format.length > 2) continue;
if (videoURL[format] != undefined && FORMAT_LABEL[format] != undefined && showFormat[format]) {
downloadCodeList.push({
url: videoURL[format],
sig: videoSignature[format],
format: format,
label: FORMAT_LABEL[format]
});
debug('DYVAM - Info: itag' + format + ' url:' + videoURL[format]);
}
}
if (downloadCodeList.length == 0) {
debug('DYVAM - Error: No download URL found. Probably YouTube uses encrypted streams.');
return;
}
var newWatchPage = false;
var parentElement = document.getElementById('watch7-action-buttons');
if (parentElement == null) {
parentElement = document.getElementById('watch8-secondary-actions');
if (parentElement == null) {
debug('DYVAM Error - No container for adding the download button. YouTube must have changed the code.');
return;
} else {
newWatchPage = true;
}
}
var buttonLabel = (BUTTON_TOOLTIP[language]) ? BUTTON_TOOLTIP[language] : BUTTON_TOOLTIP['en'];
var mainSpan = document.createElement('span');
if (newWatchPage) {
var spanIcon = document.createElement('span');
spanIcon.setAttribute('class', 'yt-uix-button-content');
var imageIcon = document.createElement('img');
imageIcon.setAttribute('src', '//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif');
imageIcon.setAttribute('class', 'yt-uix-button-icon');
imageIcon.setAttribute('src', 'data:image/false;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAeCAIAAABc0ozeAAAACXBIWXMAAAsTAAALEwEAmpwYAAA57GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNyAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTctMDMtMjZUMDQ6MDI6MTgrMDI6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDE3LTAzLTI2VDA0OjAyOjE4KzAyOjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNy0wMy0yNlQwNDowMjoxOCswMjowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6Yzc2YTExOWMtYjQxYi0yMjQ0LWI3MWMtYTg0NDhkMzgwNmRhPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6MzkyYTcwOGQtMTFjOC0xMWU3LWFhNGMtZDdlYjlhNmQ0NjJiPC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6MjEwNDBjYzktMDcyNS03NDRiLWJlZWItZmFlY2Y3ZGQzZWUyPC94bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpIaXN0b3J5PgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y3JlYXRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjIxMDQwY2M5LTA3MjUtNzQ0Yi1iZWViLWZhZWNmN2RkM2VlMjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNy0wMy0yNlQwNDowMjoxOCswMjowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDpjNzZhMTE5Yy1iNDFiLTIyNDQtYjcxYy1hODQ0OGQzODA2ZGE8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTctMDMtMjZUMDQ6MDI6MTgrMDI6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE3IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3BuZzwvZGM6Zm9ybWF0PgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT42NTUzNTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+OTY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MzA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/Pq4YhDcAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAABP5JREFUeNrsmlFMU1cYx/+FXqCt0EvT6kWj1YSQtgg0IyPFuKHBZDUxpptLKpmEyktLgml5WAbzZQ9TcUuERqNlD67GEeHFGV2y+kAUyEZjwtKugVYgsRdDqdB0F8rl1nZt9zBFAip1ajLN/b/dk/M/555fvvOd755cAcuydt/FsYX7C2wYvJ5KKqEqSPWJ3Rah3Xex79HvY0RBSlTEc1lRbor1hYcB5G75XHknJ5MSCHgoq5URCCI5QkWcyVlcDvN0nquUQLDIPcrhQbxcPCAe0OtJ+KqGH/f2mjYBABO9XHxvgI+gl4jgt9j/VNaaHzJ7zf/dX/F9pv6k9S1tsSwX0C2TPHlIMp7IdYN3gH6/c5C16rSlkABAip60kIV6/956AOFo3/7x0bWG5Lht4JQdOz7ZdcRR2uyuTpSMDr/PgOwTQ4Y9jftWpx1CoSIQXxqyrafzTNO3H3TtE50O7jh4STTcwkG5vdVVVqsiALDB+VuG0RHLHrspfVPk7gd0v+4/oWOvFt9zAfo79Y3UnNUttRvS3qCoSksAqXnXxLcH6ciq8Su7apotMkUBEE/SzrFzLeEIIDdXfdVZspXEKouo/ufqY4ZNeQAbWEoCzJvOQZxrv3cokFobJu2jPbc3stLjdABy1WZAdOyGqpaK3dw3+IV2zA/Z0b4KRWcsVCApNQOQ1aryQUoqjQCoShURck9FAJCSrcGJDsHg+b6EQr/9iHLVyE3VZps0ecPXIRg872DllnKzFcCu1u4Sqed+h8DV0R4T60vNVsBaYTTkz3Z7rILfrnogfjtJOtKjnxh/9smfpB3eU3YuS7OEkgClVVpMOu71D3LwPuz6JsqoZPqdM6EgodDLUKdUUozXLVSaKCgVCooLOTkAYBZcnz6cBuduiIaQLzc8G7PeRJLByOWGmWlw7jbviIcoPVoGRK6b/ugyPZgGps/O0gxBalFvKJQEo1fbwhHEhhsWIm/rFKPpUzr/OAMgFXJ6v255hYnYMAsASCdXEF9JLEMo1kZHAo8Vqm2VliJpgPnOzZKqErWtcGt4aWQwizoj/rf/aYzPMsk8Mh+IQbfT7NH3ZvS9GbWGXN/zTecged3mUmqF5OOBzlnoHg+5hDoj9bQxveCe87/onFJqlCpE7s4BRUAOsWJqyhMjPR+G27nY2Fd4FHmzd2m0gbZsMeqEbGDGvdGLJQEUCNWAHwBEJSSBeBJ1Vc026bLT13F8ZhrKk3+pybU93zSgI44PPlatbdSshHo8hYLckNP15fHneHc0aRo7tynD844WDpjyeqiDlhqjy9fPyFrbZWRw7kI/gEjIodaolob0HEBPBrYf0GGyc+O6YMDJfOaUN1/bdr4hKjlTUatNTbYHQFUTSCfC3DIKP7pUoiSxAAzciBm7ZY1d1Lk2Vn1NKs8+Sb9+HcSGE9gpWh/+mm59b/e/ddDcZYN3GAC4nwwB0lV2+G7dYYANzvcZvH4AoKcCZRoqNkQD4G55uAPa9FRHFnNfGe3R1jRbKs5kgHiSdvgunAUwfstUY2yvsbcjEWBmGYhJGey+fl210aa125AIMBEmP9vlCQ5dP/TLBneJZr9+fQSt0Ysi6N3WIW4xmwjqUbt6+OsOXjwgHhAPiAfEA3r3ABWJqdxMhgexXrmZTJGYyqksVpcn4zyj9XTKk1yVTCM8sdsC4E/Gv8j/vLBKUglVKf+wtdz8zwBtOQxheHlkawAAAABJRU5ErkJggg==');
spanIcon.appendChild(imageIcon);
mainSpan.appendChild(spanIcon);
}
var spanButton = document.createElement('span');
spanButton.setAttribute('class', 'yt-uix-button-content');
mainSpan.appendChild(spanButton);
if (!newWatchPage) {
var imgButton = document.createElement('img');
imgButton.setAttribute('class', 'yt-uix-button-arrow');
imgButton.setAttribute('src', '//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif');
mainSpan.appendChild(imgButton);
}
var listItems = document.createElement('ol');
listItems.setAttribute('style', 'display:none;');
listItems.setAttribute('class', 'yt-uix-button-menu');
for (var i = 0; i < downloadCodeList.length; i++) {
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', downloadCodeList[i].url);
listLink.setAttribute('download', videoTitle + '.' + FORMAT_TYPE[downloadCodeList[i].format]);
var listButton = document.createElement('span');
listButton.setAttribute('class', 'yt-uix-button-menu-item');
listButton.setAttribute('loop', i + '');
listButton.setAttribute('id', LISTITEM_ID + downloadCodeList[i].format);
if (downloadCodeList[i].format == '137') {
listButton.onclick = function() {
window.open('https://bvd2.nl/download/direct/1080p.php?url=' + videoID);
}
}
listButton.appendChild(document.createTextNode(downloadCodeList[i].label));
listLink.appendChild(listButton);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
}
if (videoURL['137'] != undefined) {
//console.log('Inside Full-HD :' + format);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', 'javascript:void(0);');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-1080p3');
listSpan.onclick = function () {
window.open('https://bvd2.nl/download/direct/1080p.php?url=' + videoID);
return false;
};
listSpan.appendChild(document.createTextNode('MP4 1080p (Full-HD)'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
}
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', 'https://bvd2.nl/download/direct/aac.php?url=' + videoID);
listLink.setAttribute('target', '_blank');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-aac');
listSpan.appendChild(document.createTextNode('AAC'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', 'https://bvd2.nl/download/direct/mp3.php?url=' + videoID);
listLink.setAttribute('target', '_blank');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-mp3');
listSpan.appendChild(document.createTextNode('MP3 (128 Kbps)'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', 'https://bvd2.nl/download/direct/mp3hq.php?url=' + videoID);
listLink.setAttribute('target', '_blank');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-mp3hq');
listSpan.appendChild(document.createTextNode('MP3 (192 Kbps)'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', 'https://bvd2.nl/download/direct/m4a.php?url=' + videoID);
listLink.setAttribute('target', '_blank');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-m4a');
listSpan.appendChild(document.createTextNode('M4A (Best Quality)'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
var thumbID = 'vi/' + videoID + '/hqdefault.jpg';
listLink.setAttribute('href', 'https://img.youtube.com/' + thumbID);
listLink.setAttribute('target', '_blank');
listLink.setAttribute('download', 'https://img.youtube.com/' + thumbID);
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-thumbnail');
listSpan.setAttribute('title', 'Contact to get support, Bug Report or Suggestion');
listSpan.appendChild(document.createTextNode('Thumbnail'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration:none;');
listLink.setAttribute('href', 'https://bvd2.nl/download/direct/subtitle.php?url=' + videoID);
listLink.setAttribute('target', '_blank');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-sub');
listSpan.appendChild(document.createTextNode('Subtitle'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
var listItem = document.createElement('li');
var listLink = document.createElement('a');
listLink.setAttribute('style', 'text-decoration: underline overline; margin-left: 1px; color: #1b7fcc;');
listLink.setAttribute('href', 'https://bvd2.nl/support?ver=' + version);
listLink.setAttribute('target', '_blank');
var listSpan = document.createElement('span');
listSpan.setAttribute('class', 'yt-uix-button-menu-item');
listSpan.setAttribute('id', LISTITEM_ID + '-support');
listSpan.setAttribute('title', 'Contact to get support, Bug Report or Suggestion');
listSpan.appendChild(document.createTextNode('Contact/Help/Donate'));
listLink.appendChild(listSpan);
listItem.appendChild(listLink);
listItems.appendChild(listItem);
mainSpan.appendChild(listItems);
var buttonElement = document.createElement('button');
buttonElement.setAttribute('id', BUTTON_ID);
if (newWatchPage) {
buttonElement.setAttribute('class', 'yt-uix-button yt-uix-button-size-default yt-uix-button-opacity yt-uix-tooltip yt-uix-button-active');
} else {
buttonElement.setAttribute('class', 'yt-uix-button yt-uix-tooltip yt-uix-button-empty yt-uix-button-text');
buttonElement.setAttribute('style', 'margin-top:4px; margin-left:' + ((textDirection == 'left') ? 5 : 10) + 'px;');
}
buttonElement.setAttribute('data-tooltip-text', buttonLabel);
buttonElement.setAttribute('type', 'button');
buttonElement.setAttribute('role', 'button');
buttonElement.addEventListener('click', function() {
var frm_div = document.getElementById('EXT_DIV');
if (frm_div) {
frm_div.parentElement.removeChild(frm_div);
}
return false;
}, false);
buttonElement.appendChild(mainSpan);
var containerSpan = document.createElement('span');
containerSpan.setAttribute('id', CONTAINER_ID);
containerSpan.appendChild(document.createTextNode(' '));
containerSpan.appendChild(buttonElement);
if (!newWatchPage) {
parentElement.appendChild(containerSpan);
} else {
parentElement.insertBefore(containerSpan, parentElement.firstChild);
}
for (var i = 0; i < downloadCodeList.length; i++) {
addFileSize(downloadCodeList[i].url, downloadCodeList[i].format);
}
if (typeof GM_download !== 'undefined') {
for (var i = 0; i < downloadCodeList.length; i++) {
var downloadFMT = document.getElementById(LISTITEM_ID + downloadCodeList[i].format);
var url = (downloadCodeList[i].url).toLowerCase();
if (url.indexOf('clen=') > 0 && url.indexOf('dur=') > 0 && url.indexOf('gir=') > 0 &&
url.indexOf('lmt=') > 0) {
downloadFMT.addEventListener('click', downloadVideoNatively, false);
}
}
}
addFromManifest();
function downloadVideoNatively(e) {
var elem = e.currentTarget;
e.returnValue = false;
if (e.preventDefault) {
e.preventDefault();
}
var loop = elem.getAttribute('loop');
if (loop) {
GM_download(downloadCodeList[loop].url, videoTitle + '.' + FORMAT_TYPE[downloadCodeList[loop].format]);
}
return false;
}
function addFromManifest() { // add Dash URLs from manifest file
var formats = ['137', '138', '140']; // 137=1080p, 138=4k, 140=m4a
var isNecessary = true;
for (var i = 0; i < formats.length; i++) {
if (videoURL[formats[i]]) {
isNecessary = false;
break;
}
}
if (videoManifestURL && SHOW_DASH_FORMATS && isNecessary) {
var matchSig = findMatch(videoManifestURL, /\/s\/([a-zA-Z0-9\.]+)\//i);
if (matchSig) {
var decryptedSig = decryptSignature(matchSig);
if (decryptedSig) {
videoManifestURL = videoManifestURL.replace('/s/' + matchSig + '/', '/signature/' + decryptedSig + '/');
}
}
if (videoManifestURL.indexOf('//') == 0) {
var protocol = (document.location.protocol == 'http:') ? 'http:' : 'https:';
videoManifestURL = protocol + videoManifestURL;
}
debug('DYVAM - Info: manifestURL ' + videoManifestURL);
crossXmlHttpRequest({
method: 'GET',
url: videoManifestURL, // check if URL exists
onload: function(response) {
if (response.readyState === 4 && response.status === 200 && response.responseText) {
debug('DYVAM - Info: maniestFileContents ' + response.responseText);
var lastFormatFromList = downloadCodeList[downloadCodeList.length - 1].format;
debug('DYVAM - Info: lastformat: ' + lastFormatFromList);
for (var i = 0; i < formats.length; i++) {
k = formats[i];
if (videoURL[k] || showFormat[k] == false) continue;
var regexp = new RegExp('<BaseURL>(http[^<]+itag\\/' + k + '[^<]+)<\\/BaseURL>', 'i');
var matchURL = findMatch(response.responseText, regexp);
debug('DYVAM - Info: matchURL itag= ' + k + ' url= ' + matchURL);
if (!matchURL) continue;
matchURL = matchURL.replace(/&\;/g, '&');
// ...
downloadCodeList.push({
url: matchURL,
sig: videoSignature[k],
format: k,
label: FORMAT_LABEL[k]
});
var downloadFMT = document.getElementById(LISTITEM_ID + lastFormatFromList);
var clone = downloadFMT.parentNode.parentNode.cloneNode(true);
clone.firstChild.firstChild.setAttribute('id', LISTITEM_ID + k);
clone.firstChild.setAttribute('href', matchURL);
downloadFMT.parentNode.parentNode.parentNode.appendChild(clone);
downloadFMT = document.getElementById(LISTITEM_ID + k);
downloadFMT.firstChild.nodeValue = FORMAT_LABEL[k];
addFileSize(matchURL, k);
lastFormatFromList = k;
}
}
}
});
}
}
function injectStyle(code) {
var style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(code));
document.getElementsByTagName('head')[0].appendChild(style);
}
function injectScript(code) {
var script = document.createElement('script');
script.type = 'application/javascript';
script.textContent = code;
document.body.appendChild(script);
document.body.removeChild(script);
}
function debug(str) {
var debugElem = document.getElementById(DEBUG_ID);
if (!debugElem) {
debugElem = createHiddenElem('div', DEBUG_ID);
}
debugElem.appendChild(document.createTextNode(str + ' '));
}
function createHiddenElem(tag, id) {
var elem = document.createElement(tag);
elem.setAttribute('id', id);
elem.setAttribute('style', 'display:none;');
document.body.appendChild(elem);
return elem;
}
function fixTranslations(language, textDirection) {
if (/^af|bg|bn|ca|cs|de|el|es|et|eu|fa|fi|fil|fr|gl|hi|hr|hu|id|it|iw|kn|lv|lt|ml|mr|ms|nl|pl|ro|ru|sl|sk|sr|sw|ta|te|th|uk|ur|vi|zu$/.test(language)) {
var likeButton = document.getElementById('watch-like');
if (likeButton) {
var spanElements = likeButton.getElementsByClassName('yt-uix-button-content');
if (spanElements) {
spanElements[0].style.display = 'none';
}
}
var marginPixels = 10;
if (/^bg|ca|cs|el|eu|hr|it|ml|ms|pl|sl|sw|te$/.test(language)) {
marginPixels = 1;
}
injectStyle('#watch7-secondary-actions .yt-uix-button{margin-' + textDirection + ':' + marginPixels + 'px!important}');
}
}
function findMatch(text, regexp) {
var matches = text.match(regexp);
return (matches) ? matches[1] : null;
}
function isString(s) {
return (typeof s === 'string' || s instanceof String);
}
function isInteger(n) {
return (typeof n === 'number' && n % 1 == 0);
}
function absoluteURL(url) {
var link = document.createElement('a');
link.href = url;
return link.href;
}
function getPref(name) {
var a = '',
b = '';
try {
a = typeof GM_getValue.toString;
b = GM_getValue.toString()
} catch (e) {}
if (typeof GM_getValue === 'function' &&
(a === 'undefined' || b.indexOf('not supported') === -1)) {
return GM_getValue(name, null);
} else {
var ls = null;
try {
ls = window.localStorage || null
} catch (e) {}
if (ls) {
return ls.getItem(name);
}
}
return;
}
function setPref(name, value) {
var a = '',
b = '';
try {
a = typeof GM_setValue.toString;
b = GM_setValue.toString()
} catch (e) {}
if (typeof GM_setValue === 'function' &&
(a === 'undefined' || b.indexOf('not supported') === -1)) {
GM_setValue(name, value);
} else {
var ls = null;
try {
ls = window.localStorage || null
} catch (e) {}
if (ls) {
return ls.setItem(name, value);
}
}
}
function crossXmlHttpRequest(details) {
if (typeof GM_xmlhttpRequest === 'function') {
GM_xmlhttpRequest(details);
} else if (typeof window.opera !== 'undefined' && window.opera && typeof opera.extension !== 'undefined' &&
typeof opera.extension.postMessage !== 'undefined') {
var index = operaTable.length;
opera.extension.postMessage({
'action': 'xhr-' + index,
'url': details.url,
'method': details.method
});
operaTable[index] = details;
} else if (typeof window.opera === 'undefined' && typeof XMLHttpRequest === 'function') {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (details['onload']) {
details['onload'](xhr);
}
}
}
xhr.open(details.method, details.url, true);
xhr.send();
}
}
function addFileSize(url, format) {
function updateVideoLabel(size, format) {
var elem = document.getElementById(LISTITEM_ID + format);
if (elem) {
size = parseInt(size, 10);
if (size >= 1073741824) {
size = parseFloat((size / 1073741824).toFixed(1)) + ' GB';
} else if (size >= 1048576) {
size = parseFloat((size / 1048576).toFixed(1)) + ' MB';
} else {
size = parseFloat((size / 1024).toFixed(1)) + ' KB';
}
if (elem.childNodes.length > 1) {
elem.lastChild.nodeValue = ' (' + size + ')';
} else if (elem.childNodes.length == 1) {
elem.appendChild(document.createTextNode(' (' + size + ')'));
}
}
}
var matchSize = findMatch(url, /[&\?]clen=([0-9]+)&/i);
if (matchSize) {
updateVideoLabel(matchSize, format);
} else {
try {
crossXmlHttpRequest({
method: 'HEAD',
url: url,
onload: function(response) {
if (response.readyState == 4 && response.status == 200) {
var size = 0;
if (typeof response.getResponseHeader === 'function') {
size = response.getResponseHeader('Content-length');
} else if (response.responseHeaders) {
var regexp = new RegExp('^Content\-length: (.*)$', 'im');
var match = regexp.exec(response.responseHeaders);
if (match) {
size = match[1];
}
}
if (size) {
updateVideoLabel(size, format);
}
}
}
});
} catch (e) {}
}
}
function findSignatureCode(sourceCode) {
debug('DYVAM - Info: signature start ' + getPref(STORAGE_CODE));
var signatureFunctionName =
findMatch(sourceCode,
/\.set\s*\("signature"\s*,\s*([a-zA-Z0-9_$][\w$]*)\(/) ||
findMatch(sourceCode,
/\.sig\s*\|\|\s*([a-zA-Z0-9_$][\w$]*)\(/) ||
findMatch(sourceCode,
/\.signature\s*=\s*([a-zA-Z_$][\w$]*)\([a-zA-Z_$][\w$]*\)/);
if (signatureFunctionName == null) return setPref(STORAGE_CODE, 'error');
signatureFunctionName = signatureFunctionName.replace('$', '\\$');
var regCode = new RegExp(signatureFunctionName + '\\s*=\\s*function' +
'\\s*\\([\\w$]*\\)\\s*{[\\w$]*=[\\w$]*\\.split\\(""\\);\n*(.+);return [\\w$]*\\.join');
var regCode2 = new RegExp('function \\s*' + signatureFunctionName +
'\\s*\\([\\w$]*\\)\\s*{[\\w$]*=[\\w$]*\\.split\\(""\\);\n*(.+);return [\\w$]*\\.join');
var functionCode = findMatch(sourceCode, regCode) || findMatch(sourceCode, regCode2);
debug('DYVAM - Info: signaturefunction ' + signatureFunctionName + ' -- ' + functionCode);
if (functionCode == null) return setPref(STORAGE_CODE, 'error');
var reverseFunctionName = findMatch(sourceCode,
/([\w$]*)\s*:\s*function\s*\(\s*[\w$]*\s*\)\s*{\s*(?:return\s*)?[\w$]*\.reverse\s*\(\s*\)\s*}/);
debug('DYVAM - Info: reversefunction ' + reverseFunctionName);
if (reverseFunctionName) reverseFunctionName = reverseFunctionName.replace('$', '\\$');
var sliceFunctionName = findMatch(sourceCode,
/([\w$]*)\s*:\s*function\s*\(\s*[\w$]*\s*,\s*[\w$]*\s*\)\s*{\s*(?:return\s*)?[\w$]*\.(?:slice|splice)\(.+\)\s*}/);
debug('DYVAM - Info: slicefunction ' + sliceFunctionName);
if (sliceFunctionName) sliceFunctionName = sliceFunctionName.replace('$', '\\$');
var regSlice = new RegExp('\\.(?:' + 'slice' + (sliceFunctionName ? '|' + sliceFunctionName : '') +
')\\s*\\(\\s*(?:[a-zA-Z_$][\\w$]*\\s*,)?\\s*([0-9]+)\\s*\\)');
var regReverse = new RegExp('\\.(?:' + 'reverse' + (reverseFunctionName ? '|' + reverseFunctionName : '') +
')\\s*\\([^\\)]*\\)');
var regSwap = new RegExp('[\\w$]+\\s*\\(\\s*[\\w$]+\\s*,\\s*([0-9]+)\\s*\\)');
var regInline = new RegExp('[\\w$]+\\[0\\]\\s*=\\s*[\\w$]+\\[([0-9]+)\\s*%\\s*[\\w$]+\\.length\\]');
var functionCodePieces = functionCode.split(';');
var decodeArray = [];
for (var i = 0; i < functionCodePieces.length; i++) {
functionCodePieces[i] = functionCodePieces[i].trim();
var codeLine = functionCodePieces[i];
if (codeLine.length > 0) {
var arrSlice = codeLine.match(regSlice);
var arrReverse = codeLine.match(regReverse);
debug(i + ': ' + codeLine + ' --' + (arrSlice ? ' slice length ' + arrSlice.length : '') + ' ' + (arrReverse ? 'reverse' : ''));
if (arrSlice && arrSlice.length >= 2) {
var slice = parseInt(arrSlice[1], 10);
if (isInteger(slice)) {
decodeArray.push(-slice);
} else return setPref(STORAGE_CODE, 'error');
} else if (arrReverse && arrReverse.length >= 1) {
decodeArray.push(0);
} else if (codeLine.indexOf('[0]') >= 0) {
if (i + 2 < functionCodePieces.length &&
functionCodePieces[i + 1].indexOf('.length') >= 0 &&
functionCodePieces[i + 1].indexOf('[0]') >= 0) {
var inline = findMatch(functionCodePieces[i + 1], regInline);
inline = parseInt(inline, 10);
decodeArray.push(inline);
i += 2;
} else return setPref(STORAGE_CODE, 'error');
} else if (codeLine.indexOf(',') >= 0) {
var swap = findMatch(codeLine, regSwap);
swap = parseInt(swap, 10);
if (isInteger(swap) && swap > 0) {
decodeArray.push(swap);
} else return setPref(STORAGE_CODE, 'error');
} else return setPref(STORAGE_CODE, 'error');
}
}
if (decodeArray) {
setPref(STORAGE_URL, scriptURL);
setPref(STORAGE_CODE, decodeArray.toString());
DECODE_RULE = decodeArray;
debug('DYVAM - Info: signature ' + decodeArray.toString() + ' ' + scriptURL);
for (var i = 0; i < downloadCodeList.length; i++) {
var elem = document.getElementById(LISTITEM_ID + downloadCodeList[i].format);
var url = downloadCodeList[i].url;
var sig = downloadCodeList[i].sig;
if (elem && url && sig) {
url = url.replace(/\&signature=[\w\.]+/, '&signature=' + decryptSignature(sig));
elem.parentNode.setAttribute('href', url);
addFileSize(url, downloadCodeList[i].format);
}
}
}
}
function isValidSignatureCode(arr) {
if (!arr) return false;
if (arr == 'error') return true;
arr = arr.split(',');
for (var i = 0; i < arr.length; i++) {
if (!isInteger(parseInt(arr[i], 10))) return false;
}
return true;
}
function fetchSignatureScript(scriptURL) {
var storageURL = getPref(STORAGE_URL);
var storageCode = getPref(STORAGE_CODE);
if (!(/,0,|^0,|,0$|\-/.test(storageCode))) storageCode = null;
if (storageCode && isValidSignatureCode(storageCode) && storageURL &&
scriptURL == absoluteURL(storageURL)) return;
try {
debug('DYVAM fetch ' + scriptURL);
isSignatureUpdatingStarted = true;
crossXmlHttpRequest({
method: 'GET',
url: scriptURL,
onload: function(response) {
debug('DYVAM fetch status ' + response.status);
if (response.readyState === 4 && response.status === 200 && response.responseText) {
findSignatureCode(response.responseText);
}
}
});
} catch (e) {}
}
function getDecodeRules(rules) {
var storageCode = getPref(STORAGE_CODE);
if (storageCode && storageCode != 'error' && isValidSignatureCode(storageCode)) {
var arr = storageCode.split(',');
for (var i = 0; i < arr.length; i++) {
arr[i] = parseInt(arr[i], 10);
}
rules = arr;
debug('DYVAM - Info: signature ' + arr.toString() + ' ' + scriptURL);
}
return rules;
}
function decryptSignature(sig) {
function swap(a, b) {
var c = a[0];
a[0] = a[b % a.length];
a[b] = c;
return a
};
function decode(sig, arr) {
if (!isString(sig)) return null;
var sigA = sig.split('');
for (var i = 0; i < arr.length; i++) {
var act = arr[i];
if (!isInteger(act)) return null;
sigA = (act > 0) ? swap(sigA, act) : ((act == 0) ? sigA.reverse() : sigA.slice(-act));
}
var result = sigA.join('');
return result;
}
if (sig == null) return '';
var arr = DECODE_RULE;
if (arr) {
var sig2 = decode(sig, arr);
if (sig2) return sig2;
} else {
setPref(STORAGE_URL, '');
setPref(STORAGE_CODE, '');
}
return sig;
}
}
})();