NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
(function () { "use strict"; // ==UserScript== // @name uso - installWith // @namespace http://userscripts.org/users/37004 // @description Adds option to install script with an icon and/or updater plus the original script advisor. "So easy, a cavemonkey can do it" // @copyright 2010+, Marti Martz (http://userscripts.org/users/37004) // @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt // @version 2.0.4.2eol // @icon https://raw.githubusercontent.com/Martii/UserScripts/master/src/uso/installWith/res/icon48.png // @homepageURL https://github.com/Martii/UserScripts/tree/master/src/uso/installWith // @homepageURL https://openuserjs.org/scripts/marti/uso_-_installWith // @homepageURL http://userscripts.org/scripts/show/68219 // @supportURL http://userscripts.org/topics/45480 // @include /^https?://userscripts.org(?::\d{1,5})?/?$/ // @include /^https?://userscripts\.org(?::\d{1,5})?/scripts/ // @include /^https?://userscripts\.org(?::\d{1,5})?/topics// // @include /^https?://userscripts\.org(?::\d{1,5})?/reviews// // @include /^https?://userscripts\.org(?::\d{1,5})?/users/.+?/scripts/ // @include /^https?://userscripts\.org(?::\d{1,5})?/users/.+?/favorites/ // @include /^https?://userscripts\.org(?::\d{1,5})?/groups/\d+/scripts/ // @include /^https?://userscripts\.org(?::\d{1,5})?/tags// // @include /^https?://userscripts\.org(?::\d{1,5})?/home/(?:scripts|favorites)/ // @include /^https?://userscripts\.org(?::\d{1,5})?/posts// // @include http://userscripts.org:8080/ // @include http://userscripts.org:8080/scripts* // @include http://userscripts.org:8080/topics/* // @include http://userscripts.org:8080/reviews/* // @include http://userscripts.org:8080/users/*/scripts* // @include http://userscripts.org:8080/users/*/favorites* // @include http://userscripts.org:8080/groups/*/scripts* // @include http://userscripts.org:8080/tags/* // @include http://userscripts.org:8080/home/scripts* // @include http://userscripts.org:8080/home/favorites* // @include http://userscripts.org:8080/posts* // @include http://userscripts.org/ // @include http://userscripts.org/scripts* // @include http://userscripts.org/topics/* // @include http://userscripts.org/reviews/* // @include http://userscripts.org/users/*/scripts* // @include http://userscripts.org/users/*/favorites* // @include http://userscripts.org/groups/*/scripts* // @include http://userscripts.org/tags/* // @include http://userscripts.org/home/scripts* // @include http://userscripts.org/home/favorites* // @include http://userscripts.org/posts* // @include https://userscripts.org/ // @include https://userscripts.org/scripts* // @include https://userscripts.org/topics/* // @include https://userscripts.org/reviews/* // @include https://userscripts.org/users/*/scripts* // @include https://userscripts.org/users/*/favorites* // @include https://userscripts.org/groups/*/scripts* // @include https://userscripts.org/tags/* // @include https://userscripts.org/home/scripts* // @include https://userscripts.org/home/favorites* // @include https://userscripts.org/posts* // @exclude /^https?://userscripts\.org(?::\d{1,5})?/scripts/diff// // @exclude /^https?://userscripts\.org(?::\d{1,5})?/scripts/version// // @exclude http://userscripts.org/scripts/diff/* // @exclude http://userscripts.org/scripts/version/* // @exclude https://userscripts.org/scripts/diff/* // @exclude https://userscripts.org/scripts/version/* // @updateURL http://userscripts.org:8080/scripts/source/68219.meta.js // @installURL http://userscripts.org:8080/scripts/source/68219.user.js // @downloadURL http://userscripts.org:8080/scripts/source/68219.user.js // @resource icon https://raw.githubusercontent.com/Martii/UserScripts/master/src/uso/installWith/res/icon32.png // @resource gmc https://raw.githubusercontent.com/sizzlemctwizzle/GM_config/master/gm_config_icon.png // @resource usoc https://raw.githubusercontent.com/Martii/UserScripts/master/res/compatibilityMatrix/usoc16.png // @resource uso https://raw.githubusercontent.com/Martii/UserScripts/master/res/compatibilityMatrix/uso16.png // @resource clear https://raw.githubusercontent.com/Martii/UserScripts/master/src/uso/installWith/res/clear1.gif // @resource more https://raw.githubusercontent.com/Martii/UserScripts/master/src/uso/installWith/res/more9x5.gif // @resource less https://raw.githubusercontent.com/Martii/UserScripts/master/src/uso/installWith/res/less5x9.gif // @resource list http://beta.usocheckup.dune.net/list.json //@require https://secure.dune.net/usocheckup/68219.js?method=install&open=window&maxage=1&custom=yes&topicid=45479&id=usoCheckup //@require http://userscripts.org/scripts/source/61794.user.js // @require https://raw.githubusercontent.com/Martii/UserScripts/dc7d27fef916db3bea640139bd852b2c75a08ff8/lib/GM_setStyle/GM_setStyle.js // @require https://raw.githubusercontent.com/Martii/GM_config/a0d0066ffaefb5fbb3402c3d46ac705e8b4124d8/gm_config.js // @grant GM_addStyle // @grant GM_deleteValue // @grant GM_getResourceText // @grant GM_getResourceURL // @grant GM_getValue // @grant GM_log // @grant GM_openInTab // @grant GM_registerMenuCommand // @grant GM_setClipboard // @grant GM_setValue // @grant GM_xmlhttpRequest // ==/UserScript== if (!document || !document.body) return; const gTHIS = this, gJSE = !!(typeof window.wrappedJSObject == "object" && typeof window.wrappedJSObject.jQuery == "function"), gPROTOCOL = location.protocol, gPORTX = /^80$/.test(location.port) ? "" : ":8080", gHOSTNAME = location.hostname, gPATHNAME = location.pathname, gISHOMEPAGE = /^\/scripts\/show\//.test(gPATHNAME), gHASH = location.hash, gCSS = GM_setStyle({ media: "screen, projection", data: ".hid { display: none; } .HID { display: none !important } .blah { color: #f00 !important; } .halb { background-color: #f00 !important; }" }), gUAC = !!document.body.querySelector(".alt_topbottom"), gHALT404 = true, gRETRIES = 4, gDELAYRETRYMIN = 3000, gDELAYRETRYMAX = 8000, gHEADLENADJ = 800, // NOTE: Inset gTITLELENADJ = 800, // NOTE: Outset gANONDIVISOR = 2.20, gLIST = GM_getResourceText("list").replace(/[\n\r\s]*\}[\n\r\s]*$/, '') ; let gGROUPS, gANODES, gQNODES, gBYTESMAX, gBYTESMIN, gIdle = true, gISFRAMELESS = false, gLoginMsgShown, gLoginTrying, gLoginTried ; try { gISFRAMELESS = (window == window.top); } catch (e) {} /** * */ function byteLength(aString) { return unescape(encodeURIComponent(aString)).length; } /** * */ function genReport(aReports, aReported, aMarkdown) { let i = 0, maxList = 30, post = "" ; if (aMarkdown) { aReports.split(",").forEach(function (e, i, a) { if (i % maxList == 0) { if (i != 0) post += '\n'; post += 'Potentially unwanted scripts\n\n'; } let found; aReported.split(",").forEach(function (e1, i1, a1) { if (e1 == e) found = true; }); if (!found) post += '* [' + e + '](' + e + ')\n'; else post += '* ' + e + '\n'; i++; }); } else { post = aReports.split(',').map(function (aE) { let found; aReported.split(",").forEach(function (e1, i1, a1) { if (e1 == aE) found = true; }); let item; if (!found) item = '\n<li><a href="' + aE + '">' + aE + '</a></li>'; else item = '\n<li>' + aE + '</li>'; if (i % maxList == 0) { aE = (i ? '\n</ul>\n' : '') + '<p>Potentially unwanted scripts</p>\n<ul>' + item; } else aE = item; i++; return aE; }).join('') + '\n</ul>'; } return post; } /** * */ function doReport(aReports) { GM_xmlhttpRequest({ retry: gRETRIES, url: "/topics/9.rss", method: "GET", onload: function(aR) { switch(aR.status) { case 404: if (gHALT404) this._retry = 0; case 500: case 502: case 503: if (gJSE && this.retry-- > 0) { setTimeout(GM_xmlhttpRequest, gDELAYRETRYMIN + Math.round(Math.random() * (gDELAYRETRYMAX - gDELAYRETRYMIN)), this); // NOTE: Detached break; // NOTE: Watchpoint } case 200: let parser = new DOMParser(), xml = parser.parseFromString(aR.responseText, "text/xml"), reported = [] ; let descriptions = xml.querySelectorAll("item description"); for (let i = 0, thisDescription; thisDescription = descriptions[i++];) { let docfrag = document.createDocumentFragment(); let nodeDiv = document.createElement("div"); nodeDiv.innerHTML = thisDescription.textContent; docfrag.appendChild(nodeDiv); let anchors = docfrag.querySelectorAll("a"); for (let j = 0, thisAnchor; thisAnchor = anchors[j++];) { let matches; matches = thisAnchor.href.match(/^https?:\/\/userscripts\.org(\/users\/\d+)\/?/); if (matches) reported.push(matches[1]); else if (matches = thisAnchor.href.match(/^https?:\/\/userscripts\.org(?::\d{1,5})?\/scripts\/show(\/\d+)\/?/)) reported.push(matches[1]); else if (matches = thisAnchor.href.match(/^https?:\/\/userscripts\.org(?::\d{1,5})?(\/\d+)\/?/)) reported.push(matches[1]); } } let count = 0, reports = aReports.split(","); reports.forEach(function (e, i, a) { reported.forEach(function (e1, i1, a1) { if (e1 == e) ++count; }); }); if (count > 0 && count == reports.length) ; // Do nothing else { let thisNode = document.querySelector("#content .posts tbody > tr:last-child .author .edit a.utility"), isReply; if (thisNode) { let dateNode = document.querySelector("#content .posts tbody > tr:last-child .author .date abbr"); if (dateNode) { let dateLastPost = new Date(dateNode.title); if ((Date.now() - dateLastPost) > (60 * 60 * 1000)) thisNode = undefined; } else { if (gmcHome.get("enableDebugging")) console.warn('Last posting date not found...reverting to reply mode'); thisNode = undefined; } } if (!thisNode) { thisNode = document.querySelector("#content > p a.utility"); isReply = true; } if (thisNode && (thisNode.textContent == "Reply to topic" || thisNode.textContent == "Edit post")) { setTimeout(function () { thisNode.click(); let that, retry = 4; if (!isReply) { setTimeout(that = function () { let post_body = document.querySelector("#edit textarea#edit_post_body"); if (post_body) { let UCF = !!document.querySelector("#edit .previewBtn"); if (UCF) post_body.value = post_body.textContent + '\n' + genReport(aReports, reported.join(','), document.querySelector("#edit #post_markdown").checked); else post_body.textContent += '\n' + genReport(aReports, reported.join(','), document.querySelector("#edit #post_markdown").checked); } else { if (retry-- > 0); setTimeout(that, 500); } }, 0); } else { setTimeout(that = function () { let post_body = document.querySelector("#reply textarea#post_body"); if (post_body) { let UCF = !!document.querySelector("#reply .previewBtn"); if (UCF) post_body.value = genReport(aReports, reported.join(','), document.querySelector("#reply #post_markdown").checked); else post_body.value = genReport(aReports, reported.join(','), document.querySelector("#reply #post_markdown").checked); } else { if (retry-- > 0); setTimeout(that, 500); } }, 0); } }, 1000); // NOTE: Give UCF this much initial time to load before triggering click otherwise USO default shows depending on script order/count } } break; } } }); } /** * */ function init() { gANODES = document.body.querySelectorAll(".script-meat, .userjs"); gQNODES = []; /** Initial gCSS fix for tagging **/ // NOTE: This fix may be different in later FF versions GM_setStyle({ node: gCSS, data: [ "th { border-bottom-style: none; }" ].join("\n") }); if (/(^\/users\/.+?\/(?:scripts|favorites)|^\/home\/(?:scripts|favorites))/.test(gPATHNAME) || (/^\/$/.test(gPATHNAME)) && gUAC) GM_setStyle({ node: gCSS, data: [ "#main th:first-child, #content th:first-child { border-left-width: 10px; padding-left: 7px; }", "table.forums tr td.script-meat { background-color: #eee; border-left: 10px solid #eee; }" ].join("\n") }); else if (/^\/groups\/\d+\/scripts/.test(gPATHNAME)) GM_setStyle({ node: gCSS, data: [ "#main th:first-child, #content th:first-child { border-right-width: 10px; padding-left: 7px; }", "table.forums tr td.script-meat { background-color: #eee; border-left: 10px solid #eee; }" ].join("\n") }); else GM_setStyle({ node: gCSS, data: [ "#main th:first-child, #content th:first-child { padding-left: 16px; }", "table.forums tr td.script-meat { background-color: #eee; border-left: 18px solid #eee; }" ].join("\n") }); GM_setStyle({ node: gCSS, data: [ "table.forums tr td.script-meat { background-color: #eee; border-left-color: #eee; }", "#install_script a.userjs { background: #ccc no-repeat scroll 0 0; border: 1px solid #ddd; border-left: 10px solid #888; border-radius: 0.25em; }", "#install_script a.userjs:hover { background: #ccc no-repeat scroll 0 0; }", "table.forums tr td.saU, #install_script a.saU { background-color: #ccc; border-left-color: #aaa; }", "table.forums .actions { float: right; font-size: 0.9em; margin-left: 1em; }", "table.forums .actions span { font-size: 0.8em; }", "table.forums .actions .action, table.forums .actions .toggle { color: #444; margin-left: 0.5em; text-decoration: none; }", "table.forums .actions .more { background: transparent url(" + GM_getResourceURL("more") + ") no-repeat scroll center bottom; cursor: pointer; height: 5px; padding: 4px 4px 0 4px; margin-left: 0.25em; width: 9px; }", "table.forums .actions .less { background: transparent url(" + GM_getResourceURL("less") + ") no-repeat scroll center bottom; cursor: pointer; height: 9px; padding: 0 6px; margin-left: 0.25em; width: 5px; }", "table.forums a.title { font-weight: bold; }", "table.forums tr td.saEMBED, #install_script a.saEMBED { background-image: linear-gradient(to left, #888, rgba(136,136,136,0.25), rgba(136,136,136,0)) !important; }", "table.forums tr td.saXCLUDE, #install_script a.saXCLUDE { background: #fff none repeat scroll 0 0; color: #000; }", "#install_script a.saXCLUDE:hover { background: #fff none repeat scroll 0 0; color: #000; }", "table.forums tr td.sabXCLUDE, #install_script a.sabXCLUDE { border-left-color: #ddd; }", "table.forums tr td.saLOW, #install_script a.saLOW { background: #d6efc2 repeat scroll 0 0; }", "#install_script a.saLOW:hover { background: #d6efc2 repeat scroll 0 0; }", "table.forums tr td.sabLOW, #install_script a.sabLOW { border-left-color: #b0d813; }", "table.forums tr td.saGUARD, #install_script a.saGUARD { background: #d5edf8 repeat scroll 0 0; }", "#install_script a.saGUARD:hover { background: #d5edf8 repeat scroll 0 0; }", "table.forums tr td.sabGUARD, #install_script a.sabGUARD { border-left-color: #92cae4; }", "table.forums tr td.saELEVATE, #install_script a.saELEVATE, table tr.unlisted { background: #fbfad5 repeat scroll 0 0; }", "#install_script a.saELEVATE:hover { background: #fbfad5 repeat scroll 0 0; }", "table.forums tr td.sabELEVATE, #install_script a.sabELEVATE { border-left-color: #fbf700; }", "table.forums tr td.saHIGH, #install_script a.saHIGH { background: #fbe5b0 repeat scroll 0 0; }", "#install_script a.saHIGH:hover { background: #fbe5b0 repeat scroll 0 0; }", "table.forums tr td.sabHIGH, #install_script a.sabHIGH { border-left-color: #fbbf5d; }", "table.forums tr td.saSEVERE, #install_script a.saSEVERE { background: #fbe3e4 repeat scroll 0 0; }", "#install_script a.saSEVERE:hover { background: #fbe3e4 repeat scroll 0 0; }", "table.forums tr td.sabSEVERE, #install_script a.sabSEVERE { border-left-color: #fb7e83; }", "table.forums tr td.sabABORT, #install_script a.saABORT { background: #000 none repeat scroll 0 0; color: #fff; }", "#install_script a.saABORT:hover { background: #000 none repeat scroll 0 0; color: #fff; }", "@-moz-keyframes saB { from { background: #888; } to { background: #fff; } }", ".saB { background: transparent none repeat scroll 0 0; -moz-animation: 1.5s ease 0s alternate none infinite saB !important; }", ".delusr { color: #fff; }", ".dim { opacity: 0.25; }", ".dim:hover { opacity: 1; }", ".byline { font-size: 0.9em; }", ".byline a:last-child { font-style: italic; }" ].join("\n") }); let contentNode = document.getElementById("content"); if (!gJSE && contentNode && document.title != "500 Server Error – Userscripts.org") { let nodeA = document.createElement("a"); nodeA.href = "/scripts/show/68219"; nodeA.textContent = "installWith"; let nodeSpan = document.createElement("span"); nodeSpan.textContent = "Enabling this sites JavaScript is highly recommended to improve your experience with "; let nodeP = document.createElement("p"); nodeP.classList.add("notice"); nodeP.classList.add("info"); nodeSpan.appendChild(nodeA); nodeSpan.appendChild(document.createTextNode(".")); nodeP.appendChild(nodeSpan); if (/^\/users\/\d+\/scripts/.test(gPATHNAME)) contentNode.parentNode.insertBefore(nodeP, contentNode); else contentNode.insertBefore(nodeP, contentNode.firstChild); } addEventListener("resize", onViewportChange, false); addEventListener("scroll", onViewportChange, false); onViewportChange(); } /** * */ function firstValueOf(aMb, aKey, aPrefix) { if (aPrefix) { if (aMb[aPrefix] && aMb[aPrefix][aKey]) return ((typeof aMb[aPrefix][aKey] == "string") ? aMb[aPrefix][aKey] : aMb[aPrefix][aKey][0]); } else { if (aMb[aKey]) return ((typeof aMb[aKey] == "string") ? aMb[aKey] : aMb[aKey][0]); } return undefined; } /** * */ function lastValueOf(aMb, aKey, aPrefix) { if (aPrefix) { if (aMb[aPrefix] && aMb[aPrefix][aKey]) return ((typeof aMb[aPrefix][aKey] == "string") ? aMb[aPrefix][aKey] : aMb[aPrefix][aKey][aMb[aPrefix][aKey].length - 1]); } else { if (aMb[aKey]) return ((typeof aMb[aKey] == "string") ? aMb[aKey] : aMb[aKey][aMb[aKey].length - 1]); } return undefined; } /** * */ function toArray(aName, aMb) { if (aMb) { if (aMb[aName]) return Array.isArray(aMb[aName]) ? aMb[aName] : [aMb[aName]]; } else return [aName]; return undefined; } /** * */ function addValue(aValue, aName, aMb) { if (aMb[aName]) { aMb[aName] = toArray(aName, aMb); aMb[aName].push(aValue); } else aMb[aName] = aValue; return aMb[aName]; // TODO: Opt } /** * */ function parseMeta(aString) { aString = aString.toString(); let re = /\/\/ @(\S+)(?:\s+(.*))?/, headers = {}, name, prefix, header, key, value, lines = aString.split(/[\r\n]+/).filter(function (e, i, a) { return (e.match(re)); }) ; for (let i = 0, line; line = lines[i++];) { [, name, value] = line.replace(/\s+$/, "").match(re); switch (name) { case "licence": name = "license"; break; } [key, prefix] = name.split(/:/).reverse(); if (key) { if (prefix) { if (!headers[prefix]) headers[prefix] = new Object; header = headers[prefix]; } else header = headers; if (header[key]) { if (!Array.isArray(header[key])) header[key] = new Array(header[key]); header[key].push(value || ""); } else header[key] = value || ""; } } if (headers["license"]) headers["licence"] = headers["license"]; return (headers.toSource() != "({})") ? headers : undefined; } /** * */ function isViewing(thisNode) { if (!thisNode || thisNode.nodeType !== 1) return false; if (!gJSE || gmcHome.get("disableViewportHold")) return true; /** Work-around for !javascript.enabled issue **/ let html, rect; html = document.documentElement; rect = thisNode.getBoundingClientRect(); // BUG: Needs gJSE to return meaningful values on FF 20+? return ( !!rect && rect.top <= html.clientHeight && rect.right >= 0 && rect.bottom >= 0 && rect.left <= html.clientWidth ); } /** * */ function addToQspList(aQsp, aItem) { if (aItem) aQsp += (!aQsp) ? aItem : "," + aItem; return aQsp; } /** * */ function appendToQs(aQs, aQsp) { if (aQsp) aQs += (!aQs) ? "?" + aQsp : "&" + aQsp; return aQs; } /** * */ function nag(ev) { ev.preventDefault(); if (!gmcHome.get("skipVerifyExclusion")) if (confirm('Are you sure?')) if (confirm('Are you really sure?')) if(confirm('Are you really, really sure?\n\nLast chance before impending doom?')) { ev.target.removeEventListener("click", nag, false); ev.target.click(); } } /** * */ function pingCount(ev) { let matches = ev.target.pathname.match(/(\d+)(?:\/\d+)?\.user\.js$/) if (matches) { let scriptId; [, scriptId] = matches; GM_xmlhttpRequest({ retry: gRETRIES, url: "http" + ((/^https:$/i.test(gPROTOCOL) || gmcHome.get("forceInstallSecure")) ? "s" : "") + "://userscripts.org" + gPORTX + "/scripts/source/" + scriptId + ".user.js", method: "HEAD", onload: function(aR) { switch(aR.status) { case 403: if (gmcHome.get("enableDebugging")) console.warn('Recently unlisted script'); break; case 404: if (gHALT404) this._retry = 0; case 500: case 502: case 503: if (gJSE && this.retry-- > 0) setTimeout(GM_xmlhttpRequest, gDELAYRETRYMIN + Math.round(Math.random() * (gDELAYRETRYMAX - gDELAYRETRYMIN)), this); // NOTE: Detached else { if (gmcHome.get("enableDebugging")) console.warn('Unable to increment script count for update method: ' + xhr.status); } break; case 200: break; } } }); } } /** * */ function create(aNode, aScriptId, aMb, aProviders, aKU, aUsoCMethod) { let thisNode = aNode.parentNode; let userjsNode = thisNode.querySelector(".userjs"); if (!userjsNode) return; GM_setStyle({ node: gCSS, data: [ "#install_script .userjs { font-size: 1.1em !important; }", "#install_script a.helpWith {", " background: #5173d9 linear-gradient(to bottom, #92cae4, rgba(213,237,248,0)) repeat scroll 0 0;", " border: 1px solid #999;", " -moz-border-radius: 1em;", " border-radius: 1em;", " color: #fff;", " float: right;", " font-weight: bold;", " height: 1.5em;", " margin-top: 6px;", " text-decoration: none;", " width: 1.4em;", "}", "#install_script a.helpWith:hover { background: #ddd; }", "#install_script select.updateWith { height: 24px; font-size: 0.9em; width: 88%; border: 3px solid #888; }", "#install_script select.updateWith option.separator { border-top: thin dotted #666; }", "#install_script select.updateWith img { background: none no-repeat scroll center center transparent; height: 16px; margin: 0.25em 0.25em 0.25em 0; vertical-align: middle; width: 16px; }", "#install_script select.updateWith img.indent { margin-left: 0.6em; }" ].join("\n") }); userjsNode.textContent = userjsNode.textContent + " with"; let helpNode = thisNode.querySelector(".help"); helpNode.classList.add("helpWith"); helpNode.textContent = "?"; let nodeImg = document.createElement("img"); nodeImg.src = GM_getResourceURL("uso"); let nodeText = document.createTextNode("userscripts.org (default)"); let nodeOption = document.createElement("option"); nodeOption.value = "uso"; nodeOption.title = "Use native provider"; let nodeSelect = document.createElement("select"); nodeSelect.id = "provider_id"; nodeSelect.classList.add("updateWith"); nodeSelect.addEventListener("change", function (ev) { if (aKU) gmc.set("providerPref1", this.value); else gmc.set("providerPref2", this.value); gmc.write(); switch (this.value) { case "uso": aNode.removeEventListener("click", pingCount, false); if (gISHOMEPAGE) gmc.close(); aNode.href = "/scripts/source/" + aScriptId + ".user.js"; if (gmcHome.get("forceInstallSecure")) aNode.protocol = "https:"; if (gmcHome.get("forceInstallRecent")) { aNode.pathname = aNode.pathname .replace(/\/source\//, "/version/") .replace(/(\.user\.js)$/, "/" + lastValueOf(aMb, "version", "uso") + "$1"); aNode.addEventListener("click", pingCount, false); } break; default: aNode.removeEventListener("click", pingCount, false); if (gISHOMEPAGE) gmc.close(); let thisProvider, sname, qs, max, min; for (let i = 0, thisProvider; thisProvider = aProviders[i++];) { [,,,,, sname,, qs, max, min] = thisProvider; if (sname == this.value) break; } let origin, useBeta, mirrorDomain = gmcHome.get("mirrorDomain"), useSSL = (mirrorDomain == "secure"); if (this.value == "usoCB") { useBeta = true; origin = "http://beta.usocheckup.dune.net"; } else { if (useSSL) origin = "https://secure.dune.net"; else if (mirrorDomain == "primary") origin = "http://usocheckup.dune.net"; else origin = "http://usocheckup.redirectme.net"; } let pathname = (useSSL && !useBeta ? "/usocheckup/" : "/") + aScriptId + ".user.js"; let search = ""; search = appendToQs(search, /^usoC/.test(this.value) ? "": "updater=" + this.value); search = appendToQs(search, max ? max + "=" + gmc.get("updaterMaxage") : ""); if (min && gmc.get("updaterMinage") != "1") search = appendToQs(search, min ? min + "=" + gmc.get("updaterMinage") : ""); if (gmcHome.get("allowAOU")) search = appendToQs(search, "allow=aou"); search = appendToQs(search, qs.replace(/\$1/, aScriptId)); let atUsoAvatar = lastValueOf(aMb, "avatar", "uso"), atUsoIcontype = lastValueOf(aMb, "icontype", "uso"), iconQspList = "" ; iconQspList = addToQspList(iconQspList, atUsoAvatar); if (true && atUsoIcontype) iconQspList = addToQspList(iconQspList, atUsoIcontype); if (iconQspList) search = appendToQs(search, "icon=" + (gmc.get("useGravatarIcon") || gmc.get("useScriptIcon") ? "1," : "0,") + iconQspList); let hash = "#.user.js"; aNode.href = origin + pathname + search + hash; /** Finish up gmc **/ if (gISFRAMELESS && gISHOMEPAGE) { gmc.fields["useGravatarIcon"].settings.label = "<img style='margin-right: 0.5em;' src='http" + (/^https:$/i.test(gPROTOCOL) ? "s" : "") + "://www.gravatar.com/avatar/" + atUsoAvatar + "?r=pg&s=48&default=identicon' alt='Use this authors gravatar when available if not present' title='Use this authors gravatar when available if not present' />"; gmc.fields["useScriptIcon"].settings.label = "<img src='" + gPROTOCOL + "//s3.amazonaws.com/uso_ss/icon/" + aScriptId + "/large." + atUsoIcontype + "' alt='Favor this scripts USO icon when available if not present' title='Favor this scripts USO icon when available if not present'/>"; gmc.open(); if (max) gmc.fields["updaterMaxage"].node.parentNode.classList.remove("hid"); else gmc.fields["updaterMaxage"].node.parentNode.classList.add("hid"); if (min) gmc.fields["updaterMinage"].node.parentNode.classList.remove("hid"); else gmc.fields["updaterMinage"].node.parentNode.classList.add("hid"); if (/^usoC/.test(this.value)) { switch (this.value) { case "usoCOS": case "usoCbU": gmc.fields["indirectMethod"].node.parentNode.classList.add("hid"); gmc.fields["directMethod"].node.parentNode.classList.add("hid"); break; case "usoCM": if (aUsoCMethod) { gmc.fields["indirectMethod"].node.parentNode.classList.add("hid"); gmc.fields["directMethod"].node.parentNode.classList.add("hid"); } else { gmc.fields["directMethod"].node.parentNode.classList.remove("hid"); gmc.fields["indirectMethod"].node.parentNode.classList.add("hid"); } break; case "usoCOI": gmc.fields["indirectMethod"].node.parentNode.classList.add("hid"); gmc.fields["directMethod"].node.parentNode.classList.remove("hid"); break; default: gmc.fields["indirectMethod"].node.parentNode.classList.remove("hid"); gmc.fields["directMethod"].node.parentNode.classList.add("hid"); break; } } else { gmc.fields["indirectMethod"].node.parentNode.classList.add("hid"); gmc.fields["directMethod"].node.parentNode.classList.add("hid"); } } if (/^usoC/.test(this.value)) { switch (this.value) { case "usoCOS": case "usoCbU": aNode.search = aNode.search.replace(/method\=(?:show|install|update)/i, "method=show"); break; case "usoCM": if (aUsoCMethod) aNode.search = aNode.search.replace(/method\=(?:show|install|update)/i, "method=" + aUsoCMethod); else aNode.search = aNode.search.replace(/method\=(?:show|install|update)/i, "method=" + gmc.get("directMethod")); if (/method\=update/.test(aNode.search)) aNode.addEventListener("click", pingCount, false); break; case "usoCOI": aNode.search = aNode.search.replace(/method\=(?:show|install|update)/i, "method=" + gmc.get("directMethod")); if (gmc.get("directMethod") == "update") aNode.addEventListener("click", pingCount, false); break; default: aNode.search = aNode.search.replace(/method\=(?:show|install|update)/i, "method=" + gmc.get("indirectMethod")); if (gmc.get("directMethod") == "update") aNode.addEventListener("click", pingCount, false); break; } } break; } }, false); nodeOption.appendChild(nodeImg); nodeOption.appendChild(nodeText); nodeSelect.appendChild(nodeOption); for (let i = 0, thisProvider; thisProvider = aProviders[i++];) { let stock, indent, icon, lname, separator, sname, tooltip; [stock, indent, icon, lname, separator, sname, tooltip] = thisProvider; nodeText = document.createTextNode(lname); nodeImg = document.createElement("img"); nodeImg.src = /^http/.test(icon) ? icon : "http" + (/^https:$/i.test(gPROTOCOL) ? "s" : "") + "://www.gravatar.com/avatar/" + icon + "?r=PG&s=92&default=identicon"; if (indent) nodeImg.classList.add("indent"); nodeOption = document.createElement("option"); nodeOption.value = sname; nodeOption.title = tooltip; if (separator) nodeOption.classList.add("separator"); nodeOption.appendChild(nodeImg); nodeOption.appendChild(nodeText); if (stock) nodeSelect.insertBefore(nodeOption, nodeSelect.firstChild.nextSibling); // NOTE: Reversed order else if (!aKU) nodeSelect.appendChild(nodeOption); } thisNode.insertBefore(nodeSelect, helpNode); let providerPreference; if (aKU) providerPreference = gmc.get("providerPref1"); else providerPreference = gmc.get("providerPref2"); for (let i = 0, thatNode; thatNode = nodeSelect.options[i]; ++i) if (thatNode.value == providerPreference) { nodeSelect.selectedIndex = i; break; } let ev = new CustomEvent("change"); nodeSelect.dispatchEvent(ev); } /** * */ function advise(aSa, aNode, aMb, aEmbed, aReduce, aCollapse, aHide) { //if (gmcHome.get("enableDebugging")) { //console.groupCollapsed(JSON.stringify(aMb, null, " ")); // BUG: FF 27 doesn't collapse these //console.groupEnd(); //} let title, max, deletedUser, advisories = [ "ABORT", "SEVERE", "HIGH", "ELEVATE", "GUARD", "LOW", "XCLUDE", "EMBED", "UNKNOWN", "INFO" ] ; advisories.forEach(function (e, i, a) { if (aSa[e]) { if (!max) max = e; if (!title) title = e + ":"; else title += "\n" + e + ":"; title += "\n " + aSa[e].join("\n "); } let sa = Array.isArray(aSa[e]) ? aSa[e] : [aSa[e]], advisory; for (let i = 0, len = sa.length; advisory = sa[i++];) { // NOTE: Post actions if (e == "ABORT" && aSa[e] == "Deleted user") { aReduce = true; aCollapse = true; if (gmcHome.get("alwaysHideDeletedUser")) aNode.parentNode.classList.add("hid"); else deletedUser = true; } } }); if (max) { if (aEmbed) aNode.classList.add("saEMBED"); aNode.classList.add("sa" + max); aNode.classList.add("sab" + max); } if (title) aNode.title = title; if (max == "INFO") { aNode.title = "UNKNOWN:\n Undetermined\n" + aNode.title; pushAdvisory(aSa, "UNKNOWN", "Undetermined"); } /** Sidebar **/ if (gISHOMEPAGE) { let hookNode = document.getElementById("script_sidebar"); if (hookNode) { GM_setStyle({ node: gCSS, data: [ "#script_sidebar h7 { display: block; font-weight: bold; }", "#script_sidebar h7 dl { margin-bottom: 0; font-size: 0.9em; }", "#script_sidebar h7 dt { font-weight: bold; padding: 0.25em 0.5em 0.5em 0.66em; }", "#script_sidebar h7 dd { font-weight: normal; font-style: italic; padding-left: 0.5em; padding-right: 0.33em; }", ".advisories { background-image: linear-gradient(to top, #ddd, rgba(255,255,255,0)); border: thin solid #aaa !important; border-radius: 0.25em 0.25em; cursor: default; font-family: sans-serif; font-weight: normal !important; padding: 0.25em 0.75em; text-align: left; width: auto; }", ".advisories:hover { background-image: linear-gradient(to top, #bfe1ff, rgba(237,249,255,0)); }", ".advisories a { margin-top: -0.0625em; position: absolute; right: 0.5em; }", ".advisories img { max-height: 1.5em; }", ".barlight { background-color: #eee; }", ".barmedium { background-color: #ddd; }" ].join("\n") }); advisories.reverse().forEach(function (e, i, a) { if (aSa[e]) { let nodeH7 = document.createElement("h7"); nodeH7.textContent = e; hookNode.insertBefore(nodeH7, hookNode.firstChild); let nodeDiv = document.createElement("div"); nodeDiv.classList.add("sa"); for (let j = 0, thisSummary; thisSummary = aSa[e][j]; j++) { let thisDescription = thisSummary.split("\n").map(function (e) { return e.trim(); }); let nodeDl = document.createElement("dl"); let nodeDt = document.createElement("dt"); nodeDt.textContent = thisDescription[0]; if (j % 2 == 0) nodeDt.classList.add("barlight"); for (let k = 1, thisClarification; thisClarification = thisDescription[k]; k++) { let nodeDd = document.createElement("dd"); nodeDd.textContent = thisClarification; if (k % 2 == 1) nodeDd.classList.add("barmedium"); nodeDt.appendChild(nodeDd); } nodeDl.appendChild(nodeDt); nodeDiv.appendChild(nodeDl); nodeH7.appendChild(nodeDiv); } } }); let nodeImg = document.createElement("img"); nodeImg.src = GM_getResourceURL("icon"); nodeImg.title = "uso - installWith"; nodeImg.alt = "installWith"; let nodeA = document.createElement("a"); nodeA.href = "/scripts/show/68219"; let nodeH6 = document.createElement("h6"); nodeH6.classList.add("advisories"); nodeH6.textContent = "Advisor"; nodeH6.addEventListener("click", function () { gmcFilters.open(); let aid = lastValueOf(aMb, "author", "uso"); if (aid) { gmcFilters.fields["lastScriptWrightId"].node.value = lastValueOf(aMb, "author", "uso"); // NOTE: Watchpoint gmcFilters.fields["lastScriptWrightId"].node.title = lastValueOf(aMb, "name", "uso"); } else gmcFilters.fields["lastScriptWrightId"].node.value = ""; gmcFilters.fields["lastUserScriptId"].node.value = lastValueOf(aMb, "script", "uso"); gmcFilters.fields["lastUserScriptId"].node.title = lastValueOf(aMb, "title", "uso"); }, false); nodeA.appendChild(nodeImg); nodeH6.appendChild(nodeA); hookNode.insertBefore(nodeH6, hookNode.firstChild); } } else { if (aHide && !/(^\/users\/.+?\/scripts|^\/home\/scripts|^\/scripts\/show\/\d+)/.test(gPATHNAME)) aNode.parentNode.classList.add("hid"); let actionsNodeDiv = document.createElement("div"); actionsNodeDiv.classList.add("actions"); aNode.insertBefore(actionsNodeDiv, aNode.firstChild); let titleNode, descNode; if (aMb) { titleNode = aNode.querySelector(".title"); if (titleNode) { if (aCollapse) { titleNode.classList.add("dim"); if (deletedUser) titleNode.classList.add("delusr"); } let maxLength = 50, // NOTE: Watchpoint atName = lastValueOf(aMb, "name"), atUsoScript = lastValueOf(aMb, "script", "uso"), title = titleNode.textContent ; let filterNodeA = document.createElement("a"); filterNodeA.classList.add("action"); filterNodeA.href = "#"; filterNodeA.textContent = "advisor"; filterNodeA.addEventListener("click", function (ev) { ev.preventDefault(); gmcFilters.open(); let aid = lastValueOf(aMb, "author", "uso"); if (aid) { gmcFilters.fields["lastScriptWrightId"].node.value = lastValueOf(aMb, "author", "uso"); // NOTE: Watchpoint gmcFilters.fields["lastScriptWrightId"].node.title = lastValueOf(aMb, "name", "uso"); } else gmcFilters.fields["lastScriptWrightId"].node.value = ""; gmcFilters.fields["lastUserScriptId"].node.value = lastValueOf(aMb, "script", "uso"); gmcFilters.fields["lastUserScriptId"].node.title = lastValueOf(aMb, "title", "uso"); }, false); let sourceNodeA = document.createElement("a"); sourceNodeA.classList.add("action"); sourceNodeA.href = "/scripts/review/" + atUsoScript; sourceNodeA.textContent = "source"; actionsNodeDiv.appendChild(sourceNodeA); actionsNodeDiv.appendChild(filterNodeA); if (atName) { let matches = title.match(/(.*)\.\.\.$/); if (matches && atName.length > maxLength) title = matches[1].trim(); let titlex = title.substr(0, maxLength).trim(), atNamex = atName.substr(0, titlex.length) ; if (atNamex != titlex) { titleNode.title = "@name " + atName; if (titlex.replace("\u200d", "", "g").trim() == "") { // NOTE: Watchpoint titleNode.textContent = atName; titleNode.classList.add("halb"); } else titleNode.classList.add("blah"); } else titleNode.title = "@name " + titleNode.title.trim(); } } descNode = aNode.querySelector(".desc"); if (descNode) { let maxLength = 250, // NOTE: Watchpoint atDescription = lastValueOf(aMb, "description"), desc = descNode.textContent ; if (atDescription) { let matches = desc.match(/(.*)\.\.\.$/); if (matches && atDescription.length > maxLength) desc = matches[1].trim(); let descx = desc.substr(0, maxLength).toLowerCase().trim(), atDescriptionx = atDescription.substr(0, descx.length).toLowerCase() ; if (atDescriptionx != descx) { descNode.classList.add("blah"); descNode.title = "@description " + atDescription; } else descNode.title = "@description " + atDescription; } else { descNode.classList.add("blah"); descNode.title = "undefined @description"; } } } let nodeImg = document.createElement("img"); nodeImg.classList.add("more"); nodeImg.src = GM_getResourceURL("clear"); nodeImg.alt = "hide"; nodeImg.addEventListener("click", unhideClick, false); actionsNodeDiv.appendChild(nodeImg); if (!/^(?:\/home\/scripts|\/users\/.+?\/scripts)/.test(gPATHNAME)) { let bylineNodeDiv = document.createElement("div"); bylineNodeDiv.classList.add("byline"); if (aCollapse) { bylineNodeDiv.classList.add("pus"); if (!gmcHome.get("alwaysShowAuthorId")) bylineNodeDiv.classList.add("hid"); else bylineNodeDiv.classList.add("dim"); } if (descNode) aNode.insertBefore(bylineNodeDiv, descNode); else aNode.appendChild(bylineNodeDiv); if (aMb) { let atUsoAuthor = lastValueOf(aMb, "author", "uso"), atUsoName = lastValueOf(aMb, "name", "uso"), atUsoVanity = lastValueOf(aMb, "vanity", "uso") ; if ((atUsoVanity && atUsoName) || atUsoAuthor) { bylineNodeDiv.appendChild(document.createTextNode("By ")); if (atUsoVanity && atUsoName) { let vanityNodeA = document.createElement("a"); vanityNodeA.href = "/users/" + atUsoVanity; vanityNodeA.textContent = atUsoName; bylineNodeDiv.appendChild(vanityNodeA); } if (atUsoAuthor) { bylineNodeDiv.appendChild(document.createTextNode(" (")); let authorNodeA = document.createElement("a"); authorNodeA.href = "/users/" + atUsoAuthor; authorNodeA.textContent = atUsoAuthor; bylineNodeDiv.appendChild(authorNodeA); bylineNodeDiv.appendChild(document.createTextNode(")")); } } } } if (aReduce) { nodeImg.classList.remove("more"); nodeImg.classList.add("less"); nodeImg.alt = "show"; if (descNode) descNode.classList.add("hid"); qNodes(gANODES); } } } /** * */ function pushAdvisory(aSa, aAdvisory, aComment) { aComment = toArray(aComment); if (!aSa[aAdvisory]) aSa[aAdvisory] = new Array(); for (let i = 0, comment; comment = aComment[i++];) { let found; for (let j = 0, commented; commented = aSa[aAdvisory][j++];) if (comment == commented) found = true; if (!found) aSa[aAdvisory].push(comment); } } /** * */ function validateAOU(aURL, aScriptId, aRe1, aRe2, aCb) { let matches = aURL.match(aRe1), match, REL; if (matches) { REL = true; [, match] = matches; aURL = gPROTOCOL + "//" + gHOSTNAME + "/scripts/source/" + match; } let protocols = aURL.match(/^(\w+:)/), protocol; if (protocols) { [, protocol] = protocols; let SSL, sid, source, ISI, DDS, RHV, BT; switch (protocol) { case "https:": SSL = true; case "http:": let matches = aURL.match(aRe2); if (matches) { let sid, source; [, sid, source] = matches; if (sid != aScriptId) ISI = true; if (source && source != "meta") DDS = true; } else { if (/^https?:\/\/userscripts.org(?::\d{1,5})?\/scripts\/\w+\/\d+.*\.(?:user|meta)\.js/.test(aURL)) BT = true; else RHV = true; } break; } aCb(REL, SSL, ISI, RHV, BT, DDS); } } /** * */ function parseList(aGroups, aCb) { for (let group in aGroups) { let scopes = aGroups[group]; // NOTE: Watchpoint for (let scope in scopes) { let target = scopes[scope]; for (let i = 0, len = target.length; i < len;) { let abstract, patterns, patternsx = {} ; [abstract, patterns] = [target[i], typeof target[i + 1] != "undefined" ? target[i + 1] : undefined]; ++i; let advisory, summary ; if (typeof abstract == "string") [, advisory, summary] = abstract.match(/(\w+) (.*)/); else continue; ++i; if (typeof patterns == "object") { if (Array.isArray(patterns)) { if (typeof patterns[0] != "string") continue; for (let i = 0, pattern; pattern = patterns[i++];) patternsx[pattern] = ""; } else patternsx = patterns; } else continue; let j = 0, tips, provider, collector, block, reduce, collapse, hide; for (; target[i + j] && typeof target[i + j] != "string"; ++j) { let optflag = target[i + j]; if (!!optflag[0]) { let verb; [, verb] = optflag; switch (verb) { case "tip": // `tip1,tip2,...` let comments; [,, comments] = optflag; if (typeof comments == "string") tips = comments.split(","); break; case "provide": optflag.shift(); optflag.shift(); // NOTE: No validation provider = optflag; break; case "collect": optflag.shift(); optflag.shift(); // NOTE: No validation collector = optflag; break; case "block": block = true; break; case "reduce": reduce = true; break; case "collapse": collapse = true; break; case "hide": hide = true; break; } } } i += (j - 1); aCb(scope, patternsx, advisory, summary, tips, block, reduce, collapse, hide, provider, collector); } } } } /** * */ function unhideClick(ev) { ev.preventDefault(); let targetNode = ev.target; if (targetNode.classList.contains("less")) { targetNode.classList.remove("less"); targetNode.classList.add("more"); targetNode.alt = "hide"; } else { targetNode.classList.remove("more"); targetNode.classList.add("less"); targetNode.alt = "show"; } let requeue; let descNode = targetNode.parentNode.parentNode.querySelector(".desc"); if (descNode) { if (!descNode.classList.contains("hid")) { descNode.classList.add("hid"); requeue = true; } else descNode.classList.remove("hid"); } else { if (gmcHome.get("enableDebugging")) console.error("Description node not found"); } let bylineNode = targetNode.parentNode.parentNode.querySelector(".byline"); if (bylineNode) { if (!gmcHome.get("alwaysShowAuthorId") && !bylineNode.classList.contains("hid") && bylineNode.classList.contains("pus")) { bylineNode.classList.add("hid"); requeue = true; } else bylineNode.classList.remove("hid"); } else { if (gmcHome.get("enableDebugging")) console.warn("Byline node not found"); } if (requeue) qNodes(gANODES); } /** * */ function parse(aSa, aNode, aScriptId, aMb, aSource) { let block, lib, KU, usoCMethod, ISI, DDS, RHV, BT, RN, REL, SSL, EMBED, REDUCE, COLLAPSE, HIDE ; let excludes = toArray("exclude", aMb); if (excludes) for (let i = 0, exclude; exclude = excludes[i++];) { if (exclude == "*") { pushAdvisory(aSa, "XCLUDE", "Possible library support file detected"); block = true; lib = true; if (gISHOMEPAGE && !gmcHome.get("skipVerifyExclusion")) aNode.addEventListener("click", nag, false); break; } } let updateURL = lastValueOf(aMb, "updateURL"); if (updateURL) validateAOU( updateURL, aScriptId, /^(\d+.*\.(?:meta|user)\.js)$/, /^https?:\/\/(?:.*\.)?userscripts\.org(?::\d{1,5})?\/scripts\/source\/(\d+).*\.(meta|user)\.js/, function (aREL, aSSL, aISI, aRHV, aBT, aDDS) { if (aISI) { ISI = true; REDUCE = true; } if (aREL) REL = true; if (aSSL) SSL = true; if (aRHV) RHV = true; if (aBT) BT = true; if (aDDS) DDS = true; } ); let downloadURL = lastValueOf(aMb, "downloadURL"), installURL = lastValueOf(aMb, "installURL") ; [ installURL, downloadURL ].forEach(function (e, i, a) { if (e) validateAOU( e, aScriptId, /^(\d+.*\.user\.js)$/, /^https?:\/\/(?:.*\.)?userscripts\.org(?::\d+)?\/scripts\/source\/(\d+).*\.user\.js/, function (aREL, aSSL, aISI, aRHV, aBT) { if (aISI) { ISI = true; REDUCE = true; } if (aREL) REL = true; if (aSSL) SSL = true; if (aRHV) RHV = true; if (aBT) BT = true; } ); }); let grants = toArray("grant", aMb); if (grants) for (let i = 0, grant; grant = grants[i++];) { if (grant == "none") { block = (lib) ? block : !gmcHome.get("allowUpdatersOnAOUgrantnone"); RN = (lib) ? RN : true; break; } } let atRequires = toArray("require", aMb), atIncludes = toArray("include", aMb), atMatches = toArray("match", aMb), atUsoScript = lastValueOf(aMb, "script", "uso"), atUsoAuthor = lastValueOf(aMb, "author", "uso"), atUsoTitle = lastValueOf(aMb, "title", "uso"), atUsoDesc = lastValueOf(aMb, "desc", "uso"), providers = [] ; let rewrite, json, GROUPS; try { // TODO: Watchpoint GROUPS = JSON.parse(gLIST + '}'); let jsonFilters = gmcFilters.get("jsonFilters"); json = JSON.parse(jsonFilters); gGROUPS = JSON.parse(gLIST + ',"user":{' + jsonFilters.replace(/^[\n\r\s]*\{/, '') + '}'); } catch (e) { if (gmcHome.get("enableDebugging")) console.warn('JSON parsing error...skipping user advisories'); gGROUPS = JSON.parse(gLIST + '}'); } parseList(gGROUPS, function (aScope, aPatterns, aAdvisory, aSummary, aTips, aBlock, aReduce, aCollapse, aHide, aProvider, aCollector) { for (let pattern in aPatterns) { let matches = pattern.match(/^\/(.*)\/(i?g?m?y?)$/), patternx = pattern; if (matches) patternx = new RegExp(matches[1].replace(/\$1/, aScriptId), matches[2]); if (aScope == "updater" && atRequires) for (let i = 0, atRequire; atRequire = atRequires[i++];) { let matches = (typeof patternx == "object") ? atRequire.match(patternx) : (atRequire == patternx) ? [atRequire, patternx] : null; if (matches) { if (/usocheckup/.test(matches[0])) { let matches = atRequire.match(/method\=(\w+)/); if (matches) usoCMethod = matches[1]; else usoCMethod = "show"; } let sid = matches[1]; if (sid == aScriptId || sid == null) { pushAdvisory(aSa, aAdvisory, aSummary + (aPatterns[pattern] ? " " + aPatterns[pattern] : "") + (aTips ? "\n " + aTips.join("\n ") : "")); KU = true; } else { pushAdvisory(aSa, "SEVERE", aSummary + "\n Possible malformed updater syntax"); REDUCE = true; block = true; break; } } } if (aScope == "@include" && atMatches) for (let i = 0, atMatch; atMatch = atMatches[i++];) if (atMatch.search(patternx) > -1) { pushAdvisory(aSa, aAdvisory, aSummary); if (aReduce) REDUCE = true; break; } if (aScope == "@include" && atIncludes) { for (let i = 0, atInclude; atInclude = atIncludes[i++];) if (atInclude.search(patternx) > -1) { pushAdvisory(aSa, aAdvisory, aSummary); if (aReduce) REDUCE = true; break; } } else if (!atMatches && !atIncludes && !lib ) { REDUCE = true; pushAdvisory(aSa, "ELEVATE", "Possible implicit global web inclusion"); } if (/^\@uso:author(?:$|\s)/.test(aScope) && atUsoAuthor) if (atUsoAuthor.search(patternx) > -1) { if (aSummary == "Potentially unwanted script") { block = true; REDUCE = true; COLLAPSE = true; if (gmcHome.get("alwaysHidePus")) HIDE = true; } pushAdvisory(aSa, aAdvisory, aSummary + (aTips ? "\n " + aTips.join("\n ") : "")); if (aBlock) block = true; if (aReduce) REDUCE = true; if (aCollapse) COLLAPSE = true; } if (/^\@uso:script(?:$|\s)/.test(aScope) && atUsoScript) if (atUsoScript.search(patternx) > -1) { if (aSummary == "Potentially unwanted script") { block = true; REDUCE = true; COLLAPSE = true; if (gmcHome.get("alwaysHidePus")) HIDE = true; } pushAdvisory(aSa, aAdvisory, aSummary + (aPatterns[pattern] ? " " + aPatterns[pattern] : "") + (aTips ? "\n " + aTips.join("\n ") : "")); if (aBlock) block = true; if (aReduce) REDUCE = true; if (aCollapse) COLLAPSE = true; } if (aScope == "@uso:title" && atUsoTitle) { if (atUsoTitle.search(patternx) > -1) { if (aSummary == "Potentially unwanted script") { block = true; REDUCE = true; COLLAPSE = true; if (gmcHome.get("alwaysHidePus")) HIDE = true; } pushAdvisory(aSa, aAdvisory, aSummary + (aPatterns[pattern] ? " " + aPatterns[pattern] : "") + (aTips ? "\n " + aTips.join("\n ") : "")); if (aBlock) block = true; if (aReduce) REDUCE = true; if (aCollapse) COLLAPSE = true; if (json && aCollector && !/^(?:\/home\/scripts|\/users\/.+?\/scripts|\/scripts\/show\/\d+)/.test(gPATHNAME)) { let scope, advisorysummary; [scope, advisorysummary] = aCollector; let collect, id; switch (scope) { case "@uso:author": collect = true; id = atUsoAuthor; break; } if (collect && id) { if (!json[scope]) { json[scope] = [advisorysummary, []]; rewrite = true; } let found, ids = json[scope][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); if (!found && json[scope + " (private)"]) { ids = json[scope + " (private)"][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found && GROUPS && GROUPS["collections"][scope]) { ids = GROUPS["collections"][scope][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found) { json[scope][1].push(id); // TODO: rewrite = true; } } } } } if (aScope == "@uso:desc" && atUsoDesc) { if (atUsoDesc.search(patternx) > -1) { if (aSummary == "Potentially unwanted script") { block = true; REDUCE = true; COLLAPSE = true; if (gmcHome.get("alwaysHidePus")) HIDE = true; } pushAdvisory(aSa, aAdvisory, aSummary + (aPatterns[pattern] ? " " + aPatterns[pattern] : "") + (aTips ? "\n " + aTips.join("\n ") : "")); if (aBlock) block = true; if (aReduce) REDUCE = true; if (aCollapse) COLLAPSE = true; if (json && aCollector && !/^(?:\/home\/scripts|\/users\/.+?\/scripts|\/scripts\/show\/\d+)/.test(gPATHNAME)) { let scope, advisorysummary; [scope, advisorysummary] = aCollector; let collect, id; switch (scope) { case "@uso:author": collect = true; id = atUsoAuthor; break; } if (collect && id) { if (!json[scope]) { json[scope] = [advisorysummary, []]; rewrite = true; } let found, ids = json[scope][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); if (!found && json[scope + " (private)"]) { ids = json[scope + " (private)"][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found && GROUPS && GROUPS["collections"][scope]) { ids = GROUPS["collections"][scope][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found) { json[scope][1].push(id); // TODO: rewrite = true; } } } } } if (aScope == "updaterEmbed" && aSource) { if (aSource.search(patternx) > -1 && aScriptId != 68219 && aScriptId != 69307) { EMBED = true; pushAdvisory(aSa, aAdvisory, aSummary + (aPatterns[pattern] ? " " + aPatterns[pattern] : "") + (aTips ? "\n " + aTips.join("\n ") : "")); } } if (aScope == "search" && aSource) { if (aSource.search(patternx) > -1) { if (aSummary == "Potentially unwanted script") { block = true; REDUCE = true; COLLAPSE = true; if (gmcHome.get("alwaysHidePus")) HIDE = true; } pushAdvisory(aSa, aAdvisory, aSummary + (aPatterns[pattern] ? " " + aPatterns[pattern] : "") + (aTips ? "\n " + aTips.join("\n ") : "")); if (aReduce) REDUCE = true; if (json && aCollector && !/^(?:\/home\/scripts|\/users\/.+?\/scripts|\/scripts\/show\/\d+)/.test(gPATHNAME)) { let scope, advisorysummary; [scope, advisorysummary] = aCollector; let collect, id; switch (scope) { case "@uso:author": collect = true; id = atUsoAuthor; break; } if (collect && id) { if (!json[scope]) { json[scope] = [advisorysummary, []]; rewrite = true; } let found, ids = json[scope][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); if (!found && json[scope + " (private)"]) { ids = json[scope + " (private)"][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found && GROUPS && GROUPS["collections"][scope]) { ids = GROUPS["collections"][scope][1]; // TODO: ids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found) { json[scope][1].push(id); // TODO: rewrite = true; } } } } } if (aProvider) providers.push(aProvider); } }); if (json && rewrite) { json["@uso:author"][1].sort(function (a, b) { return a - b }); gmcFilters.set("jsonFilters", JSON.stringify(json, null, "")); // TODO: gmcFilters.write(); } /** **/ let msgDDS = "AOU\n Possible DDoS attack script and/or Privacy Loss", msgRHV = "AOU\n Possible Remotely Hosted Version or bad target", msgBT = "AOU\n Possible bad target and/or Privacy Loss", msgISI = "AOU\n Possible incorrect scriptid applied for updates", msgRN = "Restricted (content scope) namespace script" ; if (DDS) pushAdvisory(aSa, "SEVERE", msgDDS); if (RHV) pushAdvisory(aSa, "HIGH", msgRHV); if (BT) pushAdvisory(aSa, "HIGH", msgBT); if (RN) pushAdvisory(aSa, "ELEVATE", msgRN); if (ISI) pushAdvisory(aSa, "SEVERE", msgISI); if (KU && RN) { pushAdvisory(aSa, "ABORT", "Known updater and restricted (content scope) namespace are incompatible"); block = true; } advise(aSa, aNode, aMb, EMBED, REDUCE, COLLAPSE, HIDE); if (/^\/(?:scripts|topics)\//.test(gPATHNAME)) { if (block || (gmcHome.get("allowAOU") && (DDS || RHV || BT)) || (gmcHome.get("allowAOU") && ISI) || aMb["uso"]["unlisted"] == "") { if (gmcHome.get("forceInstallSecure")) aNode.protocol = "https:"; if (gmcHome.get("forceInstallRecent")) aNode.pathname = aNode.pathname .replace(/\/source\//, "/version/") .replace(/(\.user\.js)$/, "/" + lastValueOf(aMb, "version", "uso") + "$1"); } else create(aNode, atUsoScript, aMb, providers, KU, usoCMethod); } } /** * */ function unitSizer(aNumber) { if (typeof aNumber == "string") aNumber = parseInt(aNumber); return ( (aNumber >= 1024) ? (aNumber >= 1048576) ? parseInt(aNumber / 1024 / 1024 * 100) / 100 + " MiB" : parseInt(aNumber / 1024 * 100) / 100 + " KiB" : aNumber + " B" ); } /** * */ function onError() { // NOTE: GM BUG with aR so don't use if (gmcHome.get("enableNabAuthorId")) { let contentNode = document.getElementById("content"); if (contentNode) { let loginMsgNode = contentNode.querySelector("p.notice a[href$=login]"); if (!loginMsgNode && !gLoginTried) { gLoginMsgShown = true; let nodeP; if (document.body.classList.contains("anon") && gmcHome.get("enableNabAuthorId")) { let loginNodeA = document.createElement("a"); loginNodeA.href = "/login"; loginNodeA.textContent = "login"; let installWithNodeA = document.createElement("a"); installWithNodeA.href = "/scripts/show/68219"; installWithNodeA.textContent = "installWith"; let nodeSpan = document.createElement("span"); nodeSpan.textContent = "You may be able to reduce your bandwidth usage with a visit to the "; nodeP = document.createElement("p"); nodeP.classList.add("notice"); nodeP.classList.add("info"); nodeSpan.appendChild(loginNodeA); nodeSpan.appendChild(document.createTextNode(" page while using ")); nodeSpan.appendChild(installWithNodeA); nodeSpan.appendChild(document.createTextNode(".")); nodeP.appendChild(nodeSpan); if (/^\/users\/\d+\/scripts/.test(gPATHNAME)) contentNode.parentNode.insertBefore(nodeP, contentNode); else contentNode.insertBefore(nodeP, contentNode.firstChild); } if (gmcHome.get("enableAutoSession")) { gLoginTrying = true; GM_xmlhttpRequest({ retry: gRETRIES, url: "http" + ((/^https:$/i.test(gPROTOCOL) || gmcHome.get("forceInstallSecure")) ? "s" : "") + "://userscripts.org" + gPORTX + "/login", method: "HEAD", onload: function (aR) { switch(aR.status) { case 404: if (gHALT404) this._retry = 0; case 500: case 502: case 503: if (gJSE && this.retry-- > 0) setTimeout(GM_xmlhttpRequest, gDELAYRETRYMIN + Math.round(Math.random() * (gDELAYRETRYMAX - gDELAYRETRYMIN)), this); // NOTE: Detached else { if (gmcHome.get("enableDebugging")) console.warn('Unable to establish session'); } break; case 200: gBYTESMIN = undefined; gLoginTried = true; gLoginTrying = false; break; default: if (gmcHome.get("enableDebugging")) console.warn('Untrapped status code: ' + aR.status); break; } } }); } } } gBYTESMIN = 0; // NOTE: Watchpoint gBYTESMAX = parseInt(gBYTESMAX / gANONDIVISOR); } gIdle = true; onViewportChange(); } /** * */ function onLoad(aR) { switch (aR.status) { case 404: if (gHALT404) this._retry = 0; case 500: case 502: case 503: if (gJSE && this._retry-- > 0) setTimeout(GM_xmlhttpRequest, gDELAYRETRYMIN + Math.round(Math.random() * (gDELAYRETRYMAX - gDELAYRETRYMIN)), this); // NOTE: Detached else { if (/\.meta\.js$/.test(this.url)) { pushAdvisory(this._sa, "ABORT", "Unable to retrieve script metadata"); this._mb = {}; this._mb["uso"] = {}; this._mb["uso"]["script"] = this._scriptId; } else if (/\.user\.js$/.test(this.url)) pushAdvisory(this._sa, "ABORT", "Unable to retrieve script source"); else pushAdvisory(this._sa, "UNKNOWN", "Unable to retrieve authorship"); advise(this._sa, this._node, this._mb); this._node.classList.remove("saB"); gQNODES.shift(); xhr.call(gTHIS, this); } break; case 200: case 206: if (/\.meta\.js$/.test(this.url)) { this._mb = parseMeta(aR.responseText); if (!this._mb) { pushAdvisory(this._sa, "ABORT", "Unable to retrieve script metadata"); advise(this._sa, this._node, this._mb); this._node.classList.remove("saB"); gQNODES.shift(); xhr.call(gTHIS, this); return; } let pageMetaVersion = document.querySelector("meta[name='uso:version']"); if (pageMetaVersion && gISHOMEPAGE) if (lastValueOf(this._mb, "version", "uso") != pageMetaVersion.content) { pushAdvisory(this._sa, "ABORT", "meta.js @uso:version and page @uso:version DO NOT MATCH"); advise(this._sa, this._node, this._mb); this._node.classList.remove("saB"); gQNODES.shift(); xhr.call(gTHIS, this); return; } if (lastValueOf(this._mb, "script", "uso") != this._scriptId) { pushAdvisory(this._sa, "SEVERE", "Malformed metadata block"); addValue(this._scriptId, "script", this._mb["uso"]); } /** Create phantom key(s) if detected **/ if (this._node.classList.contains("userjs")) { if (/\?token=/.test(this._node)) this._mb["uso"]["unlisted"] = ""; } else { let emNode = this._node.querySelector("em"); if (emNode && emNode.textContent == "unlisted") this._mb["uso"]["unlisted"] = ""; } let titleNode = this._node.querySelector(".title") || this._node.parentNode.parentNode.querySelector(".title"); if (titleNode) addValue(titleNode.textContent, "title", this._mb["uso"]); else addValue("", "title", this._mb["uso"]); let descNode = this._node.querySelector(".desc"); if (descNode) addValue(descNode.textContent, "desc", this._mb["uso"]); else { let summaries = document.querySelectorAll("#root #content .script_summary"); for (let i = 0, thisNode; thisNode = summaries[i++];) { let bNode = thisNode.querySelector("p b"); if (bNode && bNode.textContent.match(/^Script\sSummary\:$/i)) { descNode = bNode.nextSibling; addValue(descNode.textContent.replace(/^[\r\n]/, "").replace(/[\r\n]$/, ""), "desc", this._mb["uso"]); } } } if (!descNode) addValue("", "desc", this._mb["uso"]); let user_idNode = document.body.querySelector("#heading .author a"); if (user_idNode) { addValue(user_idNode.getAttribute("user_id"), "author", this._mb["uso"]); addValue(user_idNode.textContent, "name", this._mb["uso"]); let matches = user_idNode.getAttribute("gravatar").match(/^.+?(?:gravatar_id\=(.+?)|\/avatar\/(.+?))[\?\&]/); if (matches) addValue(matches[1] || matches[2], "avatar", this._mb["uso"]); else addValue("", "avatar", this._mb["uso"]); } else if (/^\/users\/.+?\/scripts/.test(gPATHNAME)) { user_idNode = document.querySelector("#section .container h2 a"); //document.querySelector(".avatar a"); if (user_idNode) { let aid = user_idNode.pathname.match(/\/(\d+)$/); if (aid) { addValue(aid[1], "author", this._mb["uso"]); addValue(user_idNode.textContent, "name", this._mb["uso"]); let gravatarNode = document.querySelector(".avatar a img"); if (gravatarNode) { let gid = gravatarNode.src.match(/^.+?(?:gravatar_id\=(.+?)|\/avatar\/(.+?))[\?\&]/); if (gid) addValue(gid[1] || gid[2], "avatar", this._mb["uso"]); } else addValue("", "avatar", this._mb["uso"]); } else { addValue("", "author", this._mb["uso"]); addValue("", "name", this._mb["uso"]); addValue("", "avatar", this._mb["uso"]); } } else { addValue("", "author", this._mb["uso"]); addValue("", "name", this._mb["uso"]); addValue("", "avatar", this._mb["uso"]); } } else { addValue("", "author", this._mb["uso"]); addValue("", "name", this._mb["uso"]); addValue("", "avatar", this._mb["uso"]); } let iconNode = document.getElementById("icon"); if (iconNode) { let matches = iconNode.pathname.match(/\.(\w+)$/); if (matches) { addValue(matches[1], "icontype", this._mb["uso"]); } else addValue("", "icontype", this._mb["uso"]); } else addValue("", "icontype", this._mb["uso"]); addValue(aR.responseText.length.toString(), "metajssize", this._mb["uso"]); let stats = []; let matches = aR.responseText.match(/\n/g); // NOTE: Meta should always have at least one newline if (matches) { addValue((matches.length + 1).toString(), "metajslines", this._mb["uso"]); stats.push(unitSizer(lastValueOf(this._mb, "metajssize", "uso")) + " with " + lastValueOf(this._mb, "metajslines", "uso") + " lines"); } let ws, nws; matches = aR.responseText.match(/\s/g); if (matches) { ws = matches.length; addValue(ws.toString(), "metajsws", this._mb["uso"]); } matches = aR.responseText.match(/\S/g); if (matches) { nws = matches.length; addValue(nws.toString(), "metajsnws", this._mb["uso"]); } stats.push(parseInt(ws / (ws + nws) * 10000) / 100 + "% whitespace"); pushAdvisory(this._sa, "INFO", "Raw meta.js\n " + stats.join("\n ")); /** **/ if (this._mb["uso"]["unlisted"] == "") // NOTE: Self unlisting phantom if present pushAdvisory(this._sa, "ELEVATE", "Unlisted script"); if (( /^\/$/.test(gPATHNAME) && gmcHome.get("scanMainDepth") == "deep" || /^\/tags\//.test(gPATHNAME) && gmcHome.get("scanTagsDepth") == "deep" || /^\/scripts(?:\/?$|\/search\/?$)/.test(gPATHNAME) && gmcHome.get("scanScriptsDepth") == "deep" || /^\/groups\/\d+\/scripts/.test(gPATHNAME) && gmcHome.get("scanGroupsDepth") == "deep" || /(^\/users\/.+?\/(?:scripts|favorites)|^\/home\/(?:scripts|favorites))/.test(gPATHNAME) && gmcHome.get("scanScriptWrightDepth") == "deep" || /^\/(?:scripts\/show|topics)/.test(gPATHNAME) && !gmcHome.get("disableScanDeep") ) && this._mb["uso"]["unlisted"] != "" ) { this.url = this.url.replace(/\/source\/(\d+)\.meta\.js$/, "/version/$1/" + lastValueOf(this._mb, "version", "uso") + ".user.js"); this._retry = gRETRIES; GM_xmlhttpRequest.call(gTHIS, this); } else { addValue("", "userjs", this._mb["uso"]); let atUsoAuthor = lastValueOf(this._mb, "author", "uso"); if (gmcHome.get("enableNabAuthorId") && !atUsoAuthor && !/^\/home\/scripts/.test(gPATHNAME)) { this.url = "/scripts/show/" + this._scriptId; this.headers = { "Range": "bytes=" + (gBYTESMIN ? gBYTESMIN : 0) + "-" + (gBYTESMAX ? gBYTESMAX : "") }; if (gmcHome.get("enableDebugging")) console.info(this.headers.Range); this._retry = gRETRIES; GM_xmlhttpRequest.call(gTHIS, this); } else { parse(this._sa, this._node, this._scriptId, this._mb); this._node.classList.remove("saB"); gQNODES.shift(); xhr.call(gTHIS, this); } } } else if (/\.user\.js$/.test(this.url)) { /** Add some keys **/ addValue(aR.responseText, "userjs", this._mb["uso"]); addValue(aR.responseText.length.toString(), "userjssize", this._mb["uso"]); let stats = []; let matches = aR.responseText.match(/\n/g); // NOTE: Script should always have at least one newline if (matches) { addValue((matches.length + 1).toString(), "userjslines", this._mb["uso"]); stats.push(unitSizer(lastValueOf(this._mb, "userjssize", "uso")) + " with " + lastValueOf(this._mb, "userjslines", "uso") + " lines"); } let ws, nws; matches = aR.responseText.match(/\s/g); if (matches) { ws = matches.length; addValue(ws.toString(), "userjsws", this._mb["uso"]); } matches = aR.responseText.match(/\S/g); if (matches) { nws = matches.length; addValue(nws.toString(), "userjsnws", this._mb["uso"]); } stats.push(parseInt(ws / (ws + nws) * 10000) / 100 + "% whitespace"); pushAdvisory(this._sa, "INFO", "Raw user.js\n " + stats.join("\n ")); let atUsoAuthor = lastValueOf(this._mb, "author", "uso"); if (gmcHome.get("enableNabAuthorId") && !atUsoAuthor && !/^\/home\/scripts/.test(gPATHNAME)) { this.url = "/scripts/show/" + this._scriptId; this.headers = { "Range": "bytes=" + (gBYTESMIN ? gBYTESMIN : 0) + "-" + (gBYTESMAX ? gBYTESMAX : "") }; if (gmcHome.get("enableDebugging")) console.info(this.headers.Range); this._retry = gRETRIES; GM_xmlhttpRequest.call(gTHIS, this); } else { /** Remove some keys **/ let userjs = lastValueOf(this._mb, "userjs", "uso").replace(/\s+\/\/\s@(?:updateURL|installURL|downloadURL|exclude)\s+.*[^\n\r]/gm, ""); parse(this._sa, this._node, this._scriptId, this._mb, userjs); this._node.classList.remove("saB"); gQNODES.shift(); xhr.call(gTHIS, this); } } else if (/\/scripts\/show\/\d+$/.test(this.url)) { let parser = new DOMParser(), doc = parser.parseFromString(aR.responseText, "text/html"), retry ; let titleNode = doc.querySelector(".title"); if (titleNode) addValue(titleNode.textContent, "title", this._mb["uso"]); // TODO: "desc" if resolved let author = doc.querySelector("span.author"); if (author) { let vcard = author.querySelector("a"); if (vcard) { addValue(vcard.getAttribute("user_id"), "author", this._mb["uso"]); let matches = vcard.getAttribute("gravatar").match(/^.+?(?:gravatar_id\=(.+?)|\/avatar\/(.+?))[\?\&]/); if (matches) addValue(matches[1] || matches[2], "avatar", this._mb["uso"]); matches = vcard.getAttribute("href").match(/\/users\/(.*)/); if (matches) addValue(matches[1] || matches[2], "vanity", this._mb["uso"]); addValue(vcard.textContent, "name", this._mb["uso"]); } else { if (author.textContent == "By deleted user") { pushAdvisory(this._sa, "ABORT", "Deleted user"); } } } else { gBYTESMIN = undefined; // NOTE: Force a reset during login retry = true; // NOTE: Rerun current request if (gmcHome.get("enableDebugging")) { console.error('No ScriptWright id found in fragment for url: ' + this.url); console.warn(aR.responseText); } } this.headers = undefined; if (!retry) { let userjs; /** Optionally remove some keys **/ if (this._mb["uso"]["userjs"]) userjs = lastValueOf(this._mb, "userjs", "uso").replace(/\s+\/\/\s@(?:updateURL|installURL|downloadURL|exclude)\s+.*[^\n\r]/gm, ""); parse(this._sa, this._node, this._scriptId, this._mb, userjs); this._node.classList.remove("saB"); gQNODES.shift(); } if (gQNODES.length > 0) { // Recalculate low and high bytes for next node if (!this.headLength) this.headLength = byteLength(doc.documentElement.getElementsByTagName("head")[0].innerHTML) - byteLength(doc.title) + gHEADLENADJ; let titleTextNode = gQNODES[0].querySelector("a.title").textContent; let lenTitle = byteLength(titleTextNode); if (/\.\.\.$/.test(titleTextNode) && titleTextNode.length == 50) lenTitle = 255 * 4; // WATCHPOINT: Set to max bytes of unicode since unknown lenTitle += byteLength(" for Greasemonkey"); let len = this.headLength - lenTitle; let low = len + lenTitle; let high = parseInt(len) + (lenTitle * 2) + (80 * 2) + gTITLELENADJ; if (gBYTESMIN !== 0) { gBYTESMIN = low; gBYTESMAX = high; } else { gBYTESMIN = 0; if (gLoginTrying) gBYTESMAX = high; else gBYTESMAX = parseInt(high / gANONDIVISOR); } } else { gBYTESMIN = undefined; gBYTESMAX = undefined; } if (retry) { this._retry = gRETRIES; GM_xmlhttpRequest.call(gTHIS, this); } else xhr.call(gTHIS, this); } break; default: pushAdvisory(this._sa, "ABORT", "Untrapped status code: " + aR.status); advise(this._sa, this._node, this._mb); this._node.classList.remove("saB"); gQNODES.shift(); xhr.call(gTHIS, this); break; } } /** * */ function xhr(aReq) { if (gQNODES.length > 0) { gIdle = false; let thisNode = gQNODES[0]; if (thisNode) { thisNode.classList.add("saB"); let thatNode; if (thisNode.classList.contains("userjs")) thatNode = thisNode; else thatNode = thisNode.querySelector(".title"); let scriptId; [, scriptId] = thatNode.pathname.match(/(\d+).*$/); aReq._retry = gRETRIES; aReq._sa = {}; aReq._node = thisNode; aReq._scriptId = scriptId; aReq._mb = null; aReq.url = "/scripts/source/" + scriptId + ".meta.js"; GM_xmlhttpRequest(aReq); } } else { gIdle = true; } } /** * */ function qNodes(aNodes) { for (let i = 0, thisNode; thisNode = aNodes[i++];) if (isViewing(thisNode) && !thisNode.classList.contains("saU")) { thisNode.classList.add("saU"); gQNODES.push(thisNode); } if (gIdle) xhr({ method: "GET", onload: onLoad, onerror: onError }); } /** * */ function onViewportChange() { qNodes(gANODES); } /** * */ function insertHook() { let hookNode = document.getElementById("full_description"); if (hookNode && !hookNode.firstChild) return hookNode.appendChild(document.createElement("div")); else if (hookNode) return (hookNode.insertBefore(document.createElement("div"), hookNode.firstChild)); else { hookNode = document.getElementById("content"); if (hookNode) { let nodeDiv = document.createElement("div"); let full_descriptionNodeDiv = document.createElement("div"); full_descriptionNodeDiv.id = "full_description"; full_descriptionNodeDiv.appendChild(nodeDiv); return hookNode.appendChild(full_descriptionNodeDiv); } else { if (gmcHome.get("enableDebugging")) console.log("ERROR: USO DOM change detected... appending GMC remote to EoD"); return document.body.appendChild(document.createElement("div")); } } } /** * main'ish */ /** Clean up USO for framed presentation **/ if (!gISFRAMELESS && /^\/scripts\/show\/\d+#heading/.test(gPATHNAME + gHASH)) { aNodes = document.body.querySelectorAll("a"); for (let i = 0, thisNode; thisNode = aNodes[i++];) thisNode.target = "_top"; GM_setStyle({ node: gCSS, data: [ "div.container { width: auto; margin: 0; }", "div#content { width: 100% !important; left: 0; }", "div#heading { height: 66px; min-height: 0; }", "div#details h1.title { max-height: 2.05em; overflow: hidden; }", "#section > .container { width: auto !important; }", "#section_search { display: none !important; }", "#install_script { bottom: auto !important; top: 10px !important; margin-right: 5px; }" ].join("\n") }); } /** Nearest fix(es) for any glitches with UAC/USO **/ if (gUAC) GM_setStyle({ node: gCSS, data: [ "div #full_description { width: 98.6%; }", "#screenshots { width: 98% !important; }", "#activity, #topics { float: inherit !important; }" // Alternative: "h6 { clear: both; }", ].join("\n") }); else GM_setStyle({ node: gCSS, data: [ "div #full_description { width: 97.9%; }" ].join("\n") }); /** **/ if (typeof GM_configStruct == "undefined") { if (gmcHome.get("enableDebugging")) { let msg = 'Fatal error. GM_config not found'; console.error(msg); } return; } GM_config = undefined; let gmcHome = new GM_configStruct(); gmcHome.id = "gmc68219home"; gmcHome.init( gISHOMEPAGE ? insertHook() : "", [ '<img alt="installWith" title="uso – installWith" src="' + GM_getResourceURL("icon") + '" />', '<p>Preferences</p>', '<span>', '<a href="/guides/24/">', '<img alt="usoCheckup" title="Powered in part by usoCheckup" src="' + GM_getResourceURL("usoc") + '" />', '</a>', '<a href="' + gPROTOCOL + '//github.com/sizzlemctwizzle/GM_config/wiki/">', '<img alt="GM_config" title="Powered in part by GM_config" src="' + GM_getResourceURL("gmc") + '" />', '</a>', '</span>' ].join(""), GM_setStyle({ node: null, data: [ "@media screen, projection {", "#gmc68219home { position: static !important; z-index: 0 !important; width: auto !important; height: auto !important; max-height: none !important; max-width: none !important; margin: 0 0 0.5em 0 !important; border: 1px solid #ddd !important; clear: right !important; }", "#gmc68219home_header a { display: inline; }", "#gmc68219home_header img { max-height: 32px; margin-right: 0.125em; vertical-align: middle; }", "#gmc68219home_header > p { display: inline; margin: 0; vertical-align: middle; }", "#gmc68219home_header span { float: right; }", "#gmc68219home_header span > a { display: inline; margin-left: 0.25em; }", "#gmc68219home_wrapper { background-color: #eee; padding-bottom: 0.25em; }", "#gmc68219home .config_header { background-color: #333; color: #fff; font-size: 1.57em; margin: 0; padding: 0 0.5em; text-align: left; }", "#gmc68219home .config_var { clear: both; margin: 0.33em; padding: 0; }", "#gmc68219home .field_label { color: #333; font-size: 100%; font-weight: normal; margin: 0 0.25em; position: relative; top: -0.2em; }", "#gmc68219home .section_header_holder { margin: 0.25em 0.5em !important; }", "#gmc68219home .section_desc { margin: 0.25em 1.5em !important; }", ".gmc-yellownote { background-color: #ffd; font-size: 0.66em !important; }", ".gmc68219home-invisilink { text-decoration: none; color: #000; }", ".gmc68219home-invisilink:hover { color: #000; }", "#gmc68219home_wrapper textarea,", "#gmc68219home_wrapper input", "{ font-size: 1em; }", "#gmc68219home_wrapper input[type='text']", "{ text-align: right; width: 2em; }", "#gmc68219home_maxHeightListSa_var,", "#gmc68219home_scanScriptWrightDepth_var,", "#gmc68219home_scanScriptsDepth_var,", "#gmc68219home_scanGroupsDepth_var,", "#gmc68219home_scanTagsDepth_var,", "#gmc68219home_scanMainDepth_var,", "#gmc68219home_enableAutoSession_var,", "#gmc68219home_alwaysShowAuthorId_var,", "#gmc68219home_alwaysHidePus_var,", "#gmc68219home_alwaysHideDeletedUser_var", "{ margin-left: 2em !important; }", "#gmc68219home .reset, #gmc68219home .reset a, #gmc68219home_buttons_holder { text-align: inherit; }", "#gmc68219home_buttons_holder { margin: 0.5em; }", "#gmc68219home_saveBtn { margin: 0.5em !important; padding: 0 3.0em !important; }", "#gmc68219home_resetLink { margin-right: 1.5em; }", "#gmc68219home_closeBtn { display: none; }", "}", "@media print {", "#gmc68219home { display: none !important; }", "}" ].join("\n") }), { 'forceInstallSecure': { "section": [], "type": 'checkbox', "label": 'Force userscripts.org installations to use secure when browsing the site in unsecure', "default": false }, 'forceInstallRecent': { "type": 'checkbox', "label": 'Force userscripts.org installations to use the most recently detected version', "default": false }, 'mirrorDomain': { "section": [,''], "label": 'Mirror domain name for usoCheckup <em class="gmc-yellownote">Select primary ONLY or secure OPTIONALLY if behind a domain blocklist that prevents the redirect</em>', "type": 'radio', "options": ['redirect', 'primary', 'secure'], "default": 'redirect' }, 'allowAOU': { "type": 'checkbox', "label": 'Allow Add-on Updater <em class="gmc-yellownote">WARNING: Greasemonkey versions 0.9.13+ can be <strong>UNSAFE</strong> with invalid <a class="gmc68219home-invisilink" href="' + gPROTOCOL + '//sf.net/apps/mediawiki/greasemonkey/index.php?title=Metadata_Block#.40updateURL">@updateURL</a> values</em>', "default": false }, 'allowUpdatersOnAOUgrantnone': { "section": [,''], "type": 'checkbox', "label": 'Allow updaters to be added on scripts that have <code><a class="gmc68219home-invisilink" href="' + gPROTOCOL + '//sf.net/apps/mediawiki/greasemonkey/index.php?title=Metadata_Block#.40grant">@grant</a> none</code> <em class="gmc-yellownote">WARNING: Some scripts may not work properly</em>', "default": false }, 'skipVerifyExclusion': { "type": 'checkbox', "label": 'Skip verify for installation of exclusion scripts <em class="gmc-yellownote">Not recommended</em>', "default": false }, 'disableScanDeep': { "section": [,''], "type": "checkbox", "label": 'Disable deep scanning for individual script home pages <em class="gmc-yellownote">WARNING: Turning this option on may provide less accurate results</em>', "default": false }, 'limitMaxHeightSa': { "type": 'checkbox', "label": 'Limit maximum height of all shown item types in the sidebar', "default": false }, 'maxHeightListSa': { "type": 'unsigned number', "label": 'em maximum height of all shown item types', "default": 10 }, 'enableScanScriptWright': { "section": [,''], "type": "checkbox", "label": 'Enable ScriptWright script pages scanning <em class="gmc-yellownote">WARNING: Deep scanning may be CPU and bandwidth intensive</em>', "default": false }, 'scanScriptWrightDepth': { "type": 'radio', "options": ['shallow', 'deep'], "default": 'shallow' }, 'enableScanGroups': { "section": [,''], "type": "checkbox", "label": 'Enable Group script pages scanning <em class="gmc-yellownote">WARNING: Deep scanning may be CPU and bandwidth intensive</em>', "default": false }, 'scanGroupsDepth': { "type": 'radio', "options": ['shallow', 'deep'], "default": 'shallow' }, 'enableScanScripts': { "type": "checkbox", "label": 'Enable Scripts pages scanning <em class="gmc-yellownote">WARNING: Deep scanning may be CPU and bandwidth intensive</em>', "default": false }, 'scanScriptsDepth': { "type": 'radio', "options": ['shallow', 'deep'], "default": 'shallow' }, 'enableScanTags': { "type": "checkbox", "label": 'Enable Tags pages scanning <em class="gmc-yellownote">WARNING: Deep scanning may be CPU and bandwidth intensive</em>', "default": false }, 'scanTagsDepth': { "type": 'radio', "options": ['shallow', 'deep'], "default": 'shallow' }, 'enableScanMain': { "type": "checkbox", "label": 'Enable Popular scripts pages scanning <em class="gmc-yellownote">WARNING: Deep scanning may be CPU and bandwidth intensive</em>', "default": false }, 'scanMainDepth': { "type": 'radio', "options": ['shallow', 'deep'], "default": 'shallow' }, 'enableNabAuthorId': { "section": [,''], "type": "checkbox", "label": 'Enable ScriptWright info request when unavailable <em class="gmc-yellownote">BETA: This may be bandwidth intensive and can be slow during high traffic periods</em>', "default": false }, 'enableAutoSession': { "type": "checkbox", "label": 'Auto attempt to establish a session with userscripts.org <em class="gmc-yellownote">WARNING: This should reduce bandwidth some but usually has less privacy</em>', "default": false }, 'alwaysShowAuthorId': { "type": "checkbox", "label": 'Always show ScriptWright info in mixed ScriptWright script lists', "default": false }, 'alwaysHideDeletedUser': { "type": "checkbox", "label": 'Always hide a deleted ScriptWright in mixed ScriptWright script lists', "default": false }, 'alwaysHidePus': { "type": "checkbox", "label": 'Always hide Potentially Unwanted scripts in mixed ScriptWright script lists', "default": false }, 'disableViewportHold': { "section": [,''], "type": "checkbox", "label": 'Disable Viewport hold <em class="gmc-yellownote">WARNING: This uses more bandwidth and can be slow during high traffic periods</em>', "default": false }, 'enableDebugging': { "section": [,''], "type": "checkbox", "label": 'Enable debugging <em class="gmc-yellownote">WARNING: Includes console methods, and alerts that may block script execution, for any known potential issues and monitoring</em>', "default": false } } ); gmcHome.onSave = function() { let write = false; let reopen = false; GM_setStyle({ node: gCSS, data: [ "#script_sidebar h7 div.sa { max-height: " + (gmcHome.get("limitMaxHeightSa") ? gmcHome.get("maxHeightListSa") + "em" : "none") + "; }" ].join("\n") }); if (write) gmc.write(); if (reopen) { gmc.close(); gmc.open(); } } /** **/ if (gmcHome.get("limitMaxHeightSa")) GM_setStyle({ node: gCSS, data: [ "#script_sidebar h7 div.sa { max-height: " + gmcHome.get("maxHeightListSa") + "em; overflow: auto; }" ].join("\n") }); if (gISFRAMELESS && /\/scripts\/show\/68219\/?$/.test(gPATHNAME)) { gmcHome.open(); } /** * */ let gmc = new GM_configStruct(); gmc.id = "gmc68219"; gmc.init( gISHOMEPAGE ? insertHook() : "", ( ( (/\/scripts\/show\/68219\/?$/.test(gPATHNAME)) ? [ '<img alt="installWith" title="uso - installWith" src="' + GM_getResourceURL("icon") + '" />' ].join("") : [ '<a href="/scripts/show/68219">', '<img alt="installWith" title="uso - installWith" src="' + GM_getResourceURL("icon") + '" />', '</a>' ].join("") ) + [ '<p>Options</p>', '<span>', '<a href="/guides/24/">', '<img alt="usoCheckup" title="Powered in part by usoCheckup" src="' + GM_getResourceURL("usoc") + '" />', '</a>', '<a href="' + gPROTOCOL + '//github.com/sizzlemctwizzle/GM_config/wiki">', '<img alt="GM_config" title="Powered in part by GM_config" src="' + GM_getResourceURL("gmc") + '" />', '</a>', '</span>' ].join("") ), /* Custom CSS */ GM_setStyle({ node: null, data: [ "@media screen, projection {", "#gmc68219 { position: static !important; z-index: 0 !important; width: auto !important; height: auto !important; max-height: none !important; max-width: none !important; margin: 0 0 0.5em 0 !important; border: 1px solid #ddd !important; clear: right !important; }", "#gmc68219_header a { display: inline; }", "#gmc68219_header img { max-height: 32px; margin-right: 0.125em; vertical-align: middle; }", "#gmc68219_header > p { display: inline; margin: 0; vertical-align: middle; }", "#gmc68219_header span { float: right; }", "#gmc68219_header span > a { display: inline; margin-left: 0.25em; }", "#gmc68219_wrapper { background-color: #eee; padding-bottom: 0.25em; }", "#gmc68219 .config_header { background-color: #333; color: #fff; font-size: 1.57em; margin: 0; padding: 0 0.5em; text-align: left; }", "#gmc68219 .config_var { clear: both; margin: 0.33em; padding: 0; }", "#gmc68219 .field_label { color: #333; font-size: 100%; font-weight: normal; margin: 0 0.25em; position: relative; top: -0.2em; }", "#gmc68219 .section_header_holder { margin: 0.25em 0.5em !important; }", "#gmc68219 .section_desc { margin: 0.25em 1.5em !important; }", ".gmc-yellownote { background-color: #ffd; font-size: 0.66em !important; }", ".gmc68219-invisilink { text-decoration: none; color: #000; }", ".gmc68219-invisilink:hover { color: #000; }", "#gmc68219 .config_header { margin-bottom: 0.5em; }", "#gmc68219_useGravatarIcon_var,", "#gmc68219_useScriptIcon_var", "{ display: inline !important; }", "#gmc68219_useGravatarIcon_field_label img,", "#gmc68219_useScriptIcon_field_label img", "{ max-height: 48px; max-width: 48px; vertical-align: middle; }", "#gmc68219_field_updaterMaxage,", "#gmc68219_field_updaterMinage", "{ height: 1em; margin: 0 0.25em; min-height: 0.8em; max-height: 2.1em; text-align: right; width: 2.5em; }", "#gmc68219 .reset, #gmc68219 .reset a, #gmc68219_buttons_holder { text-align: inherit; }", "#gmc68219_buttons_holder { margin: 0.5em; }", "#gmc68219_saveBtn { margin: 0.5em !important; padding: 0 3.0em !important; }", "#gmc68219_resetLink { margin-right: 1.5em; }", "#gmc68219_closeBtn { display: none; }", "}", "@media print {", "#gmc68219 { display: none !important; }", "}" ].join("\n") }), /* Settings Object */ { "useGravatarIcon": { "section": [], "type": "checkbox", "label": '', "default": false }, "useScriptIcon": { "type": "checkbox", "label": '', "default": false }, "updaterMaxage": { "type": "unsigned integer", "label": 'day(s) maximum between checks for this script', "default": 30 }, "updaterMinage": { "type": "unsigned integer", "label": 'hour(s) minimum before starting a check for this script', "default": 1 }, 'indirectMethod': { "label": 'Method <em class="gmc-yellownote">Select update to use the most recently detected version.</em>', "type": 'radio', "options": ['show', 'install', 'update'], "default": 'show' }, 'directMethod': { "label": 'Method <em class="gmc-yellownote">Select update to use the most recently detected version.</em>', "type": 'radio', "options": ['install', 'update'], "default": 'install' }, 'providerPref1': { "type": 'hidden', "default": "uso" }, 'providerPref2': { "type": 'hidden', "default": "uso" } } ); gmc.onSave = function() { let write = false; let reopen = false; if (gmc.get("updaterMinage") > gmc.get("updaterMaxage") * 24 ) { gmc.set("updaterMinage", 1); write = true; } if (write) gmc.write(); if (reopen) { gmc.close(); gmc.open(); } let ev = new CustomEvent("change"); let selectNode = document.getElementById("provider_id"); selectNode.dispatchEvent(ev); } GM_config = undefined; let gmcFilters = new GM_configStruct(); gmcFilters.id = "gmc68219filters"; gmcFilters.init( document.body.insertBefore(document.createElement("div"), document.body.firstChild), ( ( (/\/scripts\/show\/68219\/?$/.test(gPATHNAME)) ? [ '<img alt="installWith" title="uso - installWith" src="' + GM_getResourceURL("icon") + '" />' ].join("") : [ '<a href="/scripts/show/68219">', '<img alt="installWith" title="uso - installWith" src="' + GM_getResourceURL("icon") + '" />', '</a>' ].join("") ) + [ '<p>Advisor</p>', '<span>', '<a href="/guides/24/">', '<img alt="usoCheckup" title="Powered in part by usoCheckup" src="' + GM_getResourceURL("usoc") + '" />', '</a>', '<a href="' + gPROTOCOL + '//github.com/sizzlemctwizzle/GM_config/wiki">', '<img alt="GM_config" title="Powered in part by GM_config" src="' + GM_getResourceURL("gmc") + '" />', '</a>', '</span>' ].join("") ), /* Custom CSS */ GM_setStyle({ node: null, data: [ "@media screen, projection {", "#gmc68219filters { background-color: rgba(0, 0, 0, 0.66) !important; height: 100% !important; width: 100% !important; max-height: 100% !important; max-width: 100% !important; left: 0 !important; top: 0 !important; }", "#gmc68219filters_wrapper { background-color: #eee; width: 45em; height: 40em; position: absolute; left: 45%; top: 50%; margin: -20em 0 0 -15em; border: 1px solid #ddd; }", "#gmc68219filters_header a { display: inline; }", "#gmc68219filters_header img { vertical-align: middle; }", "#gmc68219filters_header > a img { height: 32px; margin-right: 0.25em; width: 32px; }", "#gmc68219filters_header > img { height: 32px; margin-right: 0.25em; width: 32px; }", "#gmc68219filters_header > p { display: inline; margin: 0; vertical-align: middle; }", "#gmc68219filters_header span { float: right; }", "#gmc68219filters_header span > a { display: inline; margin-left: 0.25em; }", "#gmc68219filters .config_header { background-color: #333; color: #fff; font-size: 1.57em; margin: 0; padding: 0 0.5em; text-align: left; }", "#gmc68219filters .config_var { clear: both; margin: 0 1em; padding: 0; }", "#gmc68219filters .field_label { color: #333; font-size: 100%; font-weight: normal; margin: 0 0.25em; position: relative; top: 0.125em; }", "#gmc68219filters .section_desc { margin: 0.25em 1.5em !important; }", "#gmc68219filters .section_header { margin: 0 1em; text-align: left; }", "#gmc68219filters .section_header img { margin: 0 0.25em; vertical-align: middle; }", ".gmc-yellownote { background-color: #ffd; font-size: 0.66em !important; }", ".gmc68219filters-invisilink { text-decoration: none; color: #000; }", ".gmc68219filters-invisilink:hover { color: #000; }", "#gmc68219filters .field_label { top: -0.25em; }", "#gmc68219filters_postPUStoSAM_var { margin-bottom: 0.25em !important; margin-top: 1.25em !important; }", "#gmc68219filters_field_postPUStoSAM { height: 2.5em; width: 38.75em; }", "#gmc68219filters_openSAMtopic_var,", "#gmc68219filters_disableSAMCSS_var", "{", " margin-top: 0.125em !important; margin-bottom: 0.25em !important; margin-left: 1.75em !important; ", "}", "#gmc68219filters_section_0 { margin-top: 0 !important; }", "#gmc68219filters_section_desc_0 { border-style: none !important; text-align: left !important; font-style: italic; }", "#gmc68219filters_section_desc_0 span:first-child { margin-left: 10.5em; }", "#gmc68219filters_section_desc_0 span:last-child { float: right; margin-right: 10.25em; }", "#gmc68219filters_clearUserScriptIds_var", "{ display: inline !important; margin-right: 0 !important; }", "#gmc68219filters_field_clearUserScriptIds", "{ font-size: 0.9em; width: 6em; }", "#gmc68219filters_clearUserScriptPrivIds_var", "{ display: inline !important; margin-right: 0 !important; margin-left: 3em !important; }", "#gmc68219filters_field_clearUserScriptPrivIds", "{ font-size: 0.9em; width: 8em; }", "#gmc68219filters_moveUserScriptIds_var,", "#gmc68219filters_moveUserScriptPrivIds_var", "{ display: inline !important; margin-right: 0 !important; margin-left: 0 !important; }", "#gmc68219filters_field_moveUserScriptIds,", "#gmc68219filters_field_moveUserScriptPrivIds", "{ font-size: 0.9em; width: 10.75em; }", "#gmc68219filters_copyUserScriptIds_var,", "#gmc68219filters_copyUserScriptPrivIds_var", "{ display: inline !important; margin-right: 0 !important; margin-left: 0 !important; }", "#gmc68219filters_field_copyUserScriptIds,", "#gmc68219filters_field_copyUserScriptPrivIds", "{ font-size: 0.9em; width: 6em; }", "#gmc68219filters_usePlain_var { display: inline !important; margin: 0 !important; }", "#gmc68219filters_copyScriptWrightIds_var,", "#gmc68219filters_copyScriptWrightPrivIds_var", "{ display: inline !important; margin-left: 0 !important; margin-right: 0 !important; }", "#gmc68219filters_field_copyScriptWrightIds,", "#gmc68219filters_field_copyScriptWrightPrivIds", "{ font-size: 0.9em; width: 6em; }", "#gmc68219filters_moveScriptWrightIds_var", "{ display: inline !important; margin-left: 0 !important; margin-right: 0 !important; }", "#gmc68219filters_field_moveScriptWrightIds", "{ font-size: 0.9em; width: 10.75em; }", "#gmc68219filters_moveScriptWrightPrivIds_var", "{ display: inline !important; margin-left: 5.5em !important; margin-right: 0 !important; }", "#gmc68219filters_field_moveScriptWrightPrivIds", "{ font-size: 0.9em; width: 10.75em; }", "#gmc68219filters_clearScriptWrightIds_var", "{ display: inline !important; margin-left: 0 !important; }", "#gmc68219filters_field_clearScriptWrightIds", "{ font-size: 0.9em; width: 6em; }", "#gmc68219filters_clearScriptWrightPrivIds_var", "{ display: inline !important; margin-left: 0 !important; }", "#gmc68219filters_field_clearScriptWrightPrivIds", "{ font-size: 0.9em; width: 8em; }", "#gmc68219filters_field_jsonFilters { height: 11em; min-height: 11em; max-height: 11em; font-size: 1.1em; resize: none; width: 38.2em; min-width: 38.2em; max-width: 38.2em; margin-top: 0.5em; }", "#gmc68219filters_jsonFilters_field_label > p { margin-bottom: 0.25em; margin-top: 0.25em; }", "#gmc68219filters_insertUserScriptIdToPU_var { display: inline !important; }", "#gmc68219filters_field_insertUserScriptIdToPU { height: 2.25em; width: 8.5em; }", "#gmc68219filters_lastUserScriptId_var { display: inline !important; margin-left: 0 !important; }", "#gmc68219filters_field_lastUserScriptId { width: 8.125em; margin-top: 0; text-align: right; }", "#gmc68219filters_lastScriptWrightId_var { display: inline !important; }", "#gmc68219filters_field_lastScriptWrightId { width: 8.125em; margin-top: 0; text-align: right; }", "#gmc68219filters_insertScriptWrightIdToPU_var { display: inline !important; margin-left: 0 !important; }", "#gmc68219filters_field_insertScriptWrightIdToPU { height: 2.25em; width: 8.5em; }", "#gmc68219filters_buttons_holder { margin: 0.5em; margin-top: 1em; padding-top: 0; text-align: inherit; bottom: 0; right: 0; }", "#gmc68219filters .saveclose_buttons { margin: 0.5em 10px; }", "#gmc68219filters_saveBtn { float: right; margin-right: 0.4em !important; width: 10em;", "#gmc68219filters_resetLink { margin-right: 1.5em; }", "}", "@media print {", "#gmc68219filters { display: none !important; }", "}" ].join("\n") }), /* Settings Object */ { 'postPUStoSAM': { "type": "button", "label": 'Queue Potentially Unwanted (PU) Ids to Spam and Malware', "script": function () { try { let json, write, post, GROUPS; GROUPS = JSON.parse(gLIST + '}'); json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let jsonFull = JSON.parse('{"user":' + gmcFilters.fields["jsonFilters"].node.value + '}'); let reports = []; let pendingReports = GM_getValue(":pendingReports"); if (pendingReports) { pendingReports.split(',').forEach(function (e, i, a) { reports.push(e); }); } parseList(jsonFull, function (aScope, aPatterns, aAdvisory, aSummary, aTips, aBlock, aReduce, aCollapse, aHide, aProvider, aCollector) { switch (aScope) { case "@uso:script": case "@uso:author": if (/Potentially\sunwanted\sscript/.test(aSummary)) { for (let pattern in aPatterns) { let matches = pattern.match(/^\"?(\d+)\"?$/); if (matches) { let id = matches[1]; if (aScope == "@uso:script") { if (!json["@uso:script (private)"]) { json["@uso:script (private)"] = ["GUARD Potentially unwanted script", []]; write = true; } let privateSids = json["@uso:script (private)"][1]; // TODO: let found; privateSids.forEach(function (e, i, a) { if (e == id) found = true; }); if (!found && GROUPS && GROUPS["collections"]["@uso:script"]) { let globalSids = GROUPS["collections"]["@uso:script"][1]; // TODO: globalSids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found) { privateSids.push(id); write = true; reports.push('/' + id); } } else { if (!json["@uso:author (private)"]) { json["@uso:author (private)"] = ["GUARD Potentially unwanted script", []]; write = true; } let privateAids = json["@uso:author (private)"][1]; // TODO: let found; privateAids.forEach(function (e, i, a) { if (e == id) found = true; }); if (!found && GROUPS && GROUPS["collections"]["@uso:author"]) { let globalAids = GROUPS["collections"]["@uso:author"][1]; // TODO: globalAids.forEach(function (e, i, a) { if (e == id) found = true; }); } if (!found) { privateAids.push(id); write = true; reports.push('/users/' + id); } } } } } break; } }); if (write) { json["@uso:author"][1] = []; json["@uso:script"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); gmcFilters.set("jsonFilters", JSON.stringify(json, null, "")); GM_setValue(":pendingReports", reports.sort(function (a, b) { let re = /(\d+)$/; return a.match(re)[1] - b.match(re)[1]; }).sort(function (a, b) { let re = /^(.*\/)\d+$/; if (a.match(re)[1] < b.match(re)[1]) return -1; if (a.match(re)[1] > b.match(re)[1]) return 1 return 0; }).toString()); post = true; } let openSAMtopic = gmcFilters.fields["openSAMtopic"].node.checked; if (openSAMtopic != gmcFilters.get("openSAMtopic")) { gmcFilters.set("openSAMtopic", openSAMtopic); write = true; } if (write) gmcFilters.write(); if (post && openSAMtopic) { gmcFilters.close(); location.href = "/topics/9#posts-last"; } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'openSAMtopic': { "type": "checkbox", "label": 'Auto open the <a href="/topics/9#posts-last"></>Spam and Malware</a> topic on queue', "default": false }, 'clearUserScriptIds' : { "type": "button", "label": 'Clear PU', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); json["@uso:script"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'moveUserScriptIds': { "type": "button", "label": 'Move PU to private', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let sids = json["@uso:script"][1]; if (sids.length > 0) { let GROUPS = JSON.parse(gLIST + '}'); sids.sort(function (a, b) { return a - b }); if (!json["@uso:script (private)"]) json["@uso:script (private)"] = ["GUARD Potentially unwanted script", []]; let privateSids = json["@uso:script (private)"][1]; // TODO: sids.forEach(function (e, i, a) { let found; privateSids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); if (!found && GROUPS && GROUPS["collections"]["@uso:script"]) { let globalSids = GROUPS["collections"]["@uso:script"][1]; // TODO: globalSids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); } if (!found) privateSids.push(e); }); json["@uso:script (private)"][1] = privateSids.sort(function (a, b) { return a - b }); json["@uso:script"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'copyUserScriptIds' : { "type": "button", "label": 'Copy PU', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let aids = json["@uso:script"][1]; if (aids.length > 0) { aids.sort(function (a, b) { return a - b }); if (gmcFilters.fields["usePlain"].node.checked) GM_setClipboard( aids.join('\n'), "text" ); else GM_setClipboard( aids.map(function (aE) { return '"' + aE + '"' }).join(',\n'), "text" ); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'usePlain': { "type": "checkbox", "label": '', "default": false }, 'copyScriptWrightIds' : { "type": "button", "label": 'Copy PU', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let aids = json["@uso:author"][1]; if (aids.length > 0) { aids.sort(function (a, b) { return a - b }); if (gmcFilters.fields["usePlain"].node.checked) GM_setClipboard( aids.join('\n'), "text" ); else GM_setClipboard( aids.map(function (aE) { return '"' + aE + '"' }).join(',\n'), "text" ); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'moveScriptWrightIds': { "type": "button", "label": 'Move PU to private', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let aids = json["@uso:author"][1]; if (aids.length > 0) { let GROUPS = JSON.parse(gLIST + '}'); aids.sort(function (a, b) { return a - b }); if (!json["@uso:author (private)"]) json["@uso:author (private)"] = ["GUARD Potentially unwanted script", []]; let privateAids = json["@uso:author (private)"][1]; // TODO: aids.forEach(function (e, i, a) { let found; privateAids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); if (!found && GROUPS && GROUPS["collections"]["@uso:author"]) { let globalAids = GROUPS["collections"]["@uso:author"][1]; // TODO: globalAids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); } if (!found) privateAids.push(e); }); json["@uso:author (private)"][1] = privateAids.sort(function (a, b) { return a - b }); json["@uso:author"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'clearScriptWrightIds' : { "type": "button", "label": 'Clear PU', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); json["@uso:author"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'clearUserScriptPrivIds' : { "section" : [,'<span class="gmc-yellownote">Group Script shortcuts</span><span class="gmc-yellownote">Group Author shortcuts</span>'], "type": "button", "label": 'Clear private', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); json["@uso:script (private)"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } catch (e) { if (!/is\sundefined$/.test(e.message)) alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'moveUserScriptPrivIds': { "type": "button", "label": 'Move private to PU', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let privateSids = json["@uso:script (private)"][1]; if (privateSids.length > 0) { let GROUPS = JSON.parse(gLIST + '}'); privateSids.sort(function (a, b) { return a - b }); if (!json["@uso:script"]) json["@uso:script"] = ["GUARD Potentially unwanted script", []]; let sids = json["@uso:script"][1]; // TODO: privateSids.forEach(function (e, i, a) { let found; sids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); if (!found && GROUPS && GROUPS["collections"]["@uso:script"]) { let globalSids = GROUPS["collections"]["@uso:script"][1]; // TODO: globalSids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); } if (!found) sids.push(e); }); json["@uso:script"][1] = sids.sort(function (a, b) { return a - b }); json["@uso:script (private)"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'moveScriptWrightPrivIds': { "type": "button", "label": 'Move private to PU', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let privateAids = json["@uso:author (private)"][1]; if (privateAids.length > 0) { let GROUPS = JSON.parse(gLIST + '}'); privateAids.sort(function (a, b) { return a - b }); if (!json["@uso:author"]) json["@uso:author"] = ["GUARD Potentially unwanted script", []]; let aids = json["@uso:author"][1]; privateAids.forEach(function (e, i, a) { let found; aids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); if (!found && GROUPS && GROUPS["collections"]["@uso:author"]) { let globalAids = GROUPS["collections"]["@uso:author"][1]; // TODO: globalAids.forEach(function (e1, i1, a1) { if (e == e1) found = true; }); } if (!found) aids.push(e); }); json["@uso:author"][1] = aids.sort(function (a, b) { return a - b }); json["@uso:author (private)"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'clearScriptWrightPrivIds' : { "type": "button", "label": 'Clear private', "script": function () { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); json["@uso:author (private)"][1] = []; gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } catch (e) { if (!/is\sundefined$/.test(e.message)) alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } }, 'jsonFilters': { "type": 'textarea', "label": "<p><em class='gmc-yellownote'>use <a href='http://json.org/'>JSON</a> data-interchange format</em></p>", "default": JSON.stringify( JSON.parse( [ '{', ' "@uso:author": [', ' "GUARD Potentially unwanted script",', ' [', ' "authorid1"', ' ]', ' ],', ' "@uso:script": [', ' "GUARD Potentially unwanted script",', ' [', ' "scriptid1"', ' ]', ' ]', '}' ].join("\n") ), null, " ") }, 'insertUserScriptIdToPU': { "type": "button", "label": 'Script to PU', "script": function () { let sid = gmcFilters.fields["lastUserScriptId"].node.value; if (sid != "") { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let GROUPS = JSON.parse(gLIST + '}'); let found, scripts = json["@uso:script"][1]; // TODO: scripts.forEach(function (e, i, a) { if (e == sid) found = true; }); if (!found && json["@uso:script (private)"]) { scripts = json["@uso:script (private)"][1]; // TODO: scripts.forEach(function (e, i, a) { if (e == sid) found = true; }); } if (!found && GROUPS && GROUPS["collections"]["@uso:script"]) { let globalSids = GROUPS["collections"]["@uso:script"][1]; // TODO: globalSids.forEach(function (e, i, a) { if (e == sid) found = true; }); } if (!found) { if (!json["@uso:script"]) json["@uso:script"] = ["GUARD Potentially unwanted script", []]; json["@uso:script"][1].push(sid); gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } } }, 'lastUserScriptId': { "type": "text", "default": "" }, 'lastScriptWrightId': { "type": "text", "default": "" }, 'insertScriptWrightIdToPU': { "type": "button", "label": 'Author to PU', "script": function () { let aid = gmcFilters.fields["lastScriptWrightId"].node.value; if (aid != "") { try { let json = JSON.parse(gmcFilters.fields["jsonFilters"].node.value); let GROUPS = JSON.parse(gLIST + '}'); let found, authors = json["@uso:author"][1]; // TODO: authors.forEach(function (e, i, a) { if (e == aid) found = true; }); if (json["@uso:author (private)"]) { authors = json["@uso:author (private)"][1]; // TODO: authors.forEach(function (e, i, a) { if (e == aid) found = true; }); } if (!found && GROUPS && GROUPS["collections"]["@uso:author"]) { let globalAids = GROUPS["collections"]["@uso:author"][1]; // TODO: globalAids.forEach(function (e, i, a) { if (e == aid) found = true; }); } if (!found) { if (!json["@uso:author"]) json["@uso:author"] = ["GUARD Potentially unwanted script", []]; json["@uso:author"][1].push(aid); gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(json, null, " "); } } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); } } } } } ); gmcFilters.onOpen = function () { try { gmcFilters.fields["jsonFilters"].node.value = JSON.stringify(JSON.parse(gmcFilters.get("jsonFilters")), null, " "); } catch (e) {} gmcFilters.fields["usePlain"].node.title = "Use plain ids for clipboard copy"; gmcFilters.fields["jsonFilters"].node.setAttribute("spellcheck", "false"); gmcFilters.fields["jsonFilters"].node.setAttribute("wrap", "off"); gmcFilters.fields["lastScriptWrightId"].node.setAttribute("readonly", "readonly"); gmcFilters.fields["lastScriptWrightId"].node.setAttribute("placeholder", "No ScriptWright Id"); gmcFilters.fields["lastUserScriptId"].node.setAttribute("readonly", "readonly"); gmcFilters.fields["lastUserScriptId"].node.setAttribute("placeholder", "No User Script Id"); let saveBtn = document.getElementById("gmc68219filters_saveBtn"); if (saveBtn) saveBtn.textContent = "Save \u0026 Close"; let closeBtn = document.getElementById("gmc68219filters_closeBtn"); if (closeBtn) closeBtn.textContent = "Cancel"; } gmcFilters.onSave = function () { try { gmcFilters.set("jsonFilters", JSON.stringify(JSON.parse(gmcFilters.get("jsonFilters")), null, "")); gmcFilters.write(); gmcFilters.close(); } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nPlease correct or reset to defaults'); gmcFilters.open(); } } gmcFilters.onClose = function () { try { let junk = JSON.stringify(JSON.parse(gmcFilters.get("jsonFilters")), null, ""); } catch (e) { alert('ERROR: Invalid JSON for advisories.\n\nAll user defined advisories will be skipped until corrected.'); } } /** * */ GM_setStyle({ node: gCSS, data: [ "table.forums tr td.script-meat { background-color: #eee; }" ].join("\n") }); let authenticated = document.querySelector("body.loggedin"); if (/^\/topics\/9\/?$/.test(gPATHNAME) || /^\/posts\/?$/.test(gPATHNAME)) { GM_setStyle({ node: gCSS, data: [ ".columnize { column-width: 10em; -moz-column-width: 10em; }" ].join("\n") }); let posts = document.querySelectorAll("#content .posts .entry-content p~ul"); for (let i = 0, thisNode; thisNode = posts[i++];) if (thisNode.previousSibling && thisNode.previousSibling.textContent.match(/Potentially\sunwanted\sscripts/i)) thisNode.classList.add("columnize"); } let pendingReports = GM_getValue(":pendingReports"); if (/^\/topics\/9\/?$/.test(gPATHNAME) && authenticated && pendingReports) { let paginationLast = document.querySelector("#content .pagination .next_page"); if (paginationLast && !paginationLast.classList.contains("disabled")) { let url = paginationLast.previousSibling.previousSibling.href; if (url) location.replace(url + "#footer"); } else { if (!gmcFilters.get("openSAMtopic")) { if (confirm("You seem to have pending reports.\n\nDo you wish to post now?\n\nPlease note if cancelled the reports will be removed from the queue")) { GM_deleteValue(":pendingReports"); doReport(pendingReports); } } else { GM_deleteValue(":pendingReports"); doReport(pendingReports); } } } else { if ( /^\/$/.test(gPATHNAME) && gmcHome.get("enableScanMain") || /^\/tags\//.test(gPATHNAME) && gmcHome.get("enableScanTags") || /^\/scripts(?:\/?$|\/search\/?$)/.test(gPATHNAME) && gmcHome.get("enableScanScripts") || /^\/groups\/\d+\/scripts/.test(gPATHNAME) && gmcHome.get("enableScanGroups") || /(^\/users\/.+?\/(?:scripts|favorites)|^\/home\/(?:scripts|favorites))/.test(gPATHNAME) && gmcHome.get("enableScanScriptWright") || /^\/scripts\/show\//.test(gPATHNAME) || /^\/topics\//.test(gPATHNAME) ) { init(); } } })();