Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
save from net
// ==UserScript==
// @name SaveFrom.net helper
// @namespace http://savefrom.net/
// @version 2.70
// @date 2014-07-12
// @author Magicbit, Inc
// @description Youtube Downloader: all in one script to get Vimeo, Facebook, Dailymotion videos for free
// @homepage http://savefrom.net/user.php?helper=userjs
// @icon http://savefrom.net/img/extension/icon_16.png
// @icon64 http://savefrom.net/img/extension/icon_64.png
// @updateURL https://sf-addon.com/helper/chrome/helper.meta.js
// @downloadURL https://sf-addon.com/helper/chrome/helper.user.js
// @include http://*
// @include https://*
// @exclude *://google.*/*
// @exclude *://*.google.*/*
// @exclude *://acidtests.org/*
// @exclude *://*.acidtests.org/*
// @run-at document-end
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_info
// @grant GM_openInTab
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_notification
// @grant GM_download
// ==/UserScript==
(function(){
if(!window.GM_getValue)
return;
if(window.sessionStorage) {
sessionStorage['savefrom-helper-userjs'] = '1';
}
var chrome, _menu, _options, _background, SaveFrom_Utils, _moduleHosts, _modules;
/////////////////////////////////////////////////
// CHROME
chrome = {
app: {
getDetails: function(){
if(GM_info && GM_info.script)
return GM_info.script;
return {};
}
},
browserAction: {
setIcon: function(icon){},
setTitle: function(title){},
},
tabs: {
getSelected: function(winId, cb){
cb({
id: 1,
url: location.href
});
},
query: function(queryInfo, cb){
cb([]);
},
create: function(options){
GM_openInTab(options.url, {
active: options.selected || options.active,
insert: true
});
},
sendRequest: function(id, request, callback){
if(!chrome.extension.moduleRequestHandler)
return;
chrome.extension.moduleRequestHandler(request, {}, callback);
},
onRemoved: {
addListener: function(){}
}
},
extension: {
requestHandler: null,
moduleRequestHandler: null,
onRequest: {
addListener: function(cb){
if(!chrome.extension.requestHandler)
{
chrome.extension.requestHandler = cb;
return;
}
chrome.extension.moduleRequestHandler = cb;
}
},
sendRequest: function(request, callback)
{
if(!chrome.extension.requestHandler)
{
callback();
return;
}
var sender = {
moduleName: request.moduleName,
tab: {
id: 1,
url: location.href
}
};
chrome.extension.requestHandler(request, sender, callback);
}
},
i18n: {
lang: 'en',
messages: {en: {}},
detectUserLanguage: function()
{
var lang = window.navigator.userLanguage || window.navigator.language;
if(lang && this.messages[lang])
this.lang = lang;
return this.lang;
},
getMessage: function(msg_id)
{
var m = this.messages[this.lang];
if(m && m[msg_id] && m[msg_id].message)
return m[msg_id].message;
return '';
},
translate: function(parent)
{
parent = parent || document;
var e_list = parent.querySelectorAll('*[data-i18n]');
for(var i = 0, len = e_list.length; i < len; i++)
{
var el = e_list[i];
el.innerText = chrome.i18n.getMessage(el.dataset.i18n);
}
}
},
downloads: {
download: function(options, cb) {
if (!window.GM_download) {
return;
}
var gm_options = {};
gm_options.url = options.url;
gm_options.name = options.filename;
gm_options.headers = options.headers;
gm_options.saveAs = !!(options.saveAs);
gm_options.onload = function() {
cb(true);
};
gm_options.onerror = cb;
GM_download(gm_options);
}
}
};
/////////////////////////////////////////////////
// MENU
_menu = {
activeDataAttr: 'data-sfh-active',
id: 'sfh--ujs-menu',
tooltipId: 'sfh--ujs-menu-tooltip',
enabled: true,
active: false,
hover: false,
title: '',
items: [],
shakeTimer: 0,
shakeInterval: 10000,
menu: null,
icon: null,
style: {
menu: {
initial: {
background: '#fff',
borderStyle: 'solid',
borderWidth: '2px 0 2px 2px',
borderRadius: '5px 0 0 5px',
display: 'none',
boxSizing: 'content-box',
font: '13px/18px Arial,Helvetica,sans-serif',
width: 'auto',
height: 'auto',
padding: 0,
margin: 0,
overflow: 'visible',
position: 'fixed',
top: '50px',
right: '0',
textAlign: 'left',
WebkitTransition: 'all 0.2s',
transition: 'all 0.2s',
zIndex: 99999,
cursor: 'pointer'
},
enabled: {
borderColor: '#8dc50b'
},
disabled: {
borderColor: '#d0d0d0'
},
tag: {
display: 'block',
width: '10px',
height: '20px',
overflow: 'hidden',
opacity: 0.5
},
tagHover: {
width: '20px',
opacity: 0.8
},
active: {
width: 'auto',
height: 'auto',
overflow: 'visible',
opacity: 0.9
}
},
icon: {
initial: {
display: 'inline-block',
boxSizing: 'content-box',
backgroundPosition: '50% 50%',
backgroundRepeat: 'no-repeat',
width: '16px',
height: '16px',
margin: 0,
padding: '2px',
overflow: 'hidden',
verticalAlign: 'middle'
},
enabled: {
backgroundImage: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAACOklEQVQ4y42TTWgTURSFz3sv00maJqVWg6LiD7VUdGERQQnoQlS6sStxVVBULE0XoiDFjejChaC4qCCIKBQE0U1XpYoLFX9AXLbVVhR/UInGTjKZeTOTee+6aKdO2iAeuJvDd8+73MtjRIRIT2ud5d3GdOsLdP0150VEyLN3LGIiPxGHPE8RDEApAkCLAuboiInE45ArwxIAhKHWWhPiFYak40zdBCMzazpyy9btcsuoIAcEUktuIB0HVUASScAtozIu8n3F359e9m36+j4BAHa1erzqTB7mjK0HAE8qaVB9QOBBAoDt2tvKzuRFIroHYIgDwEC3NWQV3YJlyZn5ADcIFOLlS+UCgGXJGavoFga6rSEAYPErRLozsXqqOUtddfsp4+2Rrd82L2YTDz53nDST2Q1ps42STZlmVdMrBGvmQa1SBwqe5c8qB+8Kg//0Att1/Fnme5WPbHgq026qpjEh2A4A4Ew4XBh2GHor615KJH9oVctoUmkAUIpe+yLoYUSECw8zufZ2MWoYfCf+Q7WaflUqqd7z++3iwg4ujadXpVr4fcPk+X82+/q5rOpD5w4435cs8cwoW7s8mxoxTb6nUbPv6ye/KrLvSi99ibwlVzh9m23M5MwbqTTfF/elox/ZRb//6lH6EPcbnnHwJutsaRPX0q2iBwCcshqrzqpTwydoejHbMAAABq+zLSLDLgOAsunscIEmGnELAYwxBoABEABMAKm9x7AdAB7fwhsAEoAPQM397rnGP/fQK/eKCl8BAAAAAElFTkSuQmCC)'
},
disabled: {
backgroundImage: 'url(data:image/png;base64,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)'
},
tag: {padding: '2px'},
active: {padding: '5px'}
},
title: {
display: 'inline-block',
font: 'bold 13px/18px Arial,Helvetica,sans-serif',
lineHeight: '26px',
margin: 0,
padding: 0,
textAlign: 'left',
verticalAlign: 'middle'
},
itemsBox: {
display: 'block',
margin: 0,
padding: 0
},
item: {
color: '#000',
backgroundColor: '#fff',
border: 'none',
boxSizing: 'content-box',
font: 'normal 13px/18px Arial,Helvetica,sans-serif',
margin: '2px',
padding: '2px 3px',
position: 'relative',
whiteSpace: 'nowrap',
textAlign: 'left',
cursor: 'pointer'
},
itemHover: {
backgroundColor: '#f9f9f9',
border: '1px solid #d0d0d0',
borderRadius: '3px',
padding: '1px 2px'
},
itemSep: {
backgroundColor: '#d0d0d0',
border: 'none',
borderRadius: 0,
boxSizing: 'content-box',
height: '1px',
lineHeight: '1px',
margin: '5px',
padding: '0',
cursor: 'default'
}
},
addItem: function(id, title, fn)
{
if(!title)
title = '-';
return this.items.push({id: id, title: title, fn: fn});
},
resetItems: function()
{
this.items = [];
},
setTitle: function(title, version)
{
this.title = title;
if(version)
this.title += ' ' + version;
},
create: function(enabled){
if(this.menu || !document.body)
return;
if(!this.items)
return;
var _this = this;
var menu = document.createElement('div');
menu.addEventListener('mouseover', function(){
if(!_this.active)
{
_this.hover = true;
_this.setElementsStyle('tagHover');
}
});
menu.addEventListener('mouseout', function(){
if(!_this.active)
{
_this.hover = false;
_this.setElementsStyle('tag');
}
});
var icon = document.createElement('div');
icon.title = this.title;
icon.addEventListener('click', function(event){
event.preventDefault();
event.stopPropagation();
if(event.button === 0)
{
_this.toggleMenuItems();
}
else if(event.button == 2)
{
_this.remove();
}
return false;
}, false);
icon.addEventListener('contextmenu', function(event){
event.preventDefault();
event.stopPropagation();
_this.remove();
return false;
}, false);
this.icon = menu.appendChild(icon);
this.menu = document.body.appendChild(menu);
this.setElementsStyle('initial');
this.setEnabled(enabled);
this.showTag();
if(this.isNewUser())
{
this.shakeTimer = setTimeout(function(){_this.shakeTag();}, this.shakeInterval);
}
},
setStyle: function(element, style)
{
if(this[element] && this.style[element] && this.style[element][style])
SaveFrom_Utils.setStyle(this[element], this.style[element][style]);
},
setElementsStyle: function(style)
{
if(!style)
return;
var elements = ['menu', 'icon'];
for(var i = 0; i < elements.length; i++)
this.setStyle(elements[i], style);
},
setEnabled: function(enabled)
{
this.enabled = enabled;
this.setElementsStyle(this.enabled ? 'enabled' : 'disabled');
},
showTag: function()
{
this.setElementsStyle('tag');
},
toggleMenuItems: function()
{
return _menu.active ? _menu.hideMenuItems() : _menu.showMenuItems();
},
remove: function()
{
if(_menu.menu)
_menu.menu.parentNode.removeChild(_menu.menu);
_menu.removeTooltip();
},
showMenuItems: function()
{
if(this.active)
return;
this.removeActiveItems();
var title = this.createTitle();
if(title)
this.menu.appendChild(title);
var items = this.createItems();
if(items)
this.menu.appendChild(items);
this.active = true;
this.setElementsStyle('active');
document.addEventListener('click', this.onDocumentClick, false);
document.addEventListener('keydown', this.onDocumentKeyDown, false);
if(this.isNewUser())
{
GM_setValue('newUser', '0');
this.showTooltip();
}
},
hideMenuItems: function()
{
this.removeTooltip();
this.removeActiveItems();
document.removeEventListener('click', this.onDocumentClick, false);
document.removeEventListener('keydown', this.onDocumentKeyDown, false);
this.active = false;
this.showTag();
},
onDocumentClick: function(event)
{
var node = event.target;
if(node != _menu.menu && !SaveFrom_Utils.isParent(node, _menu.menu))
{
_menu.hideMenuItems();
}
},
onDocumentKeyDown: function(event)
{
if(event.keyCode == 27)
{
_menu.hideMenuItems();
}
},
removeActiveItems: function()
{
var e = null;
while(e = this.menu.querySelector('div[' + this.activeDataAttr + ']'))
{
e.parentNode.removeChild(e);
}
},
createTitle: function()
{
var _this = this;
if(!this.title)
return null;
var title = document.createElement('div');
title.innerHTML = this.title;
title.setAttribute(this.activeDataAttr, '1');
SaveFrom_Utils.setStyle(title, this.style.title);
title.addEventListener('click', function(event){
if(event.button === 0)
{
event.preventDefault();
event.stopPropagation();
_this.toggleMenuItems();
return false;
}
});
return title;
},
createItems: function()
{
if(!this.items)
return;
var box = document.createElement('div');
box.setAttribute(this.activeDataAttr, '1');
SaveFrom_Utils.setStyle(box, this.style.itemsBox);
for(var i = 0; i < this.items.length; i++)
{
this.createItem(this.items[i], box);
}
return box;
},
createItem: function(data, parent)
{
var _this = this,
item = document.createElement('div');
if(!data.title || data.title == '-')
{
SaveFrom_Utils.setStyle(item, this.style.itemSep);
}
else if(data.fn)
{
item.innerHTML = data.title;
SaveFrom_Utils.setStyle(item, this.style.item);
item.addEventListener('mouseover', function(){
SaveFrom_Utils.setStyle(this, _this.style.itemHover);
});
item.addEventListener('mouseout', function(){
SaveFrom_Utils.setStyle(this, _this.style.item);
});
item.addEventListener('click', function(event){
if(event.button === 0)
{
event.preventDefault();
event.stopPropagation();
_this.hideMenuItems();
data.fn(data.id, data.title);
return false;
}
});
}
parent.appendChild(item);
},
isNewUser: function()
{
return GM_getValue('newUser') == '1';
},
shakeTag: function()
{
clearTimeout(this.shakeTag);
if(!this.enabled || this.active || !this.isNewUser())
return;
if(this.hover)
{
this.shakeTimer = setTimeout(function(){_menu.shakeTag();}, _menu.shakeInterval);
return;
}
var style = 'tagHover', counter = 0;
function step()
{
SaveFrom_Utils.setStyle(_menu.menu, _menu.style.menu[style]);
style = (style == 'tagHover') ? 'tag' : 'tagHover';
if(counter++ < 3)
{
setTimeout(step, 100);
return;
}
_menu.shakeTimer = setTimeout(function(){_menu.shakeTag();}, _menu.shakeInterval);
}
step();
},
removeTooltip: function()
{
var e = document.getElementById(this.tooltipId);
if(e)
e.parentNode.removeChild(e);
},
showTooltip: function()
{
var menuSize = SaveFrom_Utils.getSize(this.menu);
var t = document.createElement('div');
t.id = this.tooltipId;
SaveFrom_Utils.setStyle(t, {
border: 'none',
display: 'block',
boxSizing: 'content-box',
width: '280px',
height: 'auto',
padding: 0,
margin: 0,
overflow: 'visible',
position: 'fixed',
top: '50px',
right: menuSize.width + 10 + 'px',
WebkitTransition: 'all 0.2s',
transition: 'all 0.2s',
zIndex: 99999,
opacity: 0
});
var cnt = document.createElement('div');
cnt.innerHTML = chrome.i18n.getMessage("menuTooltip");
SaveFrom_Utils.setStyle(cnt, {
color: '#000',
background: '#fdeca6',
border: '1px solid #b3a77d',
borderRadius: '5px',
display: 'block',
boxSizing: 'content-box',
font: '13px/18px Arial,Helvetica,sans-serif',
padding: '10px',
margin: 0,
position: 'relative',
textAlign: 'left'
});
var arrow = document.createElement('div');
SaveFrom_Utils.setStyle(arrow, {
background: '#fdeca6',
borderRight: '1px solid #b3a77d',
borderBottom: '1px solid #b3a77d',
boxSizing: 'content-box',
position: 'absolute',
top: '10px',
right: '-7px',
width: '10px',
height: '10px',
WebkitTransform: 'rotate(-45deg)'
});
cnt.appendChild(arrow);
t.appendChild(cnt);
document.body.appendChild(t);
t.style.opacity = '0.9';
}
};
/////////////////////////////////////////////////
// OPTIONS
_options = {
classPrefix: 'sfh--',
dataAttr: 'data-sfh-option',
html: 'PHN0eWxlIHR5cGU9InRleHQvY3NzIj4KLnNmaC0tb3B0aW9uc3tiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOm5vbmU7Zm9udDoxM3B4LzEgQXJpYWwsSGVsdmV0aWNhLHNhbnMtc2VyaWY7d2lkdGg6NTgwcHg7bWFyZ2luOjA7cGFkZGluZzo5cHg7dGV4dC1hbGlnbjpsZWZ0fS5zZmgtLW9wdGlvbnMgLnNmaC0tdGl0bGV7Zm9udC1zaXplOjEuM2VtO21hcmdpbjowIDAgMS4zZW0gMH0KLnNmaC0tb3B0aW9ucyBmb3Jte21hcmdpbjowO3BhZGRpbmc6MH0KLnNmaC0tb3B0aW9ucyBsYWJlbHtkaXNwbGF5OmJsb2NrO21hcmdpbjouMmVtIDA7cGFkZGluZzowO3RleHQtYWxpZ246bGVmdH0KLnNmaC0tb3B0aW9ucyAuc2ZoLS1pbmxpbmUtY29udGVudCBsYWJlbHtkaXNwbGF5OmlubGluZS1ibG9jazttYXJnaW4tbGVmdDoxMHB4fQouc2ZoLS1vcHRpb25zIC5zZmgtLWZsZWZ0e2Zsb2F0OmxlZnR9Ci5zZmgtLW9wdGlvbnMgLnNmaC0tZmwtY29sdW1ue2Zsb2F0OmxlZnQ7bWFyZ2luLXJpZ2h0OjIwcHh9Ci5zZmgtLW9wdGlvbnMgLnNmaC0tY2xlYXJ7Y2xlYXI6Ym90aDtoZWlnaHQ6MDtmb250LXNpemU6MDtsaW5lLWhlaWdodDowfQouc2ZoLS1vcHRpb25zIC5zZmgtLWJsb2Nre2JvcmRlci10b3A6MXB4IHNvbGlkICNkZmUxZTg7cGFkZGluZzoxLjVlbSAwIDAgMDttYXJnaW46MS41ZW0gMCAwIDA7bWluLXdpZHRoOjE2MHB4fQouc2ZoLS1vcHRpb25zIC5zZmgtLWJsb2NrLXRpdGxle2ZvbnQtd2VpZ2h0OmJvbGQ7bWFyZ2luLWJvdHRvbTouNWVtfQouc2ZoLS1vcHRpb25zIC5zZmgtLW1vZHVsZXtmb250LXdlaWdodDpib2xkO21hcmdpbi10b3A6MWVtfS5zZmgtLW9wdGlvbnMgLnNmaC0tbW9kdWxlOmZpcnN0LWNoaWxke21hcmdpbi10b3A6MH0KLnNmaC0tb3B0aW9ucyAuc2ZoLS1tb2R1bGVfb3B0aW9uc3tmb250LXNpemU6LjllbTtmb250LXdlaWdodDpub3JtYWw7bWFyZ2luLWxlZnQ6MmVtfQoKPC9zdHlsZT4KPGRpdiBjbGFzcz0ic2ZoLS1vcHRpb25zIj4KICA8ZGl2IGNsYXNzPSJzZmgtLXRpdGxlIiBkYXRhLWkxOG49Im9wdGlvbnNUaXRsZSI+U2F2ZUZyb20ubmV0IEhlbHBlciAtIFByZWZlcmVuY2VzPC9kaXY+CgogIDxmb3JtPgogICAgPGRpdiBjbGFzcz0ic2ZoLS1ibG9jayI+CiAgICAgIDxkaXYgZGF0YS1pMThuPSJvcHRpb25zSGFuZGxlTGlua3MiIGNsYXNzPSJzZmgtLWJsb2NrLXRpdGxlIj5IYW5kbGUgbGlua3M8L2Rpdj4KICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJsbUZpbGVIb3N0aW5nIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNGaWxlSG9zdGluZ3MiPlRvIGZpbGVob3N0aW5nczwvc3Bhbj48L2xhYmVsPgogICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249ImxtTWVkaWFIb3N0aW5nIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNNZWRpYUhvc3RpbmdzIj5UbyBtZWRpYWhvc3RpbmdzPC9zcGFuPjwvbGFiZWw+CiAgICA8L2Rpdj4KCiAgICA8ZGl2IGNsYXNzPSJzZmgtLWJsb2NrIj4KICAgICAgPGRpdiBkYXRhLWkxOG49Im9wdGlvbnNNb2R1bGVzIiBjbGFzcz0ic2ZoLS1ibG9jay10aXRsZSI+TW9kdWxlczwvZGl2PgogICAgICA8ZGl2IGNsYXNzPSJzZmgtLXlvdXR1YmVfYm94IiBjbGFzcz0ic2ZoLS1tb2R1bGUiPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ibW9kdWxlWW91dHViZSIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zWW91dHViZSI+WW91VHViZTwvc3Bhbj48L2xhYmVsPgogICAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlX29wdGlvbnMiPgogICAgICAgICAgPGRpdiBjbGFzcz0ic2ZoLS1mbC1jb2x1bW4iPjxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc1lUSGlkZUxpbmtzIj5IaWRlIGxpbmtzPC9zcGFuPjo8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9InNmaC0tZmxlZnQgc2ZoLS1pbmxpbmUtY29udGVudCI+CiAgICAgICAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ieXRIaWRlRkxWIiBjaGVja2VkPSIwIj4mbmJzcDtGTFY8L2xhYmVsPgogICAgICAgICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Inl0SGlkZU1QNCIgY2hlY2tlZD0iMCI+Jm5ic3A7TVA0PC9sYWJlbD4KICAgICAgICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJ5dEhpZGVXZWJNIiBjaGVja2VkPSIxIj4mbmJzcDtXZWJNPC9sYWJlbD4KICAgICAgICAgICAgPGJyPgogICAgICAgICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Inl0SGlkZTNHUCIgY2hlY2tlZD0iMSI+Jm5ic3A7M0dQPC9sYWJlbD4KICAgICAgICAgICAgPGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgZGF0YS1zZmgtb3B0aW9uPSJ5dEhpZGUzRCIgY2hlY2tlZD0iMSI+Jm5ic3A7M0Q8L2xhYmVsPgogICAgICAgICAgICA8bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Inl0SGlkZU1QNE5vQXVkaW8iIGNoZWNrZWQ9IjEiPiZuYnNwO01QNCZuYnNwOyhubyZuYnNwO2F1ZGlvKTwvbGFiZWw+CiAgICAgICAgICAgIDxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0ieXRIaWRlQXVkaW9fTVA0IiBjaGVja2VkPSIxIj4mbmJzcDtBdWRpbzwvbGFiZWw+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9InNmaC0tY2xlYXIiPjwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KCiAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZURhaWx5bW90aW9uIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNEYWlseW1vdGlvbiI+RGFpbHltb3Rpb248L3NwYW4+PC9sYWJlbD48L2Rpdj4KCiAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZVZpbWVvIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNWaW1lbyI+VmltZW88L3NwYW4+PC9sYWJlbD48L2Rpdj4KCiAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZUZhY2Vib29rIiBjaGVja2VkPSIxIj4mbmJzcDs8c3BhbiBkYXRhLWkxOG49Im9wdGlvbnNGYWNlYm9vayI+RmFjZWJvb2s8L3NwYW4+PC9sYWJlbD48L2Rpdj4KCiAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZVNvdW5kY2xvdWQiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc1NvdW5kY2xvdWQiPlNvdW5kQ2xvdWQ8L3NwYW4+PC9sYWJlbD48L2Rpdj4KCiAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZVZrb250YWt0ZSIgY2hlY2tlZD0iMSI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zVmtvbnRha3RlIj5WSzwvc3Bhbj48L2xhYmVsPgogICAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlX29wdGlvbnMiPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIGRhdGEtc2ZoLW9wdGlvbj0idmtTaG93Qml0cmF0ZSIgY2hlY2tlZD0iMCI+Jm5ic3A7PHNwYW4gZGF0YS1pMThuPSJvcHRpb25zQml0cmF0ZSI+U2hvdyBiaXRyYXRlIGluc3RhbnRseTwvc3Bhbj48L2xhYmVsPjwvZGl2PgogICAgICA8L2Rpdj4KCiAgICAgIDxkaXYgY2xhc3M9InNmaC0tbW9kdWxlIj48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBkYXRhLXNmaC1vcHRpb249Im1vZHVsZU9kbm9rbGFzc25pa2kiIGNoZWNrZWQ9IjEiPiZuYnNwOzxzcGFuIGRhdGEtaTE4bj0ib3B0aW9uc09kbm9rbGFzc25pa2kiPk9kbm9rbGFzc25pa2k8L3NwYW4+PC9sYWJlbD48L2Rpdj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0ic2ZoLS1jbGVhciI+PC9kaXY+CiAgPC9mb3JtPgo8L2Rpdj4=',
init: function()
{
var _this = this,
parent = document.querySelector('.sfh--options');
if(!parent)
return;
chrome.i18n.translate(parent);
if(GM_getValue('lite') == '1')
this.hideBlock('youtube_box', true);
var c = parent.querySelectorAll('form input[type="checkbox"]');
for(var i = 0; i < c.length; i++)
{
var name = c[i].getAttribute(this.dataAttr);
if(name && GM_getValue(name))
{
c[i].checked = (GM_getValue(name) == '0') ? false : true;
c[i].addEventListener('change', function onCbChange(event){
var e = event.target, name = e.getAttribute(_this.dataAttr);
GM_setValue(name, e.checked ? '1' : '0');
}, false);
}
}
},
hideBlock: function(name, hide)
{
var node = document.querySelector('.' + this.classPrefix + name);
if(node)
node.style.display = hide ? 'none' : '';
},
show: function()
{
SaveFrom_Utils.popupDiv(atob(this.html), null, 640, 600);
this.init();
}
};
/////////////////////////////////////////////////
// BACKGROUND
_background = function(){
var infoPageActive = true;
var helper = getHelperName();
GM_setValue('helper', helper);
var lite = (helper == 'chromelite');
GM_setValue('lite', lite ? '1' : '0');
// default preferences
var default_preferences = {
version: 0,
enable: 1,
newUser: 1,
lmFileHosting: 1,
lmMediaHosting: 1,
moduleYoutube: 1,
moduleDailymotion: 1,
moduleVimeo: 1,
moduleFacebook: 1,
moduleSoundcloud: 1,
moduleVkontakte: 1,
moduleOdnoklassniki: 1,
moduleShowDownloadInfo: 1,
ytHideFLV: 0,
ytHideMP4: 0,
ytHideWebM: 1,
ytHide3GP: 1,
ytHide3D: 1,
ytHideMP4NoAudio: 1,
ytHideAudio_MP4: 1,
vkShowBitrate: 0
};
var pref_names = {
youtube: 'moduleYoutube',
dailymotion: 'moduleDailymotion',
vimeo: 'moduleVimeo',
facebook: 'moduleFacebook',
soundcloud: 'moduleSoundcloud',
vk: 'moduleVkontakte',
odnoklassniki: 'moduleOdnoklassniki'
};
var menuCommands = [
{
id: 'downloadFromCurrentPage',
command: downloadFromCurrentPage,
modules: ['lm', 'youtube', 'soundcloud', 'dailymotion']
},
{
id: '',
modules: ['lm', 'youtube', 'soundcloud', 'dailymotion']
},
{
id: 'updateLinks',
notify: 'updateLinksNotification',
modules: ['vk', 'odnoklassniki', 'facebook', 'lm']
},
{
id: 'downloadMP3Files',
modules: ['vk']
},
{
id: 'downloadPlaylist',
modules: ['vk']
},
{
id: 'downloadPhotos',
modules: ['vk']
},
{
id: '',
modules: ['vk', 'odnoklassniki', 'facebook', 'lm']
},
{
id: 'showOptions',
command: showOptions,
always: true
},
{
id: 'reportBug',
command: reportBug,
always: true
},
{
id: '',
always: true
},
{
id: 'disable',
command: enableExtension,
always: true
}
];
// localStorage == widget.preferences
for (var k in default_preferences)
{
if(GM_getValue(k) === undefined)
GM_setValue(k, default_preferences[k]); // set default preference
}
function registerModuleMenuCommand(params, enabled)
{
if(!params.id)
{
// separator
_menu.addItem();
return;
}
var strId = params.id;
if(!enabled && params.id == 'disable')
strId = 'menuEnable';
var name = chrome.i18n.getMessage(strId);
if(!name)
return;
if(params.command)
{
GM_registerMenuCommand(name, params.command);
_menu.addItem(params.id, name, params.command);
return;
}
var fn = function(){
chrome.tabs.sendRequest(1, {action: params.id});
if(params.notify)
GM_notification(chrome.i18n.getMessage(params.notify), null, null, null, 3000);
};
GM_registerMenuCommand(name, fn);
_menu.addItem(params.id, name, fn);
}
function registerMenuCommands(moduleName, enabled)
{
_menu.resetItems();
for(var i = 0; i < menuCommands.length; i++)
{
var item = menuCommands[i];
if(item.gmId)
{
continue;
GM_unregisterMenuCommand(item.gmId);
}
if(enabled || item.always)
{
if(!item.modules || item.modules.indexOf(moduleName) > -1)
{
menuCommands[i].gmId = registerModuleMenuCommand(item, enabled);
}
}
}
}
// modules[tab.id] = moduleName
var modules = {};
chrome.tabs.onRemoved.addListener(function(tabId){
if (tabId in modules)
delete modules[tabId];
});
// routes[action] = handler
// handler - function(request, sender) {
// ... code ...
// return response;
// }
var routes = {
initModule: function (request, sender, callback)
{
var response = {};
var extEnable = GM_getValue('enable') == '1';
var moduleName = request.moduleName;
response.name = moduleName;
if (sender.tab)
{
sender.tab.id = 1;
response.moduleEnable = true;
var info = chrome.app.getDetails();
response.version = info.version;
if(!request.frame)
{
modules[sender.tab.id] = moduleName;
}
response.helper = helper;
response.lite = lite;
response.downloads = false; //(window.GM_download !== undefined);
response.moduleShowDownloadInfo = GM_getValue('moduleShowDownloadInfo') == '1';
if(moduleName != 'savefrom')
{
response.ytHideFLV = GM_getValue('ytHideFLV');
response.ytHideMP4 = GM_getValue('ytHideMP4');
response.ytHideWebM = GM_getValue('ytHideWebM');
response.ytHide3GP = GM_getValue('ytHide3GP');
response.ytHide3D = GM_getValue('ytHide3D');
response.ytHideMP4NoAudio = GM_getValue('ytHideMP4NoAudio');
response.ytHideAudio_MP4 = GM_getValue('ytHideAudio_MP4');
if (moduleName == 'lm')
{
response.moduleEnable &= GM_getValue('lmFileHosting') == '1'
|| GM_getValue('lmMediaHosting') == '1';
response.lmMediaHosting = GM_getValue('lmMediaHosting');
response.lmFileHosting = GM_getValue('lmFileHosting');
}
else
{
response.moduleEnable &= GM_getValue(pref_names[moduleName]) == '1';
if(moduleName == 'vk')
{
response.vkShowBitrate = GM_getValue('vkShowBitrate');
}
}
}
if(!request.frame)
{
registerMenuCommands(request.moduleName, extEnable);
if(response.moduleEnable || moduleName == 'savefrom')
{
_menu.setTitle(chrome.i18n.getMessage('extName'), info.version);
_menu.create(extEnable);
}
}
response.moduleEnable &= extEnable;
}
callback(response);
userTrack();
},
hideDownloadInfo: function(request, sender){
GM_setValue('moduleShowDownloadInfo', '0');
},
getVimeoLinks: function (request, sender, callback)
{
function callback_links(links, title, thumb)
{
var response = {
action: request.action,
extVideoId: request.extVideoId,
links: links,
title: title,
thumb: thumb
};
callback(response);
}
getVimeoLinks(request.extVideoId, callback_links);
},
getVKLinks: function (request, sender, callback)
{
function callback_links(vid, links, title, duration, thumb, data, embed)
{
if(embed)
{
embed.origRequest = request;
routes[embed.action](embed, sender, callback);
return;
}
var response = {
action: request.action,
extVideoId: vid ? vid : request.extVideoId,
links: links,
title: title,
duration: duration,
thumb: thumb,
data: data,
checkLinks: null
};
if(request.checkLinks && links && links.length > 0)
{
checkVkLinks(links, function(checkUrl, isValid, status){
response.checkLinks = isValid;
callback(response);
});
return;
}
callback(response);
}
getVKLinks(request.extVideoId, callback_links);
},
getYoutubeLinks: function (request, sender, callback)
{
function callback_links(links, title, subtitles, duration)
{
var response = {
action: request.action,
extVideoId: request.extVideoId,
links: links,
title: title,
subtitles: subtitles,
duration: duration,
checkLinks: null
};
if(request.checkLinks && links)
{
checkYoutubeLinks(links, function(checkUrl, isValid, status){
response.checkLinks = isValid;
callback(response);
});
return;
}
callback(response);
}
getYoutubeLinks(sender.tab.url, request.extVideoId, request.checkSubtitles, callback_links);
},
getOdnoklassnikiLinks: function (request, sender, callback)
{
function callback_links(links)
{
var response = {
action: request.action,
extVideoId: request.extVideoId,
links: links,
title: request.title
};
callback(response);
}
getOdnoklassnikiLinks(request.extVideoId, callback_links);
},
getOdnoklassnikiAudioLinks: function (request, sender, callback)
{
function callback_links(data)
{
var response = {
action: request.action,
trackId: request.trackId,
jsessionId: request.jsessionId,
data: data
};
callback(response);
}
getOdnoklassnikiAudioLinks(sender.tab.url, request.trackId, request.jsessionId, callback_links);
},
getDailymotionLinks: function (request, sender, callback)
{
function callback_links(data)
{
if (!data) {
data = {};
}
var response = {
action: request.action,
extVideoId: request.extVideoId,
links: data.links,
title: data.title,
duration: data.duration,
thumb: data.thumb
};
callback(response);
}
getDailymotionLinks(request.extVideoId, callback_links)
},
getSoundcloudTrackInfo: function (request, sender, callback)
{
function callback_links(data, isValid)
{
var response = {
action: request.action,
trackUrl: request.trackUrl,
client_id: request.client_id,
data: data,
checkLinks: isValid
};
callback(response);
}
getSoundcloudTrackInfo(request.trackUrl, request.client_id, callback_links);
},
getFileSize: function (request, sender, callback)
{
getFileSize(request.url, callback);
},
downloadFile: function(request, sender, callback)
{
function callback_info(id)
{
var response = {
options: request.options,
id: id
};
callback(response);
}
downloadFile(request.options, callback_info);
}
};
// content scripts dispatcher
chrome.extension.onRequest.addListener(function(request, sender, callback){
//console.log('dispatcher', request, sender, callback);
routes[request.action](request, sender, callback);
});
function getHelperName()
{
var info = chrome.app.getDetails();
if(info && info.name && info.name.search(/\s+lite/i) > -1)
return 'chromelite';
if(navigator && navigator.userAgent)
{
if(navigator.userAgent.search(/YaBrowser\/\d+\.\d+/i) > -1)
return 'yabrowser';
if(navigator.userAgent.search(/OPR\/\d+\.\d+/i) > -1)
return 'opera-chromium';
}
return 'chrome';
}
// actions from menu
function enableExtension()
{
// toggle extension status
var enabled = GM_getValue('enable') == '1';
enabled = !enabled;
GM_setValue('enable', enabled ? '1' : '0');
_menu.setEnabled(enabled);
registerMenuCommands(modules[1], enabled);
setButtonParams();
}
function downloadFromCurrentPage()
{
chrome.tabs.getSelected(null, function(tab)
{
var url = 'http://savefrom.net/?url=' + encodeURIComponent(tab.url) +
'&utm_source=' + helper + '&utm_medium=extensions&utm_campaign=bookmarklet';
chrome.tabs.create({url: url, selected: true});
});
}
function installFullVersion()
{
var url = 'http://savefrom.net/user.php?helper=1' +
'&utm_source=' + helper + '&utm_medium=extensions&utm_campaign=get_full_version';
chrome.tabs.create({url: url, selected: true});
}
function showOptions()
{
_options.show();
}
function reportBug()
{
var url = 'http://savefrom.userecho.com/forum/20869-/';
if(chrome.i18n.getMessage("lang") == 'ru')
url = 'http://savefrom.userecho.com/forum/19523-/';
chrome.tabs.create({url: url, selected: true});
}
// tab actions
/*
var tabActions = ['updateLinks', 'downloadPlaylist', 'downloadMP3Files', 'downloadPhotos'];
function tabAction(request, tab)
{
if (tab)
{
chrome.tabs.sendRequest(tab.id, request);
}
else
{
chrome.tabs.getSelected(null, function(tab){
chrome.tabs.sendRequest(tab.id, request);
});
}
}
function createAction(name, tab)
{
return function(){
tabAction({action: name}, tab);
};
}
for (var i = 0; i < tabActions.length; i++)
{
var actionName = tabActions[i];
window[actionName] = createAction(actionName);
}
*/
// ---------
//setButtonParams();
if(GM_getValue('enable') != '0')
checkVersion();
function setButtonParams()
{
var icon = {path: 'images/icon_18.png'};
var title = {title: chrome.i18n.getMessage("titleDefault")};
if(GM_getValue('enable') == '0')
{
title.title = chrome.i18n.getMessage("titleDesabled");
icon.path = 'images/icon_disabled_18.png';
}
chrome.browserAction.setIcon(icon);
chrome.browserAction.setTitle(title);
}
function fixPref(pref)
{
for(i = 0; i < pref.length; i++)
{
if(GM_getValue(pref[i].name) != pref[i].check)
GM_setValue(pref[i].name, pref[i].def);
}
}
function checkVersion()
{
var url = '',
info = chrome.app.getDetails();
if(!GM_getValue('version') || GM_getValue('version') == '0')
{
// first run
url = 'http://savefrom.net/user.php?helper=userjs;firstrun';
}
else if(GM_getValue('version') != info.version)
{
// update
//url = 'http://savefrom.net/user.php?helper=userjs;update';
}
if(url)
{
GM_setValue('version', info.version);
return;
if(!infoPageActive)
{
chrome.tabs.create({url: url, selected: false, active: false});
}
else
{
chrome.tabs.query({url: '*://legal.yandex.com.tr/*'}, function(tabs) {
var active = tabs.length == 0;
chrome.tabs.query({url: '*://legal.yandex.ru/*'}, function(tabs) {
active = active && tabs.length == 0;
chrome.tabs.create({url: url, selected: active, active: active});
});
});
}
}
}
function sendRequest(url, callback, method, referer, post, cookie, header)
{
method = method ? method : ((post) ? 'POST' : 'GET');
var headers = {};
if(referer)
headers['Referer'] = referer;
if(cookie)
headers['Cookie'] = cookie;
if(post)
{
headers['Content-type'] = 'application/x-www-form-urlencoded';
headers['Content-Length'] = post.length;
}
if(header)
{
for(var i = 0; i < header.length; i++)
{
headers[header[i][0]] = header[i][1];
}
}
function cb(r)
{
r.getResponseHeader = function(header){
if(!r.responseHeaders)
return '';
var re = new RegExp("(?:^|[\\r\\n])" + header + ":\\s*(.+)(?:[\\r\\n]|$)", "im");
var m = r.responseHeaders.match(re);
if(m && m.length > 1)
return m[1];
return '';
}
callback(r);
}
GM_xmlhttpRequest({
method: method,
url: url,
data: post ? post : '',
headers: headers,
onload: cb,
onerror: cb,
ontimeout: cb
});
}
function getFileSize(url, callback, referer, cookie, header)
{
sendRequest(url, function(req){
var response = {
fileSize: 0,
fileType: '',
status: req.status
};
if (req.status == 200 || req.status == 206)
{
var s = req.getResponseHeader('Content-Length');
if(s)
{
s = parseInt(s);
if(!isNaN(s))
response.fileSize = s;
}
var t = req.getResponseHeader('Content-Type');
if(t)
response.fileType = t;
}
callback(response);
}, 'HEAD', referer, null, cookie, header);
}
function downloadFile(options, callback)
{
if(chrome.downloads)
return chrome.downloads.download(options, callback);
callback();
}
function getVimeoLinks(videoId, callback)
{
getVimeoNoEmbedLinks(videoId, function(links, title, thumb){
if(links)
{
callback(links, title, thumb);
return;
}
getVimeoEmbedLinks(videoId, callback);
});
}
function getVimeoEmbedLinks(videoId, callback)
{
sendRequest('http://player.vimeo.com/video/' + videoId, function(r){
if(r.status == 200 && r.responseText)
{
var config = r.responseText.match(/,c\s*=\s*(\{[\s\S]+?\})\s*;/i);
if(config && config.length > 1)
{
config = config[1];
var data = getVimeoDataFromConfig(config);
if(data && data.links)
{
callback(data.links, data.title, data.thumb);
return;
}
}
}
callback(null, '', '');
});
}
function getVimeoNoEmbedLinks(videoId, callback)
{
sendRequest('http://vimeo.com/' + videoId, function(r){
if(r.status == 200 && r.responseText)
{
var configUrl = r.responseText.match(
/data-config-url=[\"']([^\s\"'\<\>]+)/i);
if(configUrl && configUrl.length > 1)
{
configUrl = configUrl[1].replace(/&amp;/ig, '&');
sendRequest(configUrl, function(r){
if(r.status == 200 && r.responseText)
{
var data = getVimeoDataFromConfig(r.responseText);
if(data && data.links)
{
callback(data.links, data.title, data.thumb);
return;
}
}
callback(null, '', '');
});
return;
}
}
callback(null, '', '');
});
}
function getVimeoDataFromConfig(config)
{
config = config.replace(/(\{|,)\s*(\w+)\s*:/ig, '$1"$2":').
replace(/(:\s+)\'/g, '$1"').replace(/\'([,\]\}])/g, '"$1');
try
{
config = JSON.parse(config);
}
catch(err)
{
return null;
}
if(!config || !config.request || !config.video ||
!config.request.files || !config.request.files.codecs.length)
{
return null;
}
var r = config.request, v = config.video, data = {};
data.title = v.title ? v.title : '';
if(v.thumbs)
{
for(i in v.thumbs)
{
data.thumb = v.thumbs[i];
break;
}
}
data.links = [];
var codecs = r.files.codecs;
for(var k = 0; k < codecs.length; k++)
{
var files = r.files[codecs[k]];
if(files)
{
for(var i in files)
{
var name = i.length <= 3 ? i.toUpperCase() :
ucfirst(i.toLowerCase());
var ext = files[i].url.match(/\.(\w{2,4})(?:\?|#|$)/i);
if(ext && ext.length > 1)
ext = ext[1].toLowerCase();
else
ext = 'mp4';
data.links.push({
url: files[i].url,
name: name,
type: ext,
ext: ext.toUpperCase()
});
}
}
}
return data;
}
function getVkFlvLink(v)
{
if(v.host.search(/^https?:\/\//i) != -1)
{
if(v.host.charAt(v.host.length - 1) != '/')
v.host += '/';
if(v.host.search(/^https?:\/\/cs\d+\./i) != -1)
return v.host + 'u' + v.uid + '/videos/' + v.vtag + '.flv';
return v.host + 'assets/video/' + v.vtag + v.vkid + '.vk.flv';
}
if(v.host.search(/\D/) == -1)
return 'http://cs' + v.host + '.' + 'vk.com/u' + v.uid + '/videos/' + v.vtag + '.flv';
return 'http://' + v.host + '/assets/video/' + v.vtag + v.vkid + '.vk.flv';
}
function getVkMp4Link(v, q)
{
if(q == 240 && v.no_flv == 0)
return getVkFlvLink(v);
if(v.host.search(/^https?:\/\//i) != -1)
{
if(v.host.charAt(v.host.length - 1) != '/')
v.host += '/';
return v.host + 'u' + v.uid + '/videos/' + v.vtag + '.' + q + '.mp4';
}
return 'http://cs' + v.host + '.' + 'vk.com/u' + v.uid + '/videos/' + v.vtag + '.' + q + '.mp4';
}
function getVkVideoLinks(v)
{
if(!v || !v.host || !v.vtag || (!v.vkid && !v.uid))
return null;
if(typeof(v.host) != 'string' && v.host.toString)
v.host = v.host.toString();
v.host = v.host.replace(/\\\//g, '/');
if(v.hd > 0 && (!v.hd_def || v.hd > v.hd_def))
v.hd_def = v.hd;
var links = [];
if(v.hd_def <= 0 && v.no_flv == 0)
{
links.push({
url: getVkFlvLink(v),
name: 'FLV',
subname: '',
type: 'flv'
});
}
else
{
links.push({
url: getVkMp4Link(v, 240),
name: (v.no_flv == 0) ? 'FLV' : 'MP4',
subname: '',
type: (v.no_flv == 0) ? 'flv' : 'mp4'
});
if(v.hd_def > 0)
{
links.push({
url: getVkMp4Link(v, 360),
name: 'MP4',
subname: '360',
type: 'mp4'
});
if(v.hd_def > 1)
{
links.push({
url: getVkMp4Link(v, 480),
name: 'MP4',
subname: '480',
type: 'mp4'
});
if(v.hd_def > 2)
{
links.push({
url: getVkMp4Link(v, 720),
name: 'MP4',
subname: '720',
type: 'mp4'
});
}
}
}
}
return links;
}
function getVKLinks(videoId, callback)
{
var links = [], title = videoId, duration = '', thumb = '', data = null, embed = null;
var vid = videoId;
if(vid.search(/^video-?\d+_\d+/i) == -1)
{
var oid = '', id = '';
var m = vid.match(/(?:^|&)oid=(-?\d+)/i);
if(m && m.length > 1)
oid = m[1];
m = vid.match(/(?:^|&)id=(-?\d+)/i);
if(m && m.length > 1)
id = m[1];
vid = '';
if(oid && id)
vid = 'video' + oid + '_' + id;
}
if(!vid)
{
callback(vid, links, title);
return;
}
title = vid;
var url = 'http://vk.com/' + vid;
sendRequest(url, function(r){
try
{
if(r.status == 200 && r.responseText)
{
var json = r.responseText
.replace(/\{[a-zA-Z_\-\.]+\}/ig, '')
.match(/var vars\s*=\s*(\{[^\}]+\})/i);
if(json)
{
try
{
json = json[1];
if(json.search(/^\{\s*\\\"/) > -1)
json = json.replace(/\\\"/g, '"');
json = JSON.parse(json);
if(json)
{
data = json;
links = getVkVideoLinks(json);
if(json.md_title)
title = json.md_title;
if(json.thumb)
thumb = json.thumb;
else if(json.jpg)
thumb = json.jpg;
if(thumb && thumb.search(/\\\//) > -1)
thumb = thumb.replace(/\\\//g, '/');
}
}
catch(err){}
}
else
{
var frame = r.responseText.match(/<iframe[^>]+>/ig), m;
if(frame)
{
for(var i=0, l=frame.length; i<l; i++)
{
if(m = frame[i].match(/youtube.com\\?\/embed\\?\/([\w\-]+)/i))
{
embed = {
action: 'getYoutubeLinks',
extVideoId: m[1]
};
break;
}
if(m = frame[i].match(/vimeo.com\\?\/video\\?\/(\d+)/i))
{
embed = {
action: 'getVimeoLinks',
extVideoId: m[1]
};
break;
}
}
}
if (embed === null) {
var ajaxPreload = r.responseText.lastIndexOf('ajax.preload');
if (ajaxPreload !== -1) {
var data = r.responseText.substr(ajaxPreload);
var dmId = data.match(/url: '(?:[\w\\/]+.)?dailymotion.com(?:\\\/swf)?\\\/video\\\/([\w\d]+)\??/);
if (dmId) {
embed = {
action: 'getDailymotionLinks',
extVideoId: dmId[1]
}
}
}
}
}
var dur = r.responseText.match(/(['"]?)duration\1\s*:\s*(\d+)/i);
if(dur)
{
duration = dur[2];
}
}
}
finally
{
callback(vid, links, title, duration, thumb, data, embed);
}
});
}
function checkVkLinks(links, callback)
{
var checkUrl = '';
if(links && links.length > 0)
{
if(links[0].type == 'mp4')
checkUrl = links[0].url;
else if(links.length > 1)
checkUrl = links[1].url;
else
checkUrl = links[0].url;
}
if(checkUrl)
{
getFileSize(checkUrl, function(r){
var isValid = (r.status >= 400) ? false : true;
callback(checkUrl, isValid, r.status);
});
return;
}
callback();
}
function getYoutubeLinks(eurl, videoId, checkSubtitles, callback_) {
var links = null, title = '', duration = '';
eurl = encodeURIComponent(eurl);
var url = 'http://www.youtube.com/get_video_info?video_id=' + videoId +
'&asv=3&eurl=' + eurl + '&el=info&sts=15956';
var cookies = 'VISITOR_INFO1_LIVE=; PREF=; GEO=; use_hitbox=';
var embed = true;
var callback = function(links, title, subtitles, duration) {
if(links || !embed)
{
callback_(links, title, subtitles, duration);
}
else
{
embed = false;
url = 'http://www.youtube.com/watch?v=' + videoId;
sendRequest(url, getYoutubeLinks_, '', url, '', cookies);
}
};
sendRequest(url, getYoutubeLinks_, '', url, '', cookies);
function getYoutubeLinks_(r) {
var cb = function() {
if(checkSubtitles)
{
checkYoutubeSubtitles(videoId, function(subtitles){
callback(links, title, subtitles, duration);
});
}
else
callback(links, title, null, duration);
};
if (r.status !== 200 || !r.responseText) {
return cb();
}
var dashUrl;
try {
var getParam = function(str, param, number) {
var re = new RegExp('(?:^|&)' + param + '=([^\\s\\&\\"]+)', 'i');
if(!embed)
{
re = new RegExp('\\"' + param + '\\"\\s*:\\s*\\"([^\\"]+)\\"', 'i');
if(number)
re = new RegExp('\\"' + param + '\\"\\s*:\\s*\\"?(\\d+)', 'i');
}
var m = str.match(re);
if(m && m.length > 1)
{
if(embed)
return decodeURIComponent(m[1]);
var json = '{"v": "' + m[1] + '"}';
var obj = JSON.parse(json);
if(obj && obj.v)
return obj.v;
}
return '';
};
var baseUrl = '',
adaptiveFmts = getParam(r.responseText, 'adaptive_fmts'),
title = getParam(r.responseText, 'title'),
length_seconds = getParam(r.responseText, 'length_seconds', true),
fmtMap = getParam(r.responseText, '(?:fmt_url_map|url_encoded_fmt_stream_map)');
dashUrl = getParam(r.responseText, 'dashmpd');
if(!embed)
fmtMap = fmtMap.split('\\u0026').join('&');
if(fmtMap.search(/url%3dhttp/i) > -1)
fmtMap = decodeURIComponent(fmtMap);
var titleParam = '';
if(title)
{
title = title.replace(/\+/g, '%20');
title = decodeURIComponent(title).
replace(/[\x2F\x5C\x3A\x7C]/g, '-').
replace(/[\x2A\x3F]/g, '').
replace(/\x22/g, '\'').
replace(/\x3C/g, '(').
replace(/\x3E/g, ')').
replace(/(?:^\s+)|(?:\s+$)/g, '');
titleParam = '&title=' + encodeURIComponent(title);
}
if(length_seconds)
duration = length_seconds;
var lks = parseYoutubeFmtMap(fmtMap, titleParam, baseUrl);
if(adaptiveFmts)
{
var adaptive_links = parseYoutubeFmtMap(adaptiveFmts, titleParam, baseUrl);
for (var i in adaptive_links) {
if(!lks[i])
lks[i] = adaptive_links[i];
}
}
// Deprecated
// findYoutubeAvailableLinks(lks, baseUrl, dashUrl, adaptiveFmts, titleParam);
if(lks)
links = lks;
}
finally {
getYouTubeDashLinks(links, dashUrl, function(_links) {
if (_links) {
links = _links;
}
cb();
});
}
}
}
var getYouTubeDashLinks = (function() {
var parseDash = function(xml, links, cb) {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xml,"text/xml");
var elList = xmlDoc.querySelectorAll('Representation');
if (!links) {
links = {};
}
for (var i = 0, el; el = elList[i]; i++) {
var itag = el.id;
if (links[itag] !== undefined) {
continue;
}
var baseurl = el.querySelector('BaseURL');
if (baseurl === null) {
continue;
}
var url = baseurl.textContent;
links[itag] = url;
}
cb(links);
};
var _getDashLinks = function(links, dashmpd, cb) {
if (!dashmpd) {
return cb();
}
var signature_pos = dashmpd.indexOf('signature');
if (signature_pos === -1) {
var s_pos = dashmpd.indexOf('/s/');
if (s_pos === -1) {
return cb();
}
s_pos += 3;
var s_end = dashmpd.indexOf('/', s_pos);
if (s_end === -1) {
s_end = dashmpd.length;
}
var s = dashmpd.substr( s_pos, s_end - s_pos );
var signature = youtubeSignatureDecipher(s);
if (signature === s) {
return cb();
}
dashmpd = dashmpd.substr(0, s_pos - 2) + 'signature/' + signature + dashmpd.substr(s_end);
}
sendRequest(dashmpd, function(r) {
if(r.status !== 200) {
return cb();
}
parseDash(r.responseText, links, cb);
});
};
return _getDashLinks;
})();
function youtubeSignatureDecipher(sig)
{
function swap(a, b)
{
var t = a[0];
a[0] = a[b % a.length];
a[b] = t;
}
var s = sig.split('');
swap(s, 43);
swap(s, 2);
swap(s, 54);
s = s.reverse();
swap(s, 8);
s = s.slice(1);
return s.join('');
}
function checkYoutubeLinks(links, callback)
{
var checkUrl = '';
var checkItags = ['18', '34', '35'], checkUrl = '';
for(var i = 0; i < checkItags.length; i++)
{
if(links[checkItags[i]])
{
checkUrl = links[checkItags[i]];
break;
}
}
if(checkUrl)
{
getFileSize(checkUrl, function(r){
var isValid = (r.status >= 400) ? false : true;
callback(checkUrl, isValid, r.status);
});
return;
}
callback();
}
function findYoutubeAvailableLinks(links, baseUrl, dashUrl, adaptiveFmts, titleParam)
{
if(!baseUrl || !dashUrl || !adaptiveFmts)
return;
var dashQuery = getYoutubeDashQuery(dashUrl);
if(!dashQuery)
return;
var itags = getYoutubeAdaptiveFtmItags(adaptiveFmts);
if(!itags)
return;
var map = {
'133': ['5'], // 240
'134': ['34', '18', '43'], // 360
'135': ['35', '44'], // 480
'136': ['22', '45'], // 720
'137': ['37', '46'], // 1080
'138': ['38'] // 4k
};
for(var i = 0; i < itags.length; i++)
{
if(map[itags[i]])
{
for(var j = 0; j < map[itags[i]].length; j++)
{
var itag = map[itags[i]][j];
if(!links[itag])
{
links[itag] = baseUrl + dashQuery + '&itag=' + itag + titleParam;
}
}
}
}
}
function parseYoutubeFmtMap(fmtMap, titleParam, baseUrl)
{
if(!fmtMap)
return;
var l = {};
fmtMap = fmtMap.split(',');
for(var i = 0; i < fmtMap.length; ++i)
{
var query = parseQuery(fmtMap[i]);
if(query.url)
{
query.url = decodeURIComponent(query.url);
if(query.url.search(/(\?|&)sig(nature)?=/i) == -1)
{
if(query.sig)
query.url += '&signature=' + query.sig;
else if(query.signature)
query.url += '&signature=' + query.signature;
else if(query.s)
query.url += '&signature=' + youtubeSignatureDecipher(query.s);
}
if(query.url.search(/(\?|&)itag=/i) == -1)
{
if(query.itag)
query.url += '&itag=' + query.itag;
}
var fmt = query.url.match(/(?:\?|&)itag=(\d+)/i);
if(fmt && fmt.length > 1)
{
fmt = fmt[1];
query.url = query.url.replace(/(\?|&)sig=/i, '$1signature=').
replace(/\\u0026/ig, '&').replace(/\\\//g, '/');
l[fmt] = query.url;
if(titleParam)
l[fmt] += titleParam;
if(!baseUrl)
{
var m = query.url.match(/^(https?:\/\/[^\?]+\?)/);
if(m && m.length > 1)
baseUrl = m[1];
}
}
}
}
return l;
}
function getYoutubeDashQuery(dashUrl)
{
if(!dashUrl)
return '';
var u = dashUrl.replace(/^.+\/api\/manifest\/dash\//i, '');
if(u == dashUrl)
return '';
u = u.split('/');
if(!u || u.length < 2)
return '';
var query = {};
for(var i = 0; i < u.length - 1; i += 2)
{
if(u[i] != 'itag')
{
u[i] = decodeURIComponent(u[i]);
u[i + 1] = decodeURIComponent(u[i + 1]);
if(u[i] == 's')
{
u[i] = 'signature';
u[i + 1] = youtubeSignatureDecipher(u[i + 1]);
}
else if(u[i] == 'sig')
{
u[i] = 'signature';
}
else if(u[i] == 'sparams' && u[i + 1].search(/(^|,|%2C)itag(^|,|%2C)/i))
{
return '';
}
query[u[i]] = u[i + 1];
}
}
if(!query.signature)
return '';
query.ratebypass = 'yes';
return getQueryString(query);
}
function getYoutubeAdaptiveFtmItags(adaptiveFmts)
{
if(!adaptiveFmts)
return;
var itags = [];
adaptiveFmts = adaptiveFmts.split('\\u0026').join('&');
u = adaptiveFmts.split(',');
for(var i = 0; i < u.length; ++i)
{
var q = parseQuery(u[i]);
var itag = 0;
if(q.url)
{
q.url = decodeURIComponent(q.url);
var m = q.url.match(/(?:\?|&)itag=(\d+)/i);
if(m && m.length > 1)
itag = m[1];
}
if(!itag && q.itag)
itag = q.itag;
if(itag)
itags.push(itag);
}
return itags;
}
function checkYoutubeSubtitles(videoId, callback)
{
var url = 'http://video.google.com/timedtext?hl=en&v=' + videoId +
'&type=list&tlangs=1';
sendRequest(url, function(r){
var result = false;
if(r.status == 200 && r.responseXML)
{
var doc = r.responseXML;
if(doc.getElementsByTagName &&
(doc.getElementsByTagName('TARGET').length || doc.getElementsByTagName('TRACK').length))
{
result = true;
}
}
callback(result);
});
}
function getOdnoklassnikiLinks(extVideoId, callback)
{
if(!extVideoId)
{
callback(null);
return;
}
var url = 'http://in.video.mail.ru/cgi-bin/video/oklite?eid=' + extVideoId;
sendRequest(url, function(r){
if(r.status == 200 && r.responseText)
{
var u = 'http://www.okcontent.video.mail.ru/media/';
var host = r.responseText.match(/\$vcontentHost=([^\s\"'\<\>]+)/i);
if(host && host.length > 1)
u = 'http://' + host[1] + '/media/';
u += extVideoId;
var links = [];
links.push({
url: u + '-v.mp4',
name: 'SD',
ext: 'FLV'
});
if(r.responseText.search(/\$HDexist=1/i) > -1)
{
links.push({
url: u + '-hv.mp4',
name: 'HD',
ext: 'MP4'
});
}
if(links)
{
callback(links);
return;
}
}
callback(null);
}, '', url);
}
function getOdnoklassnikiAudioLinks(pageUrl, trackId, jsessionId, callback)
{
if(!trackId || !jsessionId)
{
callback(null);
return;
}
var url = 'http://wmf1.odnoklassniki.ru/play;jsessionid=' + jsessionId +
'?tid=' + trackId + '&';
sendRequest(url, function(r){
var data = null;
if(r.status == 200 && r.responseText)
{
data = JSON.parse(r.responseText);
}
callback(data);
}, '', url);
}
function getSoundcloudTrackInfo(trackUrl, client_id, callback)
{
if(!trackUrl || !client_id)
{
callback(null);
return;
}
var url = 'http://api.soundcloud.com/resolve.json?url=' + trackUrl +
'&client_id=' + client_id;
sendRequest(url, function(r){
var data = null;
if(r.status < 400 && r.responseText)
{
var data = JSON.parse(r.responseText);
if(!data)
data = r.responseText;
}
checkSoundcloudLinks(data, client_id, callback);
}, '', url);
}
function checkSoundcloudLinks(data, client_id, cb) {
if (!data) {
return cb();
}
var info = data;
if(info.kind !== 'track' && info.tracks && info.tracks.length === 1)
info = info.tracks[0];
if(info.kind === 'track' && info.stream_url) {
validateSoundcloudTrackUrl(info.stream_url, client_id, function (isValid) {
cb(data, isValid);
});
return;
}
if (info.tracks) {
validateSoundcloudTrackUrl(info.tracks[0].stream_url, client_id, function(isValid) {
cb(data, isValid);
});
return;
}
return cb(data);
}
function validateSoundcloudTrackUrl(url, client_id, cb) {
url += (url.indexOf('?') === -1) ? '?' : '&';
url += 'client_id=' + client_id;
sendRequest(url, function(r) {
cb(r.status === 200);
}, 'HEAD');
}
var getDailymotionLinks = (function() {
var readLink = function(url) {
url = url.replace(/\\\//g, '/');
url = url.replace(/\@\@[\w\-]+$/, '');
var size = '';
var t = url.match(/\/cdn\/\w+\-(\d+x\d+)\//i);
if(t && t.length > 1)
{
size = t[1];
}
else
{
t = url.match(/\D(\d+x\d+)\D/i);
if(t && t.length > 1)
{
size = t[1];
}
}
var ext = 'FLV';
t = url.match(/\.(\w{1,6})(?:$|\?)/);
if(t && t.length > 1)
{
ext = t[1].toUpperCase();
}
if(size !== '80x60')
{
var height = parseInt(size.split('x').slice(-1)[0]);
return {url: url, name: ext+' '+height, ext: ext, info_url: '', height: height};
}
};
var getLinks = function(text, cb)
{
var about = {};
var links = [];
var info = text.match(/(?:var|,)\s*info\s*=\s*\{(.*?)\}\s*(?:;|,\s*\w+\s*=)/i);
if(!info || info.length < 2) {
return cb();
}
info = info[1];
try {
info = JSON.parse('{' + info + '}');
if(!info) {
return cb();
}
about.title = info.title;
about.duration = info.duration;
about.thumb = info.thumbnail_medium_url;
for(var i in info)
{
if (!info.hasOwnProperty(i)) {
continue;
}
if (!info[i]) {
continue;
}
if(info[i].search(/^https?:\/\/[^\s\"]+\.(mp4|flv)(\?|$)/) > -1)
{
var link = readLink(info[i]);
if (link !== undefined) {
links.push(link);
}
}
}
} catch(e){}
if (links.length > 0) {
about.links = links;
}
cb(about);
};
var getEmbedVideoInfo = function (id, callback) {
var url = "http://www.dailymotion.com/embed/video/" + id;
sendRequest(url, function(r) {
if(r.status !== 200) {
return callback();
}
getLinks(r.responseText, callback);
});
};
return getEmbedVideoInfo;
})();
function parseQuery(query)
{
var k = {};
var re = /[?&]?([^=]+)(?:=([^&]*))?/g;
while(m = re.exec(query))
{
if(m[1] && m[2])
k[m[1]] = m[2];
else if(m[1])
k[m[1]] = '';
};
return k;
}
function getQueryString(query, key_prefix, key_suffix)
{
if(!query || typeof(query) != 'object')
return '';
if(key_prefix === undefined)
key_prefix = '';
if(key_suffix === undefined)
key_suffix = '';
var str = '';
for(key in query)
{
if(str.length)
str += '&';
if(query[key] instanceof Object)
{
if(!key_prefix)
key_prefix = '';
if(!key_suffix)
key_suffix = '';
str += getQueryString(query[key], key_prefix + key + "[", "]" + key_suffix);
}
else
str += key_prefix + escape(key) + key_suffix + '=' + escape(query[key]);
}
return str;
}
function ucfirst(str)
{
if(str.length)
str = str.charAt(0).toUpperCase() + str.slice(1);
return str;
}
function userTrack() {
var now = Date.now();
if (GM_getValue('trackTime') > now) {
return;
}
GM_setValue('trackTime', now + 86400000);
dblCheck(function() {
sendScreenViewStats('init');
});
}
function dblCheck(cb) {
var dblTrack = GM_getValue('dblTrack');
var dataList = (dblTrack)?dblTrack.split(','):'';
var now = Date.now();
if (dataList && dataList[1] > now) {
return;
}
var uuid = generateUuid();
var expire = now + 60000;
GM_setValue('dblTrack', uuid+','+expire);
setTimeout(function() {
var dblTrack = GM_getValue('dblTrack');
var dataList = (dblTrack)?dblTrack.split(','):'';
if (dataList[0] !== uuid) {
return;
}
cb();
}, 5000);
}
function sendScreenViewStats(screenName) {
var params = {
an: 'helper',
aid: 'userjs-' + helper,
av: chrome.app.getDetails().version,
t: 'screenview',
cd: screenName
};
sendStatsInfo(params);
}
function sendStatsInfo(params) {
if(!params.t)
return;
var def = {
v: 1,
tid: 'UA-7055055-5',
cid: getUuid(),
//ul: chrome.i18n.getMessage("lang")
};
for (var i in def) {
if(!params[i])
params[i] = def[i];
}
sendRequest('https://www.google-analytics.com/collect',
function(r){}, 'POST', '',
getQueryString(params)
);
}
function getUuid() {
var uuid = GM_getValue('uuid');
if (uuid) {
return uuid;
}
uuid = generateUuid();
GM_setValue('uuid', uuid);
return uuid;
}
function generateUuid()
{
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
fixPref([
{name: 'button', check: '0', def: '1'},
{name: 'moduleVimeo', check: '0', def: '1'},
{name: 'moduleFacebook', check: '0', def: '1'},
{name: 'moduleSoundcloud', check: '0', def: '1'},
{name: 'ytHideFLV', check: '1', def: '0'},
{name: 'ytHideMP4', check: '1', def: '0'},
{name: 'ytHideWebM', check: '0', def: '1'},
{name: 'ytHide3GP', check: '0', def: '1'},
{name: 'ytHide3D', check: '0', def: '1'},
{name: 'ytHideMP4NoAudio', check: '0', def: '1'},
{name: 'ytHideAudio_MP4', check: '0', def: '1'},
{name: 'vkShowBitrate', check: '1', def: '0'}
]);
};
/////////////////////////////////////////////////
// UTILS
SaveFrom_Utils = {
downloadParam: 'sfh--download',
prefs: {},
initModule: function(name, callback)
{
var request = {
action: 'initModule',
moduleName: name,
frame: (window.top != window.self)
};
callback = callback || function(){};
chrome.extension.sendRequest(request, callback);
},
runModule: function(response, module)
{
if (!response)
return;
this.prefs = response;
//console.log('moduleEnable', response.moduleEnable, module)
if(response.name == 'savefrom')
module.run();
else if (response.moduleEnable)
module.run();
},
trim: function(str)
{
return str.replace(/^\s+|\s+$/g, '');
},
nextSibling: function(obj)
{
var next = obj;
do
{
next = next.nextSibling;
if(next)
{
if(next.nodeType == 1)
return next;
if(next.nodeType == 9)
break;
}
}
while(next);
return null;
},
setStyle: function(node, style)
{
if(!node || !style)
return;
for(var i in style)
node.style[i] = style[i];
},
getStyle: function(node, property)
{
var s = undefined;
if(!node)
return undefined;
if(node.currentStyle)
{
property = property.replace(/-(w)/g, function(s, m){return m.toUpperCase()});
return node.currentStyle[property];
}
if(window.getComputedStyle)
return window.getComputedStyle(node, null).getPropertyValue(property);
return undefined;
},
addStyleRules: function(selector, rules)
{
var style = document.getElementById('savefrom-styles');
if(!style)
{
style = document.createElement('style')
style.id = 'savefrom-styles';
// maybe need for safari
//style.appendChild(document.createTextNode(""));
var s = document.querySelector('head style');
if(s)
// allow to override our styles
s.parentNode.insertBefore(style, s);
else
document.querySelector('head').appendChild(style);
}
if(typeof(rules) == 'object') {
var r = [];
for(var i in rules)
r.push(i + ':' + rules[i]);
rules = r.join(';');
}
style.sheet.addRule(selector, rules);
},
getPosition: function(node)
{
var box = node.getBoundingClientRect();
return {
top: Math.round(box.top + window.pageYOffset),
left: Math.round(box.left + window.pageXOffset)
}
},
getSize: function(node)
{
return {width: node.offsetWidth, height: node.offsetHeight};
},
getMatchFirst: function(str, re)
{
var m = str.match(re);
if(m && m.length > 1)
return m[1];
return '';
},
getElementByIds: function(ids)
{
for(var i = 0; i < ids.length; i++)
{
var node = document.getElementById(ids[i]);
if(node)
return node;
}
return null;
},
hasClass: function(node, name)
{
if(!node || !node.className || name == '')
return false;
if(node.className == name)
return true;
var re = new RegExp("(^|\\s+)" + name + "(\\s+|$)");
if(node.className.search(re) != -1)
return true;
return false;
},
addClass: function(node, name)
{
if(!this.hasClass(node, name))
{
var c = node.className;
if(c)
node.className = c + ' ' + name;
else
node.className = name;
}
},
removeClass: function(node, name)
{
if(!this.hasClass(node, name))
return;
var re = new RegExp("(^|\\s+)" + name + "(\\s+|$)");
node.className = node.className.replace(re, function(t, s1, s2){
if(s1 && s2)
return ' ';
return '';
});
},
matchesSelector: function(node, selector)
{
if(node.matchesSelector)
return node.matchesSelector(selector);
if(node.webkitMatchesSelector)
return node.webkitMatchesSelector(selector);
var nodes = node.parentNode.querySelectorAll(selector);
for(var i = 0; i < nodes.length; ++i)
{
if(nodes[i] == node)
return true;
}
return false;
},
getParentByClass: function(node, name)
{
if(!node || name == '')
return false;
if(typeof(name) == 'object' && name.length > 0)
{
for(var parent = node; parent; parent = parent.parentNode)
{
for(var i = 0; i < name.length; i++)
{
if(this.hasClass(parent, name[i]))
return parent;
}
}
}
else
{
for(var parent = node; parent; parent = parent.parentNode)
{
if(this.hasClass(parent, name))
return parent;
}
}
return null;
},
isParent: function(node, testParent)
{
for(var parent = node; parent; parent = parent.parentNode)
{
if (parent == testParent)
return true;
}
return false;
},
emptyNode: function(node)
{
while(node.firstChild)
node.removeChild(node.firstChild);
},
download: function(filename, url, options, callback, iframe)
{
if(!url)
return false;
filename = filename || this.getFileName(url);
if(!filename)
return false;
if (!this.prefs || !this.prefs.downloads) {
if (iframe && this.downloadCheckProtocol(url)) {
var src = this.getMatchFirst(url, /(^https?:\/\/[^\/]+)/);
if(src == location.protocol + '//' + location.host) {
var a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
this.click(a);
setTimeout(function(){
a.parentNode.removeChild(a);
}, 100);
}
else {
var params = {url: url, filename: filename};
params = encodeURIComponent(JSON.stringify(params));
src += '/404?#' + this.downloadParam + '=' + params;
var f = document.createElement('iframe');
f.src = src;
this.setStyle(f, {
width: 0,
height: 0,
overflow: 'hidden'
});
document.body.appendChild(f);
setTimeout(function(){
f.parentNode.removeChild(f);
}, 3000);
}
return true;
}
return false;
}
var params = options || {};
params.url = url;
params.filename = filename;
var request = {
action: 'downloadFile',
options: params
};
callback = callback || function(){};
chrome.extension.sendRequest(request, callback);
return true;
},
downloadCheckProtocol: function(url) {
if(location.protocol == 'http:') {
return true;
}
if(!url) {
return false;
}
url = url.toLowerCase();
if(location.protocol == url.substr(0, location.protocol.length)) {
return true;
}
return false;
},
downloadLink: function(a, callback, iframe)
{
if(!a.href)
return false;
var filename = a.getAttribute('download');
return this.download(filename, a.href, null, callback, iframe);
},
downloadOnClick: function(event, callback, iframe)
{
var _this = SaveFrom_Utils;
var node = event.target;
if(node.tagName != 'A')
node = node.parentNode;
if ( !(_this.prefs && _this.prefs.downloads) &&
!(iframe && node.href && _this.downloadCheckProtocol(node.href)) ) {
return;
}
if(event.button == 2)
return;
event.preventDefault();
event.stopPropagation();
_this.downloadLink(node, callback, iframe);
},
click: function(node, ctrlKey, altKey, shiftKey, button)
{
if(!node)
return;
if(!ctrlKey)
ctrlKey = false;
if(!altKey)
altKey = false;
if(!shiftKey)
shiftKey = false;
if(!button)
button = 0;
var e = document.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
ctrlKey, altKey, shiftKey, false, button, null);
node.dispatchEvent(e);
},
parseQuery: function(query)
{
var k = new Array();
var re = /[?&]?([^=]+)(?:=([^&]*))?/g;
while(m = re.exec(query))
{
if(m[1] && m[2])
k[m[1]] = m[2];
else if(m[1])
k[m[1]] = '';
};
return k;
},
getQueryString: function(query, key_prefix, key_suffix)
{
if(!query || typeof(query) != 'object')
return '';
if(key_prefix === undefined)
key_prefix = '';
if(key_suffix === undefined)
key_suffix = '';
var str = '';
for(key in query)
{
if(str.length)
str += '&';
if(query[key] instanceof Object)
{
if(!key_prefix)
key_prefix = '';
if(!key_suffix)
key_suffix = '';
str += getQueryString(query[key], key_prefix + key + "[", "]" + key_suffix);
}
else
str += key_prefix + escape(key) + key_suffix + '=' + escape(query[key]);
}
return str;
},
md5: function(str)
{
// http://kevin.vanzonneveld.net
// + original by: Webtoolkit.info (http://www.webtoolkit.info/)
// + namespaced by: Michael White (http://getsprink.com)
// + tweaked by: Jack
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + input by: Brett Zamir (http://brett-zamir.me)
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// - depends on: utf8_encode
// * example 1: md5('Kevin van Zonneveld');
// * returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
var xl;
var rotateLeft = function (lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
};
var addUnsigned = function (lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
};
var _F = function (x, y, z) {
return (x & y) | ((~x) & z);
};
var _G = function (x, y, z) {
return (x & z) | (y & (~z));
};
var _H = function (x, y, z) {
return (x ^ y ^ z);
};
var _I = function (x, y, z) {
return (y ^ (x | (~z)));
};
var _FF = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var _GG = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var _HH = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var _II = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var convertToWordArray = function (str) {
var lWordCount;
var lMessageLength = str.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = new Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
};
var wordToHex = function (lValue) {
var wordToHexValue = "",
wordToHexValue_temp = "",
lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
wordToHexValue_temp = "0" + lByte.toString(16);
wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
}
return wordToHexValue;