Advertisement
Guest User

Colin's trollegle userscript.

a guest
Dec 7th, 2019
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.42 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Trollegle
  3. // @version 0.1
  4. // @match *://*.omegle.com/
  5. // @grant GM_getValue
  6. // @grant GM_setValue
  7. // @grant GM.getValue
  8. // @grant GM.setValue
  9. // @grant unsafeWindow
  10. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  11. // @copyright SHA-1 module used under licence from Chris Veness, rest is public domain
  12. // @updateURL https://tilde.town/~tunas/trollegle.user.js
  13. // ==/UserScript==
  14.  
  15. var rooms = [];
  16. var state = {
  17. window: null,
  18. captchaWidget: null,
  19. captchaKey: null,
  20. captchas: 0,
  21. backend: null,
  22. connectTime: null,
  23. isTrollegle: false,
  24. lurkMode: null,
  25. lurkRate: null,
  26. lastLurkRate: null,
  27. lurkText: null,
  28. lurkHandle: null,
  29. };
  30. // create button
  31. /*var btn = document.createElement( 'input' );
  32. btn.setAttribute( 'onclick', '('+ coloredMain +')();' );
  33. btn.setAttribute( 'value', 'start colored' );
  34. btn.setAttribute( 'type', 'button' );*/
  35.  
  36. var lurkModes = [
  37. {name: "never", value: "never"},
  38. {name: "when a room is detected", value: "rooms"},
  39. {name: "always", value: "always"},
  40. ];
  41.  
  42. async function lurkMode(def) { return state.lurkMode || await GM.getValue("lurkMode") || "never" }
  43. async function lurkRate(def) { return state.lurkRate || Number(await GM.getValue("lurkRate")) || 10 }
  44. async function lurkText(def) { return state.lurkText || await GM.getValue("lurkText") || "/8|/id|/list" }
  45.  
  46. var sty = E("style", {}, "#prefbox>:not(button) {" +
  47. "display: block; font-family: inherit; font-size: inherit; " +
  48. "-moz-appearance: none; -webkit-appearance: none; margin: 0.2em; }" +
  49. "#prefbox input { vertical-align: middle; }" +
  50. "#prefbox textarea { border: solid black 1px; width: 95%; height: 10em; }" +
  51. ".sublabel { display:inline-block; margin-left: 1em; width: 5.5em; }" +
  52. "#prefbox * { font-size: inherit; }");
  53. document.head.appendChild(sty);
  54.  
  55. async function updateRooms() {
  56. rooms = parseRooms(await GM.getValue("rooms") || "");
  57. }
  58.  
  59. function parseRooms(text) {
  60. return text.split("\n")
  61. .map((a) => a.split(" "))
  62. .filter((a) => a.length == 3);
  63. }
  64.  
  65. async function saveRooms(text) {
  66. await GM.setValue("rooms", text);
  67. }
  68.  
  69. function playGame(obj) {
  70. var gamecontainer = document.querySelector(".chatbox3");
  71. gamecontainer.innerHTML += "<div style='width: 100%; height: 100%; margin: 0 auto; position:relative; z-index:1000;'> <iframe id='game-frame' style='width: 100%; height: 800px; margin: 0 auto; position:relative; z-index:1000;' src='https://tilde.town/~tunas/js_game_test/'>";
  72. }
  73.  
  74. function playAudio(obj) {
  75. var audiocontainer = document.querySelector(".fb-like");
  76. audiocontainer.innerHTML = "<audio autoplay src='" + obj.audio + "'>";
  77. }
  78.  
  79. function inspectPost(text) {
  80. let parts = text.split(/ +/);
  81. if (parts.length >= 5 && parts[1] == "Login" && parts[2] == "challenge:")
  82. return {action: async () => !await GM.getValue("disabled")
  83. && inspectChallenge(parts[3], parts[4])};
  84.  
  85. if (text.match(/^\s*\| .*is +your +username/))
  86. return {action: async () => {
  87. state.isTrollegle = true;
  88. await GM.getValue("autoCaptchaEnabled") && say("/cap");
  89. await GM.getValue("colorEnabled") && coloredMain();
  90. updateLurk();
  91. }};
  92.  
  93. if (text.match(/^\s*.*#A /)) {
  94. try {
  95. let obj = JSON.parse(text.slice(text.indexOf("{")));
  96. if ("game" in obj) {
  97. return{action: async() => await playGame(obj)};
  98. }
  99. if ("audio" in obj) {
  100. return {action: async () => await GM.getValue("audioEnabled") && playAudio(obj)};
  101. }
  102. if ("captchas" in obj)
  103. return {action: async () => !await GM.getValue("captchaDisabled")
  104. && inspectCaptcha(obj),
  105. override: logCaptchaCount(obj.captchas)};
  106. } catch (e) {
  107. console.log("Bad JSON: " + text);
  108. }
  109. }
  110. if (text.match(/users/) || text.match(/others/)) {
  111. console.log("narf");
  112. }
  113. return {};
  114. }
  115.  
  116. function logCaptchaCount(count) {
  117. if (count == state.captchas)
  118. return events => events.push(["stoppedTyping"]);
  119. state.captchas = count;
  120. return events => {
  121. events.push(["stoppedTyping"]);
  122. events.push(["serverMessage", "Captchas to solve: " + count]);
  123. };
  124. }
  125.  
  126. function inspectChallenge(salt, challenge) {
  127. var matching = rooms.filter((a) => Sha1.hash(salt + a[1]) == challenge);
  128. if (matching.length) {
  129. if (matching.length == 1) {
  130. var a = matching[0];
  131. log("This *seems* to be " + a[0]);
  132. say("/password " + Sha1.hash(salt + a[2]));
  133. } else {
  134. log("More than one matching room found (" + matching.map((a) => a[0]).join(", ") +
  135. "). There might be something amiss in the settings.");
  136. }
  137. } else {
  138. log("This doesn't look like a known room");
  139. }
  140. }
  141.  
  142. function say(text) {
  143. var chatmsg = document.querySelector(".chatmsg");
  144. chatmsg.value = text;
  145. var sendbtn = document.querySelector(".sendbtn");
  146. if (sendbtn)
  147. sendbtn.click();
  148. else
  149. chatmsg.parentNode.dispatchEvent(new MouseEvent("submit"));
  150. }
  151.  
  152. function sayQuiet(text, description) {
  153. if (state.backend) {
  154. console.log("sayQuiet: " + text);
  155. unXray(state.backend).sendMessage(text);
  156. log(description);
  157. } else {
  158. say(text);
  159. }
  160. }
  161.  
  162. function clearSession() {
  163. clearCaptcha();
  164. state.connectTime = null;
  165. state.isTrollegle = false;
  166. clearLurk();
  167. }
  168.  
  169. async function shouldLurk() {
  170. let mode = await lurkMode();
  171. return mode == "always" && state.connectTime || mode == "rooms" && state.isTrollegle;
  172. }
  173.  
  174. async function updateLurk() {
  175. let enabled = await shouldLurk();
  176. let newRate = await lurkRate();
  177. if (state.lurkHandle && enabled && newRate != state.lastLurkRate) {
  178. clearInterval(state.lurkHandle);
  179. setLurk(newRate);
  180. } else if (state.lurkHandle && !enabled) {
  181. clearLurk();
  182. } else if (!state.lurkHandle && enabled) {
  183. setLurk(newRate);
  184. }
  185. state.lastLurkRate = newRate;
  186. }
  187.  
  188. function setLurk(rate) {
  189. log("Setting lurk timer for " + rate + " min");
  190. if (Date.now() - state.connectTime > 1000 * 60)
  191. lurk();
  192. state.lurkHandle = setInterval(lurk, 1000 * 60 * rate);
  193. }
  194.  
  195. async function lurk() {
  196. if (document.querySelector(".chatmsg").value) return;
  197. let textSpec = await lurkText();
  198. let choices = textSpec.split(/\|/);
  199. let choice = choices[Math.floor(Math.random() * choices.length)];
  200. say(choice.replace("[TIMESTAMP]", Math.floor(Date.now() / 1000)));
  201. }
  202.  
  203. function clearLurk() {
  204. if (state.lurkHandle)
  205. log("Stopping lurk timer");
  206. clearInterval(state.lurkHandle);
  207. state.lurkHandle = null;
  208. }
  209.  
  210. function inspectCaptcha(obj) {
  211. if (obj.key) {
  212. state.captchaKey = obj.key;
  213. console.log("set key: " + state.captchaKey);
  214. }
  215. if (obj.captchas)
  216. showCaptcha();
  217. else if (obj.captchas === 0)
  218. hideCaptcha();
  219. console.log("key after inspectCaptcha: " + state.captchaKey);
  220. }
  221.  
  222. function clearCaptcha() {
  223. state.captchas = 0;
  224. hideCaptcha();
  225. }
  226.  
  227. function showCaptcha() {
  228. try {
  229. let container = ensureCaptchaElement();
  230. if (state.captchaWidget === null || !container.children.length) {
  231. state.captchaWidget = state.window.grecaptcha.render(clone(container), clone({
  232. sitekey: state.captchaKey,
  233. callback: wrap(submitCaptcha),
  234. }));
  235. }
  236. container.style.visibility = "visible";
  237. } catch (e) {
  238. console.log(e);
  239. }
  240. }
  241.  
  242. function hideCaptcha() {
  243. let container = ensureCaptchaElement();
  244. container.style.visibility = "collapse";
  245. resetCaptcha();
  246. }
  247.  
  248. function ensureCaptchaElement() {
  249. let element = document.querySelector("#trollegle-captcha");
  250. if (!element) {
  251. document.body.appendChild(
  252. element = E("div", {id: "trollegle-captcha"}));
  253. style(element, {position: "absolute", top: "0", left: "0"});
  254. }
  255. return element;
  256. }
  257.  
  258. function submitCaptcha(response) {
  259. sayQuiet("/cap " + JSON.stringify({key: state.captchaKey, token: response}),
  260. "Captcha submitted");
  261. resetCaptcha();
  262. }
  263.  
  264. function resetCaptcha() {
  265. let container = ensureCaptchaElement();
  266. if (state.captchaWidget !== null && container.children.length)
  267. state.window.grecaptcha.reset(state.captchaWidget);
  268. }
  269.  
  270. function log(message) {
  271. document.querySelector(".logbox").children[0].appendChild(
  272. E("div", {"class": "logitem"},
  273. E("p", {"class": "statuslog"}, message)));
  274. }
  275.  
  276. function E(tag, attrs, content) {
  277. function addContent(elem, content) {
  278. if (content instanceof Node) {
  279. elem.appendChild(content);
  280. } else {
  281. if (elem.styleSheet) {
  282. elem.styleSheet.cssText = (elem.styleSheet.cssText || "") + content;
  283. } else {
  284. elem.appendChild(document.createTextNode(content));
  285. }
  286. }
  287. }
  288. var elem = document.createElement(tag);
  289. if (attrs) Object.getOwnPropertyNames(attrs).forEach(function(name) {
  290. elem.setAttribute(name, attrs[name]);
  291. });
  292. if (content) {
  293. if (content instanceof Array)
  294. content.forEach(function(a) {addContent(elem, a)});
  295. else
  296. addContent(elem, content);
  297. }
  298. return elem;
  299. };
  300.  
  301. function style(elem, spec) {
  302. Object.getOwnPropertyNames(spec).forEach(function(prop) {
  303. elem.style[prop] = spec[prop];
  304. });
  305. return elem;
  306. }
  307.  
  308. async function editor(callback) {
  309. var win, list, lurkModeList, lurkRateInput, lurkTextInput,
  310. captchaCheck, autoCaptchaCheck, audioCheck, colorCheck, loginCheck, save, cancel;
  311. win = E("form", {id: "prefbox"}, [
  312. E("div", {}, [
  313. E("label", {"for": "lurkMode"}, "Lurk: "),
  314. lurkModeList = E("select", {id: "lurkMode"},
  315. lurkModes.map(mode => E("option", {"value": mode.value}, mode.name))),
  316. ]),
  317. E("div", {}, [
  318. E("label", {"for": "lurkText", "class": "sublabel"}, "sending "),
  319. lurkTextInput = E("input", {id: "lurkText"}),
  320. ]),
  321. E("div", {}, [
  322. E("label", {"for": "lurkRate", "class": "sublabel"}, "every "),
  323. lurkRateInput = E("input", {id: "lurkRate", type: "number"}),
  324. E("label", {"for": "lurkRate"}, " min"),
  325. ]),
  326. E("div", {}, [
  327. captchaCheck = E("input", {id: "captchaEnabled", type: "checkbox"}),
  328. E("label", {"for": "captchaEnabled"}, "Load captcha widget"),
  329. ]),
  330. E("div", {}, [
  331. autoCaptchaCheck = E("input", {id: "autoCaptcha", type: "checkbox"}),
  332. E("label", {"for": "autoCaptcha"}, "Ask room for captchas upon joining"),
  333. ]),
  334. E("div", {}, [
  335. audioCheck = E("input", {id: "audio", type: "checkbox"}),
  336. E("label", {"for": "audio"}, "Allow rooms to play audio"),
  337. ]),
  338. E("div", {}, [
  339. colorCheck = E("input", {id: "color", type: "checkbox"}),
  340. E("label", {"for": "color"}, "Colorize room"),
  341. ]),
  342. E("div", {}, [
  343. loginCheck = E("input", {id: "enabled", type: "checkbox"}),
  344. E("label", {"for": "enabled"}, "Enable admin login with credentials:"),
  345. ]),
  346. list = E("textarea", {id: "rooms"}, await GM.getValue("rooms")),
  347. E("label", {"for": "rooms"}, ["(one room per line, ",
  348. E("em", {}, "roomname challenge response"), ")"]),
  349. save = E("button", {type: "button"}, "Save"),
  350. cancel = E("button", {type: "button"}, "Cancel"),
  351. ]);
  352. [list, lurkModeList, lurkRateInput, lurkTextInput, captchaCheck, autoCaptchaCheck, audioCheck, loginCheck, save, cancel]
  353. .forEach(widget => widget.onkeyup = widget.onkeydown = ev => ev.stopPropagation());
  354. lurkModeList.value = await lurkMode();
  355. lurkRateInput.value = await lurkRate();
  356. lurkTextInput.value = await lurkText();
  357. captchaCheck.checked = !await GM.getValue("captchaDisabled");
  358. autoCaptchaCheck.checked = await GM.getValue("autoCaptchaEnabled");
  359. audioCheck.checked = await GM.getValue("audioEnabled");
  360. colorCheck.checked = await GM.getValue("colorEnabled");
  361. loginCheck.checked = !await GM.getValue("disabled");
  362. style(win, {
  363. display: "block",
  364. position: "fixed",
  365. right: 0,
  366. top: 0,
  367. border: "solid black 0.1em",
  368. background: "white",
  369. color: "black",
  370. zIndex: 100,
  371. padding: "0.2em",
  372. });
  373. style(lurkRateInput, {width: "4em"});
  374. style(lurkTextInput, {width: "11em"});
  375. save.onclick = async function() {
  376. if (!captchaCheck.checked)
  377. hideCaptcha();
  378. else if (state.captchas)
  379. showCaptcha();
  380. GM.setValue("captchaDisabled", !captchaCheck.checked && "true" || "");
  381. GM.setValue("autoCaptchaEnabled", autoCaptchaCheck.checked && "true" || "");
  382. GM.setValue("audioEnabled", audioCheck.checked && "true" || "");
  383. GM.setValue("colorEnabled", colorCheck.checked && "true" || "");
  384. GM.setValue("disabled", !loginCheck.checked && "true" || "");
  385. GM.setValue("lurkText", state.lurkText = lurkTextInput.value);
  386. await GM.setValue("lurkRate", state.lurkRate = Number(lurkRateInput.value));
  387. await GM.setValue("lurkMode", state.lurkMode = lurkModeList.value);
  388. await saveRooms(list.value);
  389. win.parentNode.removeChild(win);
  390. callback();
  391. return false;
  392. };
  393. cancel.onclick = function() {
  394. win.parentNode.removeChild(win);
  395. callback();
  396. return false;
  397. };
  398. document.body.appendChild(win);
  399. }
  400.  
  401. function win() {
  402. try {
  403. return unsafeWindow;
  404. } catch (e) {
  405. return window;
  406. }
  407. }
  408.  
  409. function unXray(obj) {
  410. return obj.wrappedJSObject || obj;
  411. }
  412.  
  413. function wrap(fun) {
  414. try {
  415. return exportFunction(fun, unsafeWindow, {allowCrossOriginArguments: true});
  416. } catch (e) {
  417. return fun;
  418. }
  419. }
  420.  
  421. function clone(obj) {
  422. try {
  423. return cloneInto(obj, unsafeWindow, {cloneFunctions: true, wrapReflectors: true});
  424. } catch (e) {
  425. return obj;
  426. }
  427. }
  428.  
  429. function begin() {
  430. let window = state.window = win();
  431. if (!window.COMETBackend) {
  432. setTimeout(begin, 500);
  433. } else {
  434. if (!window.COMETBackend.prototype.Trollegle$gotEvents) {
  435. window.COMETBackend.prototype.Trollegle$gotEvents =
  436. window.COMETBackend.prototype.gotEvents;
  437. window.COMETBackend.prototype.Trollegle$disconnect =
  438. window.COMETBackend.prototype.disconnect;
  439. var button = document.createElement("button");
  440. var update = async function() {
  441. button.textContent = "Trollegle ▾";
  442. updateRooms();
  443. updateLurk();
  444. };
  445. window.addEventListener("focus", update);
  446. update();
  447. button.onclick = function() {
  448. editor(update);
  449. return false;
  450. };
  451. (document.querySelector("#sharebuttons")
  452. || document.querySelector("#header")).appendChild(button);
  453. }
  454. var newGotEvents = function (events) {
  455. state.backend = this;
  456. if (!state.connectTime) {
  457. state.connectTime = Date.now();
  458. updateLurk();
  459. }
  460. let remaining = [];
  461. events.forEach(function (event) {
  462. if (event[0] == "gotMessage") {
  463. let result = inspectPost(event[1]);
  464. if (result.action)
  465. result.action();
  466. if (result.override) {
  467. console.log("gotMessage overridden: " + event[1]);
  468. result.override(remaining);
  469. return;
  470. }
  471. }
  472. remaining.push(event);
  473. });
  474. unXray(this).Trollegle$gotEvents(clone(remaining));
  475. if (unXray(this).stopped)
  476. clearSession();
  477. };
  478. var newDisconnect = function () {
  479. unXray(this).Trollegle$disconnect();
  480. clearSession();
  481. };
  482. window.COMETBackend.prototype.gotEvents = wrap(newGotEvents);
  483. window.COMETBackend.prototype.disconnect = wrap(newDisconnect);
  484. }
  485. }
  486.  
  487. // Code for colorizing
  488. // new message listener and color assignment
  489. function coloredMain() {
  490. 'use strict';
  491. say("/dids");
  492. var msges = document.getElementsByClassName('logbox')[0].firstChild;
  493. var background = document.getElementsByClassName('logbox')[0];
  494. background.style.background = '#263C4F';
  495. background.style.fontFamily = 'monospace';
  496. background.style.fontSize = "13pt";
  497. var idRegex = /.*?((\d+))/gm;
  498.  
  499. function change(obj){
  500. var idstr = idRegex.exec(obj.innerHTML);
  501. if (idstr != null){
  502. var col = parseInt(idstr[1]) * 20;
  503. obj.style.color = colourlist[parseInt(idstr[1])];
  504. }else{
  505. obj.style.color = '#ffffff';
  506. }
  507. }
  508.  
  509. var observrOptions = {
  510. childList: true
  511. }
  512.  
  513. var observr = new MutationObserver(mutationList => {
  514. // Loop over the mutations
  515. mutationList.forEach(mutation => {
  516. // For added nodes apply the color function
  517. mutation.addedNodes.forEach(node => {
  518. change(node)
  519. //console.log(node)
  520. })
  521. })
  522. })
  523.  
  524. observr.observe(msges, observrOptions);
  525. }
  526.  
  527. begin();
  528.  
  529. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  530. /* SHA-1 (FIPS 180-4) implementation in JavaScript (c) Chris Veness 2002-2016 */
  531. /* MIT Licence */
  532. /* www.movable-type.co.uk/scripts/sha1.html */
  533. /* */
  534. /* - see http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html */
  535. /* http://csrc.nist.gov/groups/ST/toolkit/examples.html */
  536. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  537.  
  538.  
  539.  
  540. /**
  541. * SHA-1 hash function reference implementation.
  542. *
  543. * This is a direct implementation of FIPS 180-4, without any optimisations. It is intended to aid
  544. * understanding of the algorithm rather than for production use, though it could be used where
  545. * performance is not critical.
  546. *
  547. * @namespace
  548. */
  549. var Sha1 = {};
  550.  
  551. (function () {
  552. 'use strict';
  553.  
  554.  
  555. /**
  556. * Generates SHA-1 hash of string.
  557. *
  558. * @param {string} msg - (Unicode) string to be hashed.
  559. * @param {Object} [options]
  560. * @param {string} [options.msgFormat=string] - Message format: 'string' for JavaScript string
  561. * (gets converted to UTF-8 for hashing); 'hex-bytes' for string of hex bytes ('616263' ≡ 'abc') .
  562. * @param {string} [options.outFormat=hex] - Output format: 'hex' for string of contiguous
  563. * hex bytes; 'hex-w' for grouping hex bytes into groups of (4 byte / 8 character) words.
  564. * @returns {string} Hash of msg as hex character string.
  565. */
  566. Sha1.hash = function(msg, options) {
  567. var defaults = { msgFormat: 'string', outFormat: 'hex' };
  568. var opt = Object.assign(defaults, options);
  569.  
  570. switch (opt.msgFormat) {
  571. default: // default is to convert string to UTF-8, as SHA only deals with byte-streams
  572. case 'string': msg = Sha1.utf8Encode(msg); break;
  573. case 'hex-bytes':msg = Sha1.hexBytesToString(msg); break; // mostly for running tests
  574. }
  575.  
  576. // constants [§4.2.1]
  577. var K = [ 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 ];
  578.  
  579. // initial hash value [§5.3.1]
  580. var H = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];
  581.  
  582. // PREPROCESSING [§6.1.1]
  583.  
  584. msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1]
  585.  
  586. // convert string msg into 512-bit/16-integer blocks arrays of ints [§5.2.1]
  587. var l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length
  588. var N = Math.ceil(l/16); // number of 16-integer-blocks required to hold 'l' ints
  589. var M = new Array(N);
  590.  
  591. for (var i=0; i<N; i++) {
  592. M[i] = new Array(16);
  593. for (var j=0; j<16; j++) { // encode 4 chars per integer, big-endian encoding
  594. M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) |
  595. (msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
  596. } // note running off the end of msg is ok 'cos bitwise ops on NaN return 0
  597. }
  598. // add length (in bits) into final pair of 32-bit integers (big-endian) [§5.1.1]
  599. // note: most significant word would be (len-1)*8 >>> 32, but since JS converts
  600. // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators
  601. M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14]);
  602. M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;
  603.  
  604. // HASH COMPUTATION [§6.1.2]
  605.  
  606. for (var i=0; i<N; i++) {
  607. var W = new Array(80);
  608.  
  609. // 1 - prepare message schedule 'W'
  610. for (var t=0; t<16; t++) W[t] = M[i][t];
  611. for (var t=16; t<80; t++) W[t] = Sha1.ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
  612.  
  613. // 2 - initialise five working variables a, b, c, d, e with previous hash value
  614. var a = H[0], b = H[1], c = H[2], d = H[3], e = H[4];
  615.  
  616. // 3 - main loop (use JavaScript '>>> 0' to emulate UInt32 variables)
  617. for (var t=0; t<80; t++) {
  618. var s = Math.floor(t/20); // seq for blocks of 'f' functions and 'K' constants
  619. var T = (Sha1.ROTL(a,5) + Sha1.f(s,b,c,d) + e + K[s] + W[t]) >>> 0;
  620. e = d;
  621. d = c;
  622. c = Sha1.ROTL(b, 30) >>> 0;
  623. b = a;
  624. a = T;
  625. }
  626.  
  627. // 4 - compute the new intermediate hash value (note 'addition modulo 2^32' – JavaScript
  628. // '>>> 0' coerces to unsigned UInt32 which achieves modulo 2^32 addition)
  629. H[0] = (H[0]+a) >>> 0;
  630. H[1] = (H[1]+b) >>> 0;
  631. H[2] = (H[2]+c) >>> 0;
  632. H[3] = (H[3]+d) >>> 0;
  633. H[4] = (H[4]+e) >>> 0;
  634. }
  635.  
  636. // convert H0..H4 to hex strings (with leading zeros)
  637. for (var h=0; h<H.length; h++) H[h] = ('00000000'+H[h].toString(16)).slice(-8);
  638.  
  639. // concatenate H0..H4, with separator if required
  640. var separator = opt.outFormat=='hex-w' ? ' ' : '';
  641.  
  642. return H.join(separator);
  643. };
  644.  
  645.  
  646. /**
  647. * Function 'f' [§4.1.1].
  648. * @private
  649. */
  650. Sha1.f = function(s, x, y, z) {
  651. switch (s) {
  652. case 0: return (x & y) ^ (~x & z); // Ch()
  653. case 1: return x ^ y ^ z; // Parity()
  654. case 2: return (x & y) ^ (x & z) ^ (y & z); // Maj()
  655. case 3: return x ^ y ^ z; // Parity()
  656. }
  657. };
  658.  
  659. /**
  660. * Rotates left (circular left shift) value x by n positions [§3.2.5].
  661. * @private
  662. */
  663. Sha1.ROTL = function(x, n) {
  664. return (x<<n) | (x>>>(32-n));
  665. };
  666.  
  667.  
  668. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  669.  
  670.  
  671. /**
  672. * Encodes multi-byte string to utf8 - monsur.hossa.in/2012/07/20/utf-8-in-javascript.html
  673. */
  674. Sha1.utf8Encode = function(str) {
  675. return unescape(encodeURIComponent(str));
  676. };
  677.  
  678.  
  679. /**
  680. * Converts a string of a sequence of hex numbers to a string of characters (eg '616263' => 'abc').
  681. */
  682. Sha1.hexBytesToString = function(hexStr) {
  683. hexStr = hexStr.replace(' ', ''); // allow space-separated groups
  684. var str = '';
  685. for (var i=0; i<hexStr.length; i+=2) {
  686. str += String.fromCharCode(parseInt(hexStr.slice(i, i+2), 16));
  687. }
  688. return str;
  689. };
  690. })();
  691.  
  692. var colourlist = ['#24d654', '#75d428', '#d46128','#d44528','#d6277e','#6b56f0','#42ebc3','#d4e362','#db4fa3','#da5ae0','#deab33','#d1a73d','#787deb','#80d66d','#f27777','#e8b600','#dbe868','#d65899','#6ade6a','#09d66f','#8eedac','#eddb64','#b80b98','#98de43','#c800ff','#ed85d7'];
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement