1. Greasemonkey Emulation

Emulate the Greasemonkey GM_* functions for other browsers.

  1. // ==UserScript==
  2. // @run-at document-start
  3. // @name 1. Greasemonkey Emulation
  4. // @description Emulate the Greasemonkey GM_* functions for other browsers.
  5. // @version 2.0
  6. // @author Lil Devil
  7. // @attribution based on version 1.4.5 by ale5000 http://userscripts.org/scripts/show/88932
  8. // @namespace http://www.lildevil.org/greasemonkey/
  9. // @include http://*
  10. // @include https://*
  11. // @filename aab-greasemonkey-emulation.user.js
  12. // @filename-IE aab-greasemonkey-emulation.ieuser.js
  13. // @filename-opera aab-greasemonkey-emulation.js
  14. // @uniquescriptname greasemonkey_emulation
  15. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  16. // ==/UserScript==
  17.  
  18.  
  19.  
  20. (function()
  21. {
  22. // Settings, can be changed
  23. var enable_GM_registerMenuCommand = true,
  24. override_GM_registerMenuCommand = false,
  25. show_global_config_menu_item = false,
  26. enable_opera_scriptStorage = true,
  27. use_alert_as_fallback = true;
  28.  
  29. // Internal variables, do not change
  30. var version = "2.0";
  31. var unique_script_name = "greasemonkey_emulation";
  32.  
  33. var opera_obj = window.opera, hostname = location.hostname;
  34. var rnd = ( Math.floor(Math.random() * 100) + 1 );
  35. var chrome = (navigator.userAgent.indexOf("Chrome") != -1), midori = (navigator.userAgent.indexOf("Midori") != -1);
  36. var unsfw = null, storage = null, storage_used = false, cross_domain_values = false, opera_script_storage_active = false;
  37. if(opera_obj && enable_opera_scriptStorage) // http://www.opera.com/docs/userjs/specs/#scriptstorage
  38. {
  39. try { storage = opera_obj.scriptStorage; opera_script_storage_active = true; } catch(e) {}
  40. }
  41. if(!storage)
  42. {
  43. opera_script_storage_active = false;
  44.  
  45. if(window.localStorage)
  46. {
  47. storage = localStorage;
  48. if(opera_obj) opera_obj.postError("Go on \"opera:config#PersistentStorage|UserJSStorageQuota\" and set a quota different from 0 like for example 5120 to enable window.opera.scriptStorage");
  49. }
  50. else if(window.globalStorage)
  51. storage = globalStorage[hostname];
  52. }
  53. if((typeof unsafeWindow) != "undefined") unsfw = unsafeWindow; else { unsfw = window; unsafeWindow = unsfw; }
  54.  
  55. var base_obj, userscripts;
  56. var default_toString = function(){ return undefined; };
  57. if(opera_obj) base_obj = opera_obj; else base_obj = window;
  58.  
  59. if((typeof base_obj.userscripts) == "undefined")
  60. {
  61. userscripts = new Object();
  62. userscripts.toString = default_toString;
  63. base_obj.userscripts = userscripts;
  64. if(!opera_obj && !unsfw.userscripts) unsfw.userscripts = userscripts;
  65. }
  66. else
  67. userscripts = base_obj.userscripts;
  68.  
  69. if(userscripts.GME) { userscripts.GME.GM_log("Double execution. Browser bug!!!"); return; }
  70. // https://bugs.launchpad.net/midori/+bug/707166
  71.  
  72. userscripts.GME = new Object();
  73. var gm_extensions = userscripts.GME;
  74.  
  75. if((typeof GM_log) != "undefined") // Firefox
  76. gm_extensions.GM_log = GM_log;
  77. else
  78. {
  79. var opera_postError = null, pro_log_present = false, console_enabled = false;
  80. if(opera_obj) opera_postError = opera_obj.postError;
  81. else if((typeof PRO_log) != "undefined") pro_log_present = true;
  82. else if((typeof console) == "object") console_enabled = true;
  83.  
  84. gm_extensions.GM_log = function(message, displayed_script_name)
  85. {
  86. if(displayed_script_name != undefined) message = displayed_script_name + ":\n" + message;
  87.  
  88. if(opera_postError) // Opera
  89. opera_postError(message);
  90. else if(pro_log_present) // Internet Explorer
  91. PRO_log(message);
  92. else if(console_enabled) // Google Chrome - Midori
  93. try{ console.log(message); } catch(e){ if(use_alert_as_fallback) alert(message); }
  94. else if(use_alert_as_fallback) // Fallback to an alert if other methods fail
  95. alert(message);
  96. };
  97. }
  98.  
  99. var native_getsetvalues_functions = false, is_GM_deleteValue_bultin = false, is_GM_listValues_bultin = false;
  100. gm_extensions.GM_deleteValue = function(name, unique_script_name) { if(!name) return false; if(gm_extensions.GM_getValue(name, undefined, unique_script_name) === undefined) return; gm_extensions.GM_setValue(name, "", unique_script_name); try{ gm_extensions.GM_setValue(name, undefined, unique_script_name); } catch(e){} };
  101. gm_extensions.GM_listValues = function() { return []; }; // Dummy
  102. var get_full_name = function(name, unique_script_name) // unique_script_name is optional but recommended
  103. {
  104. if(unique_script_name != undefined)
  105. return "UserJS_" + unique_script_name + "_" + name;
  106. else
  107. return "UserJS__" + name;
  108. };
  109. if((typeof GM_setValue) != "undefined" && GM_setValue.toString().indexOf("not supported") == -1) // Firefox
  110. {
  111. cross_domain_values = true;
  112. native_getsetvalues_functions = true;
  113. var _GM_getValue = GM_getValue, _GM_setValue = GM_setValue, _GM_deleteValue = null, _GM_listValues = null;
  114. gm_extensions.GM_getValue = function(name, default_value, unique_script_name)
  115. {
  116. if(!name) return; return _GM_getValue(get_full_name(name, unique_script_name), default_value);
  117. };
  118. gm_extensions.GM_setValue = function(name, value, unique_script_name)
  119. {
  120. if(!name) return false; _GM_setValue(get_full_name(name, unique_script_name), value);
  121. };
  122. if((typeof GM_deleteValue) != "undefined")
  123. {
  124. is_GM_deleteValue_bultin = true;
  125. _GM_deleteValue = GM_deleteValue;
  126. gm_extensions.GM_deleteValue = function(name, unique_script_name)
  127. {
  128. if(!name) return false; _GM_deleteValue(get_full_name(name, unique_script_name));
  129. };
  130. }
  131. if((typeof GM_listValues) != "undefined")
  132. {
  133. is_GM_listValues_bultin = true;
  134. _GM_listValues = GM_listValues;
  135. gm_extensions.GM_listValues = _GM_listValues; // ToDO
  136. }
  137. }
  138. else
  139. {
  140. var get_recoverable_string = function(value)
  141. {
  142. var type = (typeof value);
  143. if(type == "boolean")
  144. return "" + value;
  145. if(type == "number")
  146. {
  147. if(isNaN(value)) return "Number.NaN";
  148. if(value == Number.POSITIVE_INFINITY) return "Number.POSITIVE_INFINITY";
  149. if(value == Number.NEGATIVE_INFINITY) return "Number.NEGATIVE_INFINITY";
  150. return "" + value;
  151. }
  152. if(type == "string")
  153. {
  154. var tmp = escape(value);
  155. if(value == tmp) return "'" + value + "'";
  156. return "unescape('" + tmp + "')";
  157. }
  158. if(type == "null" || (type == "object" && value == null))
  159. return "null";
  160. if(type == "date")
  161. return "new Date(" + value.getTime() + ")";
  162.  
  163. alert("Unsupported value in GM_set: " + value);
  164. return "{error: 'Unsupported value.'}";
  165. };
  166.  
  167. if((typeof PRO_setValue) != "undefined") // Internet Explorer
  168. {
  169. cross_domain_values = true;
  170. gm_extensions.GM_getValue = function(name, default_value, unique_script_name)
  171. {
  172. if(!name) return;
  173. var value = PRO_getValue(get_full_name(name, unique_script_name), default_value);
  174. if(value == default_value) return default_value;
  175.  
  176. try { eval("value = " + unescape(value)); } catch(e) { return default_value; }
  177.  
  178. // If the value is equal to default, delete it so it won't waste space
  179. if(value == default_value) gm_extensions.GM_deleteValue(name, unique_script_name);
  180.  
  181. return value;
  182. };
  183. gm_extensions.GM_setValue = function(name, value, unique_script_name)
  184. {
  185. if(!name) return false;
  186. PRO_setValue(get_full_name(name, unique_script_name), escape(get_recoverable_string(value)));
  187. };
  188. gm_extensions.GM_deleteValue = function(name, unique_script_name)
  189. {
  190. if(!name) return false;
  191. if((typeof PRO_deleteValue) != "undefined")
  192. PRO_deleteValue(get_full_name(name, unique_script_name));
  193. else
  194. PRO_setValue(get_full_name(name, unique_script_name), "");
  195. };
  196. if((typeof PRO_listValues) != "undefined") gm_extensions.GM_listValues = PRO_listValues; // ToDO
  197. }
  198. else if(storage)
  199. {
  200. storage_used = true;
  201. if(opera_script_storage_active) cross_domain_values = true;
  202. gm_extensions.GM_getValue = function(name, default_value, unique_script_name)
  203. {
  204. if(!name) return;
  205. var value = storage.getItem(get_full_name(name, unique_script_name));
  206. if(value == null) return default_value;
  207.  
  208. try { eval("value = " + unescape(value)); } catch(e) { return default_value; }
  209.  
  210. // If the value is equal to default, delete it so it won't waste space
  211. if(value == default_value) gm_extensions.GM_deleteValue(name, unique_script_name);
  212.  
  213. return value;
  214. };
  215. gm_extensions.GM_setValue = function(name, value, unique_script_name)
  216. {
  217. if(!name) return false;
  218. storage.setItem(get_full_name(name, unique_script_name), escape(get_recoverable_string(value)));
  219. };
  220. gm_extensions.GM_deleteValue = function(name, unique_script_name)
  221. {
  222. if(!name) return false;
  223. storage.removeItem(get_full_name(name, unique_script_name));
  224. };
  225. gm_extensions.GM_listValues = function(unique_script_name)
  226. {
  227. var list = [], count = 0, storage_length = storage.length, search = null, skip_length = 0; if(storage_length == undefined) return [];
  228.  
  229. if(unique_script_name != undefined) search = "UserJS_" + unique_script_name + "_";
  230. else { search = "UserJS__"; gm_extensions.GM_log("You should avoid using GM_listValues without unique_script_name."); }
  231. skip_length = search.length;
  232.  
  233. for(var i = 0; i < storage_length; i++)
  234. {
  235. name = storage.key(i);
  236. if(name.indexOf(search) == 0) { list[count] = name.substring(skip_length); count++; }
  237. }
  238.  
  239. return list;
  240. };
  241. }
  242. /*else if(window.google && google.gears){ google.gears.factory.create('beta.database'); }*/
  243. else
  244. {
  245. gm_extensions.GM_getValue = function(name, default_value, unique_script_name)
  246. {
  247. if(!name) return;
  248. var full_name = escape(get_full_name(name, unique_script_name));
  249. var cookies = document.cookie.split("; ");
  250. var cookies_length = cookies.length, one_cookie;
  251. for(var i = 0; i < cookies_length; i++)
  252. {
  253. one_cookie = cookies[i].split("=");
  254. if(one_cookie[0] == full_name)
  255. {
  256. var value;
  257. try { eval("value = "+unescape(one_cookie[1])); } catch(e) { return default_value; }
  258.  
  259. // If the value is equal to default, delete it so it won't waste space
  260. if(value == default_value) gm_extensions.GM_deleteValue(name, unique_script_name);
  261.  
  262. return value;
  263. }
  264. }
  265. return default_value;
  266. };
  267. var life_time = 157680000000; // 31536000 * 5 * 1000
  268. gm_extensions.GM_setValue = function(name, value, unique_script_name, action)
  269. {
  270. if(!name) return false;
  271. if(action == "delete") action = -10; else action = life_time;
  272. document.cookie = escape(get_full_name(name, unique_script_name))+"="+escape(get_recoverable_string(value))+";expires="+( new Date( (new Date()).getTime() + action ) ).toGMTString()+";path=/";
  273. };
  274. gm_extensions.GM_deleteValue = function(name, unique_script_name) { return gm_extensions.GM_setValue(name, "", unique_script_name, "delete"); };
  275. gm_extensions.GM_listValues = function() { return []; }; // ToDO
  276. }
  277. }
  278. gm_extensions.GM_areStoredValuesCrossDomain = function()
  279. {
  280. return cross_domain_values;
  281. };
  282.  
  283. if((typeof GM_addStyle) != "undefined") // Firefox
  284. gm_extensions.GM_addStyle = GM_addStyle;
  285. else if((typeof PRO_addStyle) != "undefined") // Internet Explorer
  286. gm_extensions.GM_addStyle = PRO_addStyle;
  287. else
  288. {
  289. gm_extensions.GM_addStyle = function(css_string)
  290. {
  291. var head = document.getElementsByTagName("head"),
  292. stylesheet = document.createElement("style");
  293. stylesheet.type = "text/css";
  294. stylesheet.appendChild(document.createTextNode(css_string));
  295. if(head)
  296. head[0].appendChild(stylesheet);
  297. else
  298. document.documentElement.insertBefore(stylesheet, document.documentElement.firstChild);
  299. };
  300. }
  301.  
  302. gm_extensions.GM_renameMenuCommand = function(){}; // Dummy
  303. if((typeof GM_registerMenuCommand) != "undefined" && GM_registerMenuCommand.toString().indexOf("not supported") == -1 && !override_GM_registerMenuCommand) // Firefox
  304. gm_extensions.GM_registerMenuCommand = GM_registerMenuCommand;
  305. else if((typeof PRO_registerMenuCommand) != "undefined" && !override_GM_registerMenuCommand) // Internet Explorer
  306. gm_extensions.GM_registerMenuCommand = PRO_registerMenuCommand;
  307. else if(!enable_GM_registerMenuCommand)
  308. gm_extensions.GM_registerMenuCommand = function(){}; // Dummy
  309. else
  310. {
  311. gm_extensions.GM_registerMenuCommand = function(caption, command_func, access_key)
  312. {
  313. if (arguments.length === 5) {
  314. // GM 0.9.1 & earlier - http://wiki.greasespot.net/GM_registerMenuCommand
  315. access_key = arguments[4];
  316. }
  317. gm_menu.add_item(caption, command_func, access_key);
  318. };
  319. gm_extensions.GM_renameMenuCommand = function(old_caption, new_caption, new_access_key) {
  320. var gm_menu_list = document.getElementById("gme_menu"),
  321. matching_menu_item,
  322. re = new RegExp("^" + old_caption + "(\\s\\(.\\))?$", "i");
  323.  
  324. // find menu item with old_caption
  325. for (var i=0, len=gm_menu_list.childNodes.length; i<len; i++) {
  326. var this_caption = gm_menu_list.childNodes[i].textContent || gm_menu_list.childNodes[i].innerText;
  327. if (re.test(this_caption)) {
  328. matching_menu_item = gm_menu_list.childNodes[i];
  329. break;
  330. }
  331. }
  332. if (matching_menu_item) {
  333. gm_menu.add_access_key(matching_menu_item, new_caption, new_access_key, i);
  334. return true;
  335. } else {
  336. gm_extensions.GM_log('caption: "' + old_caption +'" not found in GM_renameMenuCommand.');
  337. return false;
  338. }
  339. };
  340.  
  341. var gm_menu = {};
  342. gm_menu.add_access_key = function(obj, menu_text, access_char, skip) {
  343. var menu_updated = false;
  344. if ((typeof access_char == "string") && (access_char.length > 0)) {
  345. access_char = access_char.substr(0,1).toUpperCase();
  346. var gm_menu_list = obj.parentNode,
  347. keycode = access_char.charCodeAt(0),
  348. keycode_in_use = false,
  349. menu_label = menu_text;
  350.  
  351. // see if another menu item uses the same keycode
  352. for (var i=0, len=gm_menu_list.childNodes.length; i<len; i++) {
  353. if ((i !== skip) &&
  354. (gm_menu_list.childNodes[i].getAttribute("accesskeycode") == keycode)) {
  355. keycode_in_use = true;
  356. break;
  357. }
  358. }
  359.  
  360. if (!keycode_in_use) {
  361. var reg_exp = new RegExp("(" + access_char + ")", "i");
  362. menu_label = menu_text.replace(reg_exp, "<u>$1</u>");
  363. if (menu_label == menu_text) {
  364. menu_label += " (<u>" + access_char + "</u>)";
  365. }
  366. obj.innerHTML = menu_label;
  367. obj.setAttribute("accesskeycode", keycode);
  368. menu_updated = true;
  369. }
  370. }
  371. if (!menu_updated) {
  372. obj.innerHTML = menu_text;
  373. obj.removeAttribute("accesskeycode");
  374. }
  375. };
  376.  
  377. var node_contains = function(outer, innie) {
  378. if (outer.contains) {
  379. return outer.contains(innie); // a node is considered to contain itself
  380. } else if (outer.compareDocumentPosition) {
  381. var bitmask = outer.compareDocumentPosition(innie);
  382. return ((bitmask === 0) || // innie "is equal to" outer
  383. !!(bitmask & 16)); // innie "is contained by" outer
  384. }
  385. return false; // unknown
  386. };
  387. gm_menu.create = function() {
  388. gm_menu.icon = document.getElementById("gme_menu_icon");
  389. if (gm_menu.icon) return; // another extension has already created the menu
  390.  
  391. var menu_icon = 'data:image/png;base64,' +
  392. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/o' +
  393. 'L2nkwAAARNJREFUOMut07ErxGEcx/HXzyFlkIUYDCKTRVZksjIRmWQwMFqfe64MJoPBKINNMd5gNOgMsi' +
  394. 'gr+QOU6EJneU7X5Y6Obz09Pd+e7/v7/Xzqm+Xz+Yo/RDuEELJWimOMlba/dP+aoI7aiW0sYQQ5POIchRD' +
  395. 'CfVMADrGMV0ym3B7WMIWxhoAYY2/qDF0JUkyTwNtPEgZR9SXDDmYxgA5c1wPqTbzDGcrpvYgHlHCBmxjj' +
  396. 'RMMJQgjvWKiRlMNq8iXDKDaw3siDeRQwjGecYBO76EvfPppJOMI4utGPuRBCJUmoRqkZoJjuFxxgOsbYg' +
  397. '6GUv8RxM8AKtnCVZJziFk8pPxNCKNcWfGfifjq/iv/ZhRhjyyv9CYEvRESFg9k9AAAAAElFTkSuQmCC';
  398. // http://webdesign.about.com/od/colorcharts/l/blsystemcolors.htm
  399. gm_extensions.GM_addStyle(
  400. "#gme_menu_icon { z-index:900000;" +
  401. " height:16px; width:16px; position:fixed; right:0; bottom:0;" +
  402. " background-color:transparent; }" +
  403.  
  404. "#gme_menu_icon { cursor:pointer; }" +
  405. "#gme_menu_icon.open, #gme_menu_icon.closed {" +
  406. " background:url('" + menu_icon + "') no-repeat center center; }" +
  407. "#gme_menu_icon.open { background-color:Highlight; }" +
  408. "#gme_menu_icon.closed:hover { background-color:Highlight; }" +
  409. "#gme_menu_icon.open ul { display:block; }" +
  410.  
  411. "#gme_menu { display:none; width:auto; padding:2px; margin:0; position:fixed;" +
  412. " background-color:Menu; right:0; bottom:15px; border:1px solid ThreeDShadow;" +
  413. " -moz-box-shadow:0px 2px 4px rgba(0,0,0,0.5);" +
  414. " -webkit-box-shadow:0px 2px 4px rgba(0,0,0,0.5);" +
  415. " box-shadow:0px 2px 4px rgba(0,0,0,0.5); }" +
  416.  
  417. ".gme_menu_item { background-color:Menu; color:MenuText;" +
  418. " list-style-type:none; padding:0 10px; white-space:pre;" +
  419. " font:11px sans-serif; text-align:left; }" +
  420.  
  421. "#gme_menu li.hover { background-color:Highlight; color:HighlightText; }");
  422.  
  423. gm_menu.icon = document.createElement("div");
  424. gm_menu.icon.id = "gme_menu_icon";
  425.  
  426. var gm_menu_list = document.createElement("ul");
  427. gm_menu_list.id = "gme_menu";
  428. gm_menu.icon.appendChild(gm_menu_list);
  429. var doc_body = document.body || document.documentElement.lastChild || document.documentElement; // HTML.body || HTML.body || HTML
  430. doc_body.appendChild(gm_menu.icon);
  431.  
  432. var is_open_query = function() {
  433. return (gm_menu.icon.className == "open");
  434. };
  435. var simulate_click = function(obj) {
  436. // the menu item may have been added by another invocation of this script
  437. // so when an access_key or enter is pressed, the only way to call the
  438. // command_func is to trigger the click event on the menu item.
  439. if (obj.dispatchEvent) {
  440. var evt = document.createEvent("MouseEvents");
  441. evt.initMouseEvent("click", true, true, window,
  442. 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  443. obj.dispatchEvent(evt);
  444. } else if (obj.fireEvent) {
  445. obj.fireEvent("onclick");
  446. }
  447. };
  448. var window_mousedown_event = function(e) {
  449. if (!e) e = window.event;
  450. var targ = (e.target || e.srcElement);
  451. if (targ.nodeType == 3) targ = targ.parentNode; // Safari
  452.  
  453. if (!node_contains(gm_menu.icon, targ)) {
  454. // not over menu
  455. if (is_open_query()) gm_menu.close();
  456. } else //if (targ.className.indexOf("gme_menu_item") >= 0) {
  457. if (targ.nodeName == "LI") {
  458. // over a menu item - prevent text selection within menu
  459. if (e.preventDefault) e.preventDefault();
  460. e.returnValue = false;
  461. } else {
  462. // over some other part of the menu
  463. if (e.stopPropagation) e.stopPropagation();
  464. e.cancelBubble = true;
  465. if (is_open_query()) gm_menu.close();
  466. else gm_menu.open();
  467. }
  468. };
  469. var window_blur_event = function() {
  470. if (is_open_query()) gm_menu.close();
  471. };
  472. /*
  473. http://asquare.net/javascript/tests/KeyCode.html
  474. http://www.quirksmode.org/js/keys.html
  475. http://unixpapa.com/js/key.html
  476. */
  477. var window_key_event = function(e) {
  478. // Note: In the keydown and keyup events you will get the keycode of the letters
  479. // always in uppercase
  480. // but in the keypress events you will get them in the same case the user typed them.
  481. if (!e) e = window.event;
  482. var keyCode = e.keyCode || e.which;
  483. if (keyCode == 0) return; // Unknown key
  484.  
  485. if (is_open_query()) {
  486. // while the menu is open, prevent all keypresses from doing anything else
  487. if (e.preventDefault) e.preventDefault();
  488. e.returnValue = false;
  489.  
  490. var gm_menu_list = document.getElementById("gme_menu"),
  491. numItems = gm_menu_list.childNodes.length,
  492. menu_item;
  493. if (keyCode == 38) { // up arrow
  494. // find which item is currently highlighted
  495. menu_item = gm_menu.highlighted_item_query();
  496.  
  497. // un-highlight the item
  498. gm_menu.highlight_item(menu_item, false);
  499.  
  500. // get the next item up
  501. if (menu_item && menu_item.previousSibling) {
  502. menu_item = menu_item.previousSibling;
  503. } else {
  504. menu_item = gm_menu_list.lastChild;
  505. }
  506.  
  507. // highlight the new item
  508. gm_menu.highlight_item(menu_item, true);
  509.  
  510. } else if (keyCode == 40) { // down arrow
  511. // find which item is currently highlighted
  512. menu_item = gm_menu.highlighted_item_query();
  513.  
  514. // un-highlight the item
  515. gm_menu.highlight_item(menu_item, false);
  516.  
  517. // get the next item down
  518. if (menu_item && menu_item.nextSibling) {
  519. menu_item = menu_item.nextSibling;
  520. } else {
  521. menu_item = gm_menu_list.firstChild;
  522. }
  523.  
  524. // highlight the new item
  525. gm_menu.highlight_item(menu_item, true);
  526.  
  527. } else if (keyCode == 27) { // esc
  528. gm_menu.close();
  529. } else if (keyCode == 13) { // enter
  530. menu_item = gm_menu.highlighted_item_query();
  531. gm_menu.close();
  532. simulate_click(menu_item);
  533. } else {
  534. // see if one of the menu items uses this keycode
  535. var menu_item_to_handle;
  536. for (var i=0; i<numItems; i++) {
  537. if (gm_menu_list.childNodes[i].hasAttribute("accesskeycode") &&
  538. gm_menu_list.childNodes[i].getAttribute("accesskeycode") == keyCode) {
  539. menu_item_to_handle = gm_menu_list.childNodes[i];
  540. break;
  541. }
  542. }
  543. if (menu_item_to_handle) {
  544. gm_menu.highlight_item(gm_menu.highlighted_item_query(), false);
  545. gm_menu.highlight_item(menu_item_to_handle, true);
  546. window.setTimeout(function() {
  547. gm_menu.close();
  548. simulate_click(menu_item_to_handle);
  549. }, 100);
  550. }
  551. }
  552. } else { // menu is not open
  553. if ((keyCode == 220) && e.ctrlKey) { // ctrl+\
  554. gm_menu.open();
  555. if (e.preventDefault) e.preventDefault();
  556. else e.returnValue = false;
  557. }
  558. }
  559. };
  560. var prevent_selection = function(e) {
  561. if (!e) e = window.event;
  562. if (e.preventDefault) e.preventDefault();
  563. e.returnValue = false;
  564. };
  565. if (document.addEventListener) {
  566. document.addEventListener("mousedown", window_mousedown_event, false);
  567. document.addEventListener("keydown", window_key_event, false);
  568. window.addEventListener ("blur", window_blur_event, false);
  569. } else {
  570. gm_menu.icon.attachEvent("onselectstart", gm_menu.prevent_selection);
  571. document.attachEvent ("onmousedown", window_mousedown_event);
  572. document.attachEvent ("onkeydown", window_key_event);
  573. window.attachEvent ("onblur", window_blur_event);
  574. }
  575. };
  576.  
  577. /*
  578. http://www.quirksmode.org/dom/events/index.html
  579. http://www.quirksmode.org/js/events_properties.html
  580. */
  581. gm_menu.add_item = function(caption, command_func, access_key) {
  582. gm_menu.create();
  583. var gm_menu_list = document.getElementById("gme_menu"),
  584. gm_menu_item = document.createElement("li");
  585. gm_menu_item.innerHTML = caption;
  586. gm_menu_item.className = "gme_menu_item";
  587. gm_menu_list.appendChild(gm_menu_item);
  588. gm_menu.add_access_key(gm_menu_item, caption, access_key);
  589.  
  590. var click_event = function(e) {
  591. if (!e) e = window.event;
  592. if (e.stopPropagation) e.stopPropagation();
  593. e.cancelBubble = true;
  594.  
  595. gm_menu.close();
  596. if ("function" == typeof command_func) command_func();
  597. };
  598. var mouseover_event = function(e) {
  599. // find which item is currently highlighted (in case highlighted via keyboard)
  600. var item = gm_menu.highlighted_item_query();
  601.  
  602. // un-highlight that item
  603. gm_menu.highlight_item(item, false);
  604.  
  605. // highlight this item
  606. if (!e) e = window.event;
  607. var targ = (e.target || e.srcElement);
  608. if (targ.nodeType == 3) targ = targ.parentNode; // Safari
  609. if (targ.nodeName != "LI") targ = targ.parentNode; // underlined access_key
  610. gm_menu.highlight_item(targ, true);
  611.  
  612. };
  613. var mouseout_event = function(e) {
  614. if (!e) e = window.event;
  615. var targ = (e.target || e.srcElement);
  616. if (targ.nodeType == 3) targ = targ.parentNode; // Safari
  617. if (targ.nodeName != "LI") targ = targ.parentNode; // underlined access_key
  618. gm_menu.highlight_item(targ, false);
  619. };
  620.  
  621. if (document.addEventListener) {
  622. gm_menu_item.addEventListener("mouseover", mouseover_event, false);
  623. gm_menu_item.addEventListener("mouseout", mouseout_event, false);
  624. gm_menu_item.addEventListener("click", click_event, false);
  625. } else {
  626. gm_menu_item.attachEvent("onmouseenter", mouseover_event);
  627. gm_menu_item.attachEvent("onmouseleave", mouseout_event);
  628. gm_menu_item.attachEvent("onclick", click_event);
  629. }
  630. };
  631. gm_menu.close = function(e) {
  632. // find which item is currently highlighted
  633. var obj = gm_menu.highlighted_item_query();
  634.  
  635. // close the menu
  636. var gm_menu_icon = document.getElementById("gme_menu_icon");
  637. if (gm_menu_icon) {
  638. gm_menu_icon.className = "closed";
  639. }
  640.  
  641. // un-highlight the item
  642. gm_menu.highlight_item(obj, false);
  643.  
  644. return obj;
  645. };
  646. gm_menu.open = function(e) {
  647. var gm_menu_icon = document.getElementById("gme_menu_icon");
  648. if (gm_menu_icon) {
  649. gm_menu_icon.className = "open";
  650. }
  651. };
  652. gm_menu.highlight_item = function(obj, state) {
  653. if (obj) {
  654. obj.className = (state ? "gme_menu_item hover" : "gme_menu_item");
  655. }
  656. };
  657. gm_menu.highlighted_item_query = function() {
  658. var gm_menu_list = document.getElementById("gme_menu");
  659. for (var i=0, len=gm_menu_list.childNodes.length; i<len; i++) {
  660. if (gm_menu_list.childNodes[i].className.indexOf(" hover") > 0) {
  661. return gm_menu_list.childNodes[i];
  662. }
  663. }
  664. };
  665. }
  666. var GlobalConfiguration = function()
  667. {
  668. var global_variables = {"Script managment":[], "Unknown script":[], "Web page":[]};
  669. var output = "";
  670.  
  671. if(storage_used)
  672. {
  673. var storage_length = storage.length, name, value, pos;
  674. if(storage_length != undefined)
  675. for(var i = 0; i < storage_length; i++)
  676. {
  677. name = storage.key(i);
  678. value = storage.getItem(name);
  679. if(name.indexOf("UserJS_") != 0)
  680. global_variables["Web page"][(global_variables["Web page"].length)] = [name, value];
  681. else
  682. {
  683. name = name.substring(7);
  684. if(name.indexOf("Script_managment-") == 0)
  685. global_variables["Script managment"][(global_variables["Script managment"].length)] = [name.substring(17), value];
  686. else
  687. {
  688. pos = name.indexOf("_");
  689. if(pos == 0)
  690. global_variables["Unknown script"][(global_variables["Unknown script"].length)] = [name.substring(1), value];
  691. else
  692. {
  693. var temp = name.substring(0, pos);
  694. if(!global_variables[temp]) global_variables[temp] = [];
  695. global_variables[temp][(global_variables[temp].length)] = [name.substring(pos+1), value];
  696. }
  697. }
  698. }
  699. }
  700.  
  701. output += "Cross-domain values => " + cross_domain_values + "<br>";
  702. output += "opera.scriptStorage active => " + opera_script_storage_active + "<br>";
  703. output += "window.localStorage => " + (!!window.localStorage) + "<br><br>";
  704. if(storage_length == undefined) output += "Warning: Missing length property in the storage array.<br><br>";
  705. var value, i, global_variables_script_length;
  706. for(var script_name in global_variables)
  707. {
  708. if(script_name == "Script managment") continue;
  709. for(i = 0, global_variables_script_length = global_variables[script_name].length; i < global_variables_script_length; i++)
  710. {
  711. if(script_name != "Web page")
  712. try { eval("value = " + unescape(global_variables[script_name][i][1])); } catch(e) { value = {error: "Failed."}; }
  713. else
  714. value = global_variables[script_name][i][1];
  715. output += script_name + " => " + global_variables[script_name][i][0] + " = " + value + "<br>";
  716. }
  717. if(global_variables_script_length > 0) output += "<br>";
  718. }
  719. global_variables = null;
  720. document.write(output);
  721. output = null;
  722. }
  723. else
  724. alert("Not yet implemented.");
  725. };
  726.  
  727. if (show_global_config_menu_item && storage_used) {
  728. // In Opera, this script runs at document-start, before the DOM is fully created.
  729. // Attempting to add the GM_menu to the DOM would fail.
  730. // This delays the menu creation until the DOM is loaded.
  731. if (opera_obj && document.addEventListener) {
  732. document.addEventListener("DOMContentLoaded", function() {
  733. gm_extensions.GM_registerMenuCommand("Global configuration", GlobalConfiguration, "G");
  734. }, false);
  735. } else {
  736. gm_extensions.GM_registerMenuCommand("Global configuration", GlobalConfiguration, "G");
  737. }
  738. }
  739.  
  740. gm_extensions.unsafeWindow = unsfw;
  741. if(!window.wrappedJSObject) window.wrappedJSObject = unsfw;
  742. if(!window.content) window.content = window.top; // https://developer.mozilla.org/en/DOM/window.content
  743. if(!unsfw.content) unsfw.content = unsfw.top;
  744. if(!unsfw._content) unsfw._content = unsfw.content;
  745.  
  746. if((typeof GM_xmlhttpRequest) != "undefined") // Firefox
  747. gm_extensions.GM_xmlhttpRequest = GM_xmlhttpRequest;
  748. else
  749. {
  750. var error_text = "GM_xmlhttpRequest failed, URL: ";
  751. var cross_domain_note = "\nNote: Cross-domain GM_xmlhttpRequest is disabled, if you are using Opera you must install the \"Cross-domain XMLHttpRequest\" userscript to enable it.";
  752. var cross_domain_opera_xmlhttprequest = (opera_obj ? opera_obj.XMLHttpRequest : null);
  753. var iepro_xmlhttprequest_exist = ((typeof PRO_xmlhttpRequest) != "undefined" ? true : false);
  754. var is_cross_domain_http_request = function(url_req)
  755. {
  756. //gm_extensions.GM_log("is_cross_domain_http_request(" + url_req + ");");
  757. var pos = url_req.indexOf("://");
  758. if( url_req.substring(0, pos + 1) != location.protocol ) return true;
  759.  
  760. url_req = url_req.substring(pos + 3);
  761. pos = url_req.indexOf("/");
  762. if(pos != -1) url_req = url_req.substring(0, pos);
  763. if( url_req != location.host ) return true;
  764.  
  765. return false;
  766. };
  767.  
  768. gm_extensions.GM_xmlhttpRequest = function(details) // http://www.w3.org/Protocols/HTTP/HTRESP.html
  769. {
  770. //gm_extensions.GM_log("XMLHttpRequest of: " + details.url);
  771. var xml_http = null, cross_domain_used = true, cross_domain_req = is_cross_domain_http_request(details.url);
  772. //gm_extensions.GM_log("cross_domain_req => " + cross_domain_req);
  773.  
  774. if(cross_domain_req && cross_domain_opera_xmlhttprequest) // Opera (cross-domain requests only)
  775. xml_http = new cross_domain_opera_xmlhttprequest();
  776. else if(iepro_xmlhttprequest_exist) // Internet Explorer + IEPro
  777. xml_http = PRO_xmlhttpRequest();
  778. else
  779. {
  780. cross_domain_used = false;
  781. if(window.XMLHttpRequest) // The standard
  782. xml_http = new XMLHttpRequest();
  783. else if(window.createRequest) // IceBrowser
  784. xml_http = window.createRequest();
  785. }
  786. if(!xml_http)
  787. { // Simulate a real error
  788. if(details.onerror) details.onerror({ responseText: "", readyState: 4, responseHeaders: "", status: 0, statusText: "GM_xmlhttpRequest failed (missing xml_http object)", finalUrl: details.url });
  789. else gm_extensions.GM_log("GM_xmlhttpRequest failed (missing xml_http object), URL: " + details.url);
  790. return;
  791. }
  792.  
  793. xml_http.onreadystatechange = function()
  794. {
  795. var ready_state = xml_http.readyState;
  796. var status3or4 = (ready_state == 3 || ready_state == 4);
  797. var response =
  798. {
  799. responseText: (status3or4 ? xml_http.responseText : ""),
  800. readyState: ready_state,
  801. responseHeaders: (status3or4 ? xml_http.getAllResponseHeaders() : null),
  802. status: (status3or4 ? xml_http.status : null),
  803. statusText: (status3or4 ? xml_http.statusText : null),
  804. finalUrl: (ready_state == 4 ? details.url : null)
  805. };
  806.  
  807. if(details.onreadystatechange) details.onreadystatechange(response);
  808. if(ready_state == 4)
  809. {
  810. if(xml_http.status >= 200 && xml_http.status < 300) { if(details.onload) details.onload(response); }
  811. else { if(details.onerror) details.onerror(response); }
  812. }
  813. };
  814.  
  815. xml_http.open(details.method, details.url, true);
  816. if(details.headers)
  817. for(var this_header in details.headers) xml_http.setRequestHeader(this_header, details.headers[this_header]);
  818.  
  819. try { xml_http.send(details.data); }
  820. catch(e)
  821. { // Simulate a real error
  822. if(details.onerror) details.onerror({ responseText: "", readyState: 4, responseHeaders: "", status: 403, statusText: "Forbidden", finalUrl: details.url });
  823. else gm_extensions.GM_log(error_text + details.url + (opera_obj && !cross_domain_used && cross_domain_req ? cross_domain_note : ""));
  824. }
  825. };
  826. }
  827.  
  828. if((typeof GM_openInTab) != "undefined") // Firefox
  829. gm_extensions.GM_openInTab = GM_openInTab;
  830. else if((typeof PRO_openInTab) != "undefined") // Internet Explorer
  831. gm_extensions.GM_openInTab = PRO_openInTab;
  832. else
  833. gm_extensions.GM_openInTab = function(url) { return window.open(url, "_blank"); };
  834.  
  835. var gm_emulation_enhanced_scripts = [];
  836. gm_extensions.GM_announcePresence = function(unique_script_name, displayed_name, version)
  837. {
  838. if(unique_script_name.length <= 4) { alert("GM_announcePresence => The \"unique_script_name\" is missing or too short."); return false; }
  839. gm_emulation_enhanced_scripts[gm_emulation_enhanced_scripts.length] = [unique_script_name, displayed_name, version];
  840. return gm_extensions.GM_getValue("is_enabled", true, "Script_managment-" + unique_script_name);
  841. };
  842. gm_extensions.GM_updateCheck = function(update_check_url, installed_version, update_check_every, handle_update_function, unique_script_name)
  843. {
  844. if(!cross_domain_values) return null;
  845. var now = Math.round( ( (new Date()).getTime() ) / 60000 ); // 60000 (1000 * 60) From milliseconds to minutes
  846.  
  847. var last_update_check_global = gm_extensions.GM_getValue("last_update_check", 0, "Script_managment-GLOBAL_SHARED");
  848. if(now - last_update_check_global < 3) return false; // Only one time every 3 minutes maximum
  849.  
  850. if(unique_script_name.length <= 4) { alert("GM_updateCheck => The \"unique_script_name\" is missing or too short."); return false; }
  851.  
  852. var last_update_check = gm_extensions.GM_getValue("last_update_check", 0, "Script_managment-" + unique_script_name);
  853. if(now - last_update_check < update_check_every * 1440) return false; // 1440 (60 * 24) From days to minutes - Only one time every X days maximum
  854.  
  855. gm_extensions.GM_setValue("last_update_check", now, "Script_managment-GLOBAL_SHARED");
  856. gm_extensions.GM_setValue("last_update_check", now, "Script_managment-" + unique_script_name);
  857. gm_extensions.GM_xmlhttpRequest(
  858. {
  859. method: "GET", url: update_check_url, onload: function(result)
  860. {
  861. //gm_extensions.GM_log(result.responseText);
  862. var new_version = /\/\/\s*@version[\t\s]+([^\s\t\r\n]+)\s*\r?\n/i.exec(result.responseText);
  863. var new_unique_script_name = /\/\/\s*@uniquescriptname[\t\s]+([^\s\t\r\n]+)\s*\r?\n/i.exec(result.responseText);
  864.  
  865. if(new_version == null)
  866. {
  867. var error = unique_script_name + " => Failed checking the new version, URL: " + update_check_url;
  868. gm_extensions.GM_log(error);
  869. alert(error);
  870. return null;
  871. }
  872. new_version = new_version[1];
  873. if(new_unique_script_name == null)
  874. gm_extensions.GM_log(unique_script_name + " => The \"uniquescriptname\" is missing on the update server, URL: " + update_check_url);
  875. else if(new_unique_script_name[1] != unique_script_name)
  876. {
  877. var error = unique_script_name + " => The unique script name passed doesn't match the unique script name on the update server, maybe the update_check_url is wrong, URL: " + update_check_url;
  878. gm_extensions.GM_log(error);
  879. alert(error);
  880. return null;
  881. }
  882. gm_extensions.GM_setValue("last_new_version", new_version, "Script_managment-" + unique_script_name);
  883. if(new_version == installed_version) handle_update_function(false);
  884. else handle_update_function(new_version);
  885. }
  886. });
  887.  
  888. return true;
  889. };
  890. gm_extensions.GM_getEmulationVersion = function()
  891. {
  892. return version;
  893. };
  894.  
  895. gm_extensions.GM_exposeAPIs = function()
  896. {
  897. GM_log = gm_extensions.GM_log;
  898. if(!native_getsetvalues_functions)
  899. {
  900. GM_getValue = gm_extensions.GM_getValue;
  901. GM_setValue = gm_extensions.GM_setValue;
  902. }
  903. if(!is_GM_deleteValue_bultin) GM_deleteValue = gm_extensions.GM_deleteValue;
  904. if(!is_GM_listValues_bultin) GM_listValues = gm_extensions.GM_listValues;
  905. GM_areStoredValuesCrossDomain = gm_extensions.GM_areStoredValuesCrossDomain;
  906. GM_addStyle = gm_extensions.GM_addStyle;
  907. GM_registerMenuCommand = gm_extensions.GM_registerMenuCommand;
  908. GM_renameMenuCommand = gm_extensions.GM_renameMenuCommand;
  909. GM_xmlhttpRequest = gm_extensions.GM_xmlhttpRequest;
  910. GM_openInTab = gm_extensions.GM_openInTab;
  911. };
  912. gm_extensions.GM_exposeAPIs();
  913. if (window == window.top)
  914. window.setTimeout(function() {
  915. var TarquinWJ = (typeof doGMMeenoo != "undefined"),
  916. ale5000 = ( (typeof window.opera != "undefined") &&
  917. (typeof window.opera.userscripts != "undefined") &&
  918. (typeof window.opera.userscripts.GM != "undefined") ) // version 1.4.5 on Opera
  919. ||
  920. ( (typeof window.userscripts != "undefined") &&
  921. (typeof window.userscripts.GM != "undefined") ) // version 1.4.5
  922. ||
  923. ( (typeof window.userjs != "undefined") &&
  924. (typeof window.userjs.GM != "undefined") ), // versions 1.3.7 through 1.4.4
  925. str = '';
  926. if (TarquinWJ) str += '"Emulate GM functions" by TarquinWJ\n';
  927. if (ale5000) str += '"Greasemonkey Emulation" by ale5000\n';
  928. if (str) alert("You have multiple Greasemonkey emulation scripts installed:\n\n" + str + '"Greasemonkey Emulation" by Lil Devil\n\nOnly the one by Lil Devil should be installed for proper operation.');
  929. }, 5000);
  930.  
  931. var compat_array_indexof = false, compat_array_foreach = false;
  932. gm_extensions.BrowserCompat_Add = function()
  933. {
  934. var result = false;
  935. if(!Array.prototype.indexOf)
  936. {
  937. result = true;
  938. compat_array_indexof = true;
  939. Array.prototype.indexOf = function(find, i /*opt*/)
  940. {
  941. var array_length = this.length;
  942. if(!i) i = 0; else { if(i < 0) i+= array_length; if(i < 0) i= 0; }
  943.  
  944. for(; i < array_length; i++) if(this[i] == find) return i;
  945. return -1;
  946. };
  947. }
  948. if(!Array.prototype.forEach)
  949. {
  950. result = true;
  951. compat_array_foreach = true;
  952. Array.prototype.forEach = function(callback, thisObject /*opt*/)
  953. {
  954. if(!thisObject)
  955. {
  956. for(var i = 0, array_length = this.length; i < array_length; i++) if (i in this) callback(this[i]);
  957. }
  958. else
  959. {
  960. for(var i = 0, array_length = this.length; i < array_length; i++) if (i in this) callback.call(thisObject, this[i]);
  961. }
  962. };
  963. }
  964. return result;
  965. };
  966.  
  967. gm_extensions.BrowserCompat_Restore = function()
  968. {
  969. if(compat_array_indexof) { delete Array.prototype.indexOf; compat_array_indexof = false; }
  970. if(compat_array_foreach) { delete Array.prototype.forEach; compat_array_foreach = false; }
  971. };
  972.  
  973. var handle_update_function = function(new_version)
  974. {
  975. if(new_version != null && new_version != false)
  976. {
  977. GM_log("Greasemonkey Emulation => New version detected: " + new_version);
  978. var result = confirm("A new version of the \"Greasemonkey Emulation\" userscript is available.\nCurrent version: " + version + "\nNew version: " + new_version + "\n\nDo you want to update it now?\nThe update check will run again in 10 days.");
  979. if(result)
  980. try { location.href = "http://userscripts.org/scripts/source/105153.user.js"; } catch(e) {}
  981. }
  982. };
  983.  
  984. // this will only run in Firefox, IE and Opera (with scriptStorage active)
  985. gm_extensions.GM_updateCheck("http://userscripts.org/scripts/source/105153.meta.js", version, 10, handle_update_function, unique_script_name);
  986. })();
  987.  
  988. var Base64 = {
  989. _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  990. encode: function (input) {
  991. var output = "";
  992. var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  993. var i = 0;
  994. input = Base64._utf8_encode(input);
  995. while (i < input.length) {
  996. chr1 = input.charCodeAt(i++);
  997. chr2 = input.charCodeAt(i++);
  998. chr3 = input.charCodeAt(i++);
  999. enc1 = chr1 >> 2;
  1000. enc2 = (chr1 & 3) << 4 | chr2 >> 4;
  1001. enc3 = (chr2 & 15) << 2 | chr3 >> 6;
  1002. enc4 = chr3 & 63;
  1003. if (isNaN(chr2)) enc3 = enc4 = 64;
  1004. else if (isNaN(chr3)) enc4 = 64;
  1005. output = output + Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
  1006. Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4)
  1007. }
  1008. return output
  1009. },
  1010. decode: function (input) {
  1011. var output = "";
  1012. var chr1, chr2, chr3;
  1013. var enc1, enc2, enc3, enc4;
  1014. var i = 0;
  1015. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  1016. while (i < input.length) {
  1017. enc1 = Base64._keyStr.indexOf(input.charAt(i++));
  1018. enc2 = Base64._keyStr.indexOf(input.charAt(i++));
  1019. enc3 = Base64._keyStr.indexOf(input.charAt(i++));
  1020. enc4 = Base64._keyStr.indexOf(input.charAt(i++));
  1021. chr1 = enc1 << 2 | enc2 >> 4;
  1022. chr2 = (enc2 & 15) << 4 | enc3 >> 2;
  1023. chr3 = (enc3 & 3) << 6 | enc4;
  1024. output = output + String.fromCharCode(chr1);
  1025. if (enc3 != 64) output = output + String.fromCharCode(chr2);
  1026. if (enc4 != 64) output = output + String.fromCharCode(chr3)
  1027. }
  1028. output = Base64._utf8_decode(output);
  1029. return output
  1030. },
  1031. _utf8_encode: function (string) {
  1032. string = string.replace(/\r\n/g, "\n");
  1033. var utftext = "";
  1034. for (var n = 0; n < string.length; n++) {
  1035. var c = string.charCodeAt(n);
  1036. if (c < 128) utftext += String.fromCharCode(c);
  1037. else if (c > 127 && c < 2048) {
  1038. utftext += String.fromCharCode(c >> 6 | 192);
  1039. utftext += String.fromCharCode(c & 63 | 128)
  1040. } else {
  1041. utftext += String.fromCharCode(c >> 12 | 224);
  1042. utftext += String.fromCharCode(c >>
  1043. 6 & 63 | 128);
  1044. utftext += String.fromCharCode(c & 63 | 128)
  1045. }
  1046. }
  1047. return utftext
  1048. },
  1049. _utf8_decode: function (utftext) {
  1050. var string = "";
  1051. var i = 0;
  1052. var c = c1 = c2 = 0;
  1053. while (i < utftext.length) {
  1054. c = utftext.charCodeAt(i);
  1055. if (c < 128) {
  1056. string += String.fromCharCode(c);
  1057. i++
  1058. } else if (c > 191 && c < 224) {
  1059. c2 = utftext.charCodeAt(i + 1);
  1060. string += String.fromCharCode((c & 31) << 6 | c2 & 63);
  1061. i += 2
  1062. } else {
  1063. c2 = utftext.charCodeAt(i + 1);
  1064. c3 = utftext.charCodeAt(i + 2);
  1065. string += String.fromCharCode((c & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
  1066. i += 3
  1067. }
  1068. }
  1069. return string
  1070. }
  1071. };
  1072. var getCroppedDomain = function () {
  1073. if (!settings.croppedDomain) settings.croppedDomain = utils.cropDomain(getUrlInfo().host);
  1074. return settings.croppedDomain
  1075. };
  1076. var getUrlInfo = function () {
  1077. if (!settings.urlInfo) settings.urlInfo = utils.getUrl(document.location);
  1078. return settings.urlInfo
  1079. };
  1080. var sendGetRequest = function (path, async) {
  1081. var url = settings.testDomain ? settings.testDomain : utils.getHostWithProtocol();
  1082. url += path;
  1083. if (typeof async == "undefined") async = false;
  1084. var xmlhttp = new XMLHttpRequest;
  1085. xmlhttp.open("GET", url, async);
  1086. xmlhttp.send();
  1087. if (xmlhttp.readyState == 4)
  1088. if (xmlhttp.status != 200) throw xmlhttp.statusText;
  1089. return xmlhttp.responseText
  1090. };
  1091. var sendPostRequest = function (path, params) {
  1092. var url = settings.testDomain ? settings.testDomain : utils.getHostWithProtocol();
  1093. url += path;
  1094. var xmlhttp = new XMLHttpRequest;
  1095. xmlhttp.open("POST", url, false);
  1096. xmlhttp.send(params);
  1097. if (xmlhttp.readyState == 4)
  1098. if (xmlhttp.status != 200) throw xmlhttp.statusText;
  1099. return xmlhttp.responseText
  1100. };
  1101.  
  1102. function GM_getResourceText(resourceName) {
  1103. return Base64.decode(GM_getResourceURL(resourceName))
  1104. }
  1105.  
  1106. function GM_openInTab(url) {
  1107. window.open(url)
  1108. }
  1109.  
  1110. function GM_getResourceURL(resourceName) {
  1111. var result = GM_Resources[resourceName];
  1112. if (typeof result === "undefined") throw "Resource " + resourceName + " not found";
  1113. return result
  1114. }
  1115.  
  1116.  
  1117. // http://mths.be/unsafewindow
  1118. window.unsafeWindow || (
  1119. unsafeWindow = (function() {
  1120. var el = document.createElement('p');
  1121. el.setAttribute('onclick', 'return window;');
  1122. return el.onclick();
  1123. }())
  1124. );
  1125. // You can now use `unsafeWindow`, ehm, safely.
  1126. //console.log(unsafeWindow);
  1127. // If the current document uses a JavaScript library, you can use it in
  1128. // your user script like this:
  1129. //console.log(unsafeWindow.jQuery);
  1130.  
  1131. function GM_setClipboard(text) {
  1132. window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  1133. }