|
| 1 | +# [Bookmarklets](https://en.wikipedia.org/wiki/Bookmarklet) |
| 2 | +This is a list of bookmarklets that are convenient for use with Charcoal. |
| 3 | +## WARNING |
| 4 | +Prior to copying and using any of the bookmarklets here: |
| 5 | +* Verify the history of this page and who edited it. If you don't trust the editors, don't trust the bookmarklets. |
| 6 | +* If you know JavaScript, it's a good idea to double-check the code. |
| 7 | + |
| 8 | +Clicking on a bookmarklet runs JavaScript in the current page. That means it's possible for the bookmarklet to do anything that code in that page can do. Thus, there are significant security concerns for bookmarklets and you need to trust the bookmarklet code. As things are currently set up, changes to this page are **not secure**, so you need to verify that the code hasn't been nefariously changed. |
| 9 | + |
| 10 | +## What are bookmarklets |
| 11 | +Bookmarklets are relatively small amounts of JavaScript code that are stored in a browser bookmark. When the bookmark is clicked, the JavaScript is run in the current page. The advantages of using a bookmarklet, rather than a userscript include: |
| 12 | +* Can be used in all browsers, even when the browser doesn't support browser extensions. Creating the bookmarklets may be inconvenient in some browsers. |
| 13 | +* Can, usually, be used in browsers/machines where installing browser extensions isn't permitted (e.g., some work environments). You should check the policies for where you are to be sure that having a bookmarklet doesn't violate the policy. |
| 14 | +* Can be used on almost all webpages, without the need to have a userscript or browser extension loaded into the page every time (i.e., They consume no resources and present no security issues, until activated by the user's click on the bookmark.). |
| 15 | + |
| 16 | +## Searching on metasmoke |
| 17 | + |
| 18 | +### Watchlist or blacklisted keyword entries |
| 19 | + |
| 20 | +Select the regex text you desire to search for as a watchlist or blacklisted keyword entry and click the bookmarklet: |
| 21 | +```javascript |
| 22 | +javascript:(function(){ |
| 23 | + /* The code to get the selected text on multiple platforms is from an [answer to "Get the Highlighted/Selected text"](https://stackoverflow.com/a/5379408) copyright by Tim Down and is under a [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/legalcode). It has been modified to use let/const instead of var. */ |
| 24 | + let text = ""; |
| 25 | + const activeEl = document.activeElement; |
| 26 | + const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null; |
| 27 | + if ((activeElTagName == "textarea" || activeElTagName == "input") && /^(?:text|textarea|search|password|tel|url)$/i.test(activeEl.type) && (typeof activeEl.selectionStart == "number")) { |
| 28 | + text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); |
| 29 | + } else if (window.getSelection) { |
| 30 | + text = window.getSelection().toString(); |
| 31 | + } |
| 32 | + let searchTerm = encodeURIComponent(`(?s)(?:^|\\b)${text}(?:\\b|$)`); |
| 33 | + const textNoNoncaptureGroups = text.replace(/\(\?:/g, '(').replace(/\(\?-i:([^()]+)\)/, '$1'); |
| 34 | + if (!/[+?*{}()|]/.test(textNoNoncaptureGroups)) { |
| 35 | + searchTerm = encodeURIComponent(`(?s)${text}(?<=(?:^|\\b)${text})(?:\\b|$)`); |
| 36 | + } else if (/^(?:\w+(?![?*+{])|\(\?-i:[^+?*{}()|]+\)\w*(?![?*+{]))/.test(text)) { |
| 37 | + searchTerm = encodeURIComponent(`(?s)${text.replace(/^(\w+(?![?*+{])|\(\?-i:[^+?*{}()|]+\)\w*(?![?*+{]))/, '$1(?<=(?:^|\\b)$1)')}(?:\\b|$)`); |
| 38 | + } |
| 39 | + const searchTitle = `&title_is_regex=1&title=${searchTerm}`; |
| 40 | + const searchBody = `&body_is_regex=1&body=${searchTerm}`; |
| 41 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 42 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchTitle}${searchBody}${searchUsername}&or_search=1`; |
| 43 | + window.open(url); |
| 44 | +})(); |
| 45 | +``` |
| 46 | +### Blacklisted website entries |
| 47 | +Select the regex text you desire to search for as a blacklisted website entry and click the bookmarklet: |
| 48 | +```javascript |
| 49 | +javascript:(function(){ |
| 50 | + /* The code to get the selected text on multiple platforms is from an [answer to "Get the Highlighted/Selected text"](https://stackoverflow.com/a/5379408) copyright by Tim Down and is under a [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/legalcode). It has been modified to use const instead of var. */ |
| 51 | + var text = ""; |
| 52 | + const activeEl = document.activeElement; |
| 53 | + const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null; |
| 54 | + if ((activeElTagName == "textarea" || activeElTagName == "input") && /^(?:text|textarea|search|password|tel|url)$/i.test(activeEl.type) && (typeof activeEl.selectionStart == "number")) { |
| 55 | + text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); |
| 56 | + } else if (window.getSelection) { |
| 57 | + text = window.getSelection().toString(); |
| 58 | + } |
| 59 | + const searchTerm = encodeURIComponent(`${text}`); |
| 60 | + const searchTitle = `&title_is_regex=1&title=${searchTerm}`; |
| 61 | + const searchBody = `&body_is_regex=1&body=${searchTerm}`; |
| 62 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 63 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchTitle}${searchBody}${searchUsername}&or_search=1`; |
| 64 | + window.open(url); |
| 65 | +})(); |
| 66 | +``` |
| 67 | +### Numbers |
| 68 | +Select the number text you desire to search for and click the bookmarklet: |
| 69 | +```javascript |
| 70 | +javascript:(function(){ |
| 71 | + /* The code to get the selected text on multiple platforms is from an [answer to "Get the Highlighted/Selected text"](https://stackoverflow.com/a/5379408) copyright by Tim Down and is under a [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/legalcode). It has been modified to use const instead of var. */ |
| 72 | + var text = ""; |
| 73 | + const activeEl = document.activeElement; |
| 74 | + const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null; |
| 75 | + if ((activeElTagName == "textarea" || activeElTagName == "input") && /^(?:text|textarea|search|password|tel|url)$/i.test(activeEl.type) && (typeof activeEl.selectionStart == "number")) { |
| 76 | + text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); |
| 77 | + } else if (window.getSelection) { |
| 78 | + text = window.getSelection().toString(); |
| 79 | + } |
| 80 | + const textOnlyNumbers = text.replace(/\D/g, ''); |
| 81 | + if (textOnlyNumbers.length < 7 || textOnlyNumbers.length > 20) { |
| 82 | + if (!confirm('This text can never be detected by a number watch. Number watches must contain between 7 and 20 digits. Do you still wish to search for this on MS?')) { |
| 83 | + return; |
| 84 | + } |
| 85 | + } |
| 86 | + text = text.replace(/\D/g, '').replace(/(\d)/g, '$1[\\W_]*+').replace(/\[\\W_\]\*\+$/, '(?:\\D|$)').replace(/(\d)/, '$1(?:(?<=^\\d)|(?<=\\D\\d))'); |
| 87 | + const searchTerm = encodeURIComponent(text); |
| 88 | + const searchTitle = `&title_is_regex=1&title=${searchTerm}`; |
| 89 | + const searchBody = `&body_is_regex=1&body=${searchTerm}`; |
| 90 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 91 | + /*Why is also searched, as it may contain deobfuscated versions.*/ |
| 92 | + const searchWhy = `&why_is_regex=1&why=${searchTerm}`; |
| 93 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchTitle}${searchBody}${searchUsername}${searchWhy}&or_search=1`; |
| 94 | + window.open(url); |
| 95 | +})(); |
| 96 | +``` |
| 97 | + |
| 98 | +### Loose number search |
| 99 | +Select the number text you desire to loosely search for and click the bookmarklet: |
| 100 | +```javascript |
| 101 | +javascript:(function(){ |
| 102 | + /* The code to get the selected text on multiple platforms is from an [answer to "Get the Highlighted/Selected text"](https://stackoverflow.com/a/5379408) copyright by Tim Down and is under a [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/legalcode). It has been modified to use const instead of var. */ |
| 103 | + var text = ""; |
| 104 | + const activeEl = document.activeElement; |
| 105 | + const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null; |
| 106 | + if ((activeElTagName == "textarea" || activeElTagName == "input") && /^(?:text|textarea|search|password|tel|url)$/i.test(activeEl.type) && (typeof activeEl.selectionStart == "number")) { |
| 107 | + text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); |
| 108 | + } else if (window.getSelection) { |
| 109 | + text = window.getSelection().toString(); |
| 110 | + } |
| 111 | + const textOnlyNumbers = text.replace(/\D/g, ''); |
| 112 | + if (textOnlyNumbers.length < 7 || textOnlyNumbers.length > 20) { |
| 113 | + if (!confirm('This text can never be detected by a number watch. Number watches must contain between 7 and 20 digits. Do you still wish to search for this on MS?')) { |
| 114 | + return; |
| 115 | + } |
| 116 | + } |
| 117 | + text = text.replace(/\D/g, '').replace(/(\d)/g, '$1[\\W_]*+').replace(/\[\\W_\]\*\+$/, ''); |
| 118 | + const searchTerm = encodeURIComponent(text); |
| 119 | + const searchTitle = `&title_is_regex=1&title=${searchTerm}`; |
| 120 | + const searchBody = `&body_is_regex=1&body=${searchTerm}`; |
| 121 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 122 | + /*Why is also searched, as it may contain deobfuscated versions.*/ |
| 123 | + const searchWhy = `&why_is_regex=1&why=${searchTerm}`; |
| 124 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchTitle}${searchBody}${searchUsername}${searchWhy}&or_search=1`; |
| 125 | + window.open(url); |
| 126 | +})(); |
| 127 | +``` |
| 128 | + |
| 129 | +### Blacklisted usernames |
| 130 | +Select the regex text you desire to search for as a blacklisted username entry and click the bookmarklet: |
| 131 | +```javascript |
| 132 | +javascript:(function(){ |
| 133 | + /* The code to get the selected text on multiple platforms is from an [answer to "Get the Highlighted/Selected text"](https://stackoverflow.com/a/5379408) copyright by Tim Down and is under a [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/legalcode). It has been modified to use const instead of var. */ |
| 134 | + var text = ""; |
| 135 | + const activeEl = document.activeElement; |
| 136 | + const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null; |
| 137 | + if ((activeElTagName == "textarea" || activeElTagName == "input") && /^(?:text|textarea|search|password|tel|url)$/i.test(activeEl.type) && (typeof activeEl.selectionStart == "number")) { |
| 138 | + text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); |
| 139 | + } else if (window.getSelection) { |
| 140 | + text = window.getSelection().toString(); |
| 141 | + } |
| 142 | + const searchTerm = encodeURIComponent(`${text}`); |
| 143 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 144 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchUsername}&or_search=1`; |
| 145 | + window.open(url); |
| 146 | +})(); |
| 147 | +``` |
| 148 | + |
| 149 | +### Verbatim text |
| 150 | +Select the verbatim text you desire to search for as a blacklisted website entry and click the bookmarklet: |
| 151 | +```javascript |
| 152 | +javascript:(function(){ |
| 153 | + /* The code to get the selected text on multiple platforms is from an [answer to "Get the Highlighted/Selected text"](https://stackoverflow.com/a/5379408) copyright by Tim Down and is under a [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/legalcode). It has been modified to use const instead of var. */ |
| 154 | + var text = ""; |
| 155 | + const activeEl = document.activeElement; |
| 156 | + const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null; |
| 157 | + if ((activeElTagName == "textarea" || activeElTagName == "input") && /^(?:text|textarea|search|password|tel|url)$/i.test(activeEl.type) && (typeof activeEl.selectionStart == "number")) { |
| 158 | + text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); |
| 159 | + } else if (window.getSelection) { |
| 160 | + text = window.getSelection().toString(); |
| 161 | + } |
| 162 | + /*Escaping a regex is from [this SO answer](https://stackoverflow.com/a/3561711) by bobince.*/ |
| 163 | + const searchTerm = encodeURIComponent(`${text.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&')}`); |
| 164 | + const searchTitle = `&title_is_regex=1&title=${searchTerm}`; |
| 165 | + const searchBody = `&body_is_regex=1&body=${searchTerm}`; |
| 166 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 167 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchTitle}${searchBody}${searchUsername}&or_search=1`; |
| 168 | + window.open(url); |
| 169 | +})(); |
| 170 | +``` |
| 171 | + |
| 172 | +### Two searches for the difference between two watchlist/keyword blacklist entries |
| 173 | +The following bookmarklet will open two searches on MS to get the differences between two watchlist/keyword blacklist entries. The searches will be the relative complements of the hits for the two entries (i.e., one window showing what's caught by the first entry, but not caught by the second entry; and one window showing what's caught by the second entry, but not caught by the first entry). |
| 174 | + |
| 175 | +The bookmarklet will prompt you for both a description for each entry and the entries (i.e., the prompts are in the order description 1, entry 1, description 2, entry 2). The descriptions are used in a regex comment, so it's easier to know which window is which. The descriptions are not permitted to be blank, nor to include "(" or ")". |
| 176 | +```javascript |
| 177 | +javascript:(function(){ |
| 178 | + function openSearchForText(text) { |
| 179 | + const searchTerm = encodeURIComponent(text); |
| 180 | + const searchTitle = `&title_is_regex=1&title=${searchTerm}`; |
| 181 | + const searchBody = `&body_is_regex=1&body=${searchTerm}`; |
| 182 | + const searchUsername = `&username_is_regex=1&username=${searchTerm}`; |
| 183 | + const url = `https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93${searchTitle}${searchBody}${searchUsername}&or_search=1`; |
| 184 | + window.open(url); |
| 185 | + } |
| 186 | + let description1 = ''; |
| 187 | + while (!description1 || description1.includes('(') || description1.includes(')')) { |
| 188 | + description1 = window.prompt('Description for first entry (may not contain "(" or ")"):'); |
| 189 | + } |
| 190 | + let entry1 = ''; |
| 191 | + while (!entry1) { |
| 192 | + entry1 = window.prompt('First entry:'); |
| 193 | + } |
| 194 | + let description2 = ''; |
| 195 | + while (!description2 || description2.includes('(') || description2.includes(')')) { |
| 196 | + description2 = window.prompt('Description for second entry (may not contain "(" or ")"):'); |
| 197 | + } |
| 198 | + let entry2 = ''; |
| 199 | + while (!entry2) { |
| 200 | + entry2 = window.prompt('Second entry:'); |
| 201 | + } |
| 202 | + openSearchForText(`(?#IN ${description1}, but NOT IN ${description2})(?s)^(?=[\\W\\w]*?(?:^|\\b)${entry1}(?:\\b|$))(?![\\W\\w]*?(?:^|\\b)${entry2}(?:\\b|$))`); |
| 203 | + openSearchForText(`(?#IN ${description2}, but NOT IN ${description1})(?s)^(?=[\\W\\w]*?(?:^|\\b)${entry2}(?:\\b|$))(?![\\W\\w]*?(?:^|\\b)${entry1}(?:\\b|$))`); |
| 204 | +})(); |
| 205 | +``` |
0 commit comments