diff --git a/hush-hush.js b/hush-hush.js index 130e4bc..d9c9b24 100644 --- a/hush-hush.js +++ b/hush-hush.js @@ -17,7 +17,8 @@ */ var findMessageIntervalTime = 5000 var publicNodes = [ - "yre3tmbu25lcogl42xlh73wfchgbx3unz2zz3ttyiylj6gaq5mzhevid" + "yre3tmbu25lcogl42xlh73wfchgbx3unz2zz3ttyiylj6gaq5mzhevid", + "ltqmmfww3tue6tibtyfc4kk7edh3owewxwcgrkvwqw4cwgd3w3zcj6id" ] var messageHashes = [] var blocks = [] @@ -33,6 +34,8 @@ function shuffleArray(array) { [array[i], array[j]] = [array[j], array[i]]; } } +shuffleArray(publicNodes) + //https://stackoverflow.com/q/10420352 function getReadableFileSizeString(fileSizeInBytes) { var i = -1; @@ -62,12 +65,22 @@ function getCurrentNode(){ } function addMessage(message, timestamp){ + + message = DOMPurify.sanitize(marked(message), + {FORBID_ATTR: ['style'], + ALLOWED_TAGS: ['b', 'p', 'em', 'i', 'a', + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'center', 'br', 'hr']}) + + let childEl = document.createElement('div') + childEl.classList.add('content') + childEl.innerHTML = message var tmpl = document.getElementById("cMsgTemplate") let newEl = tmpl.content.cloneNode(true) - newEl.children[0].children[0].children[0].innerText = message + newEl.children[0].children[0].children[0].innerText = "" + newEl.children[0].children[0].children[0].append(childEl) newEl.children[0].children[0].children[2].innerText = timestamp - document.getElementsByClassName("messageFeed")[0].append(newEl) + document.getElementsByClassName("messageFeed")[0].prepend(newEl) } async function apiGET(path, queryString, raw=false){ @@ -91,6 +104,7 @@ async function findMessages(){ } let messages = (await apiGET("getblocklist", "?type=brd")).split('\n') messages.forEach(block => { + if (!block) { return} block = reconstructHash(block) if (!block.startsWith(difficulty)){console.debug("not difficulty reached:" + block); return} @@ -101,20 +115,20 @@ async function findMessages(){ // Size is size of data (not metadata) and block hash document.getElementById('memUsage').innerText = getReadableFileSizeString(current + ((basicTextEncoder.encode(data)).length + block.length)) } - + let metadata = JSON.parse(d.split("\n")[0]) + console.debug(metadata) + //let data = d.split('\n')[1] + let data = d.substring(d.indexOf('\n') + 1); try{ verifyBlock(d, block) - verifyTime() + verifyTime(metadata['time']) } catch(e){ console.debug(block + ":" + e) + return } - - let metadata = JSON.parse(d.split("\n")[0]) - console.debug(metadata) - let data = d.split('\n')[1] blocks.push(block) - addMessage(data, new Date(metadata['time'])) + addMessage(data, new Date(metadata['time'] * 1000)) updateMemoryUsage(data, block) }) }) diff --git a/index.html b/index.html index c08c9ec..b84f9d2 100644 --- a/index.html +++ b/index.html @@ -14,6 +14,7 @@ + @@ -35,7 +36,7 @@ JavaScript is required for this app. The server has no knowledge of posts, so content must be served by P2P nodes.

kiccan is a message board program that utilizes the Onionr network.

-

⏲️posts are rate-limited using a partial hash collision proof of work function.

+

posts are rate-limited using a partial hash collision proof of work function.

⚠️ the host of this web page has no control over posts. Browse and post at your own risk.

post memory usage: 0kb

@@ -46,7 +47,8 @@
- +

Markdown is supported, except for images, styles and scripts.

+
diff --git a/onionr-blocks.js b/onionr-blocks.js index a0569cd..a64c7d6 100644 --- a/onionr-blocks.js +++ b/onionr-blocks.js @@ -11,4 +11,9 @@ function verifyBlock(raw, hash){ } } - +function verifyTime(time){ + let epoch = Math.round(Date.now() / 1000); + if ((epoch - time) > maxBlockAge){ + throw new Error("Block is too old") + } +} diff --git a/peer-lookup.js b/peer-lookup.js index 0711238..56355c6 100644 --- a/peer-lookup.js +++ b/peer-lookup.js @@ -21,7 +21,8 @@ self.addEventListener('message', async function(e) { let lookupPeer = async function(peer){ let newList = await (await fetch('http://' + peer + '.onion/pex')).text() - newList = newList.replace('.onion', '') + newList = newList.replaceAll('.onion', '') + return newList.split(',') } var data = JSON.parse(e.data) diff --git a/purify.min.js b/purify.min.js new file mode 100644 index 0000000..39a1d08 --- /dev/null +++ b/purify.min.js @@ -0,0 +1,3 @@ +/*! @license DOMPurify | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.0.8/LICENSE */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).DOMPurify=t()}(this,(function(){"use strict";var e=Object.hasOwnProperty,t=Object.setPrototypeOf,n=Object.isFrozen,r=Object.freeze,o=Object.seal,i=Object.create,a="undefined"!=typeof Reflect&&Reflect,l=a.apply,c=a.construct;l||(l=function(e,t,n){return e.apply(t,n)}),r||(r=function(e){return e}),o||(o=function(e){return e}),c||(c=function(e,t){return new(Function.prototype.bind.apply(e,[null].concat(function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1?n-1:0),o=1;o/gm),F=o(/^data-[\-\w.\u00B7-\uFFFF]/),C=o(/^aria-[\-\w]+$/),H=o(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),z=o(/^(?:\w+script|data):/i),I=o(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),j="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function U(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t0&&void 0!==arguments[0]?arguments[0]:P(),n=function(t){return e(t)};if(n.version="2.1.1",n.removed=[],!t||!t.document||9!==t.document.nodeType)return n.isSupported=!1,n;var o=t.document,i=t.document,a=t.DocumentFragment,l=t.HTMLTemplateElement,c=t.Node,s=t.NodeFilter,T=t.NamedNodeMap,B=void 0===T?t.NamedNodeMap||t.MozNamedAttrMap:T,G=t.Text,q=t.Comment,K=t.DOMParser,V=t.trustedTypes;if("function"==typeof l){var Y=i.createElement("template");Y.content&&Y.content.ownerDocument&&(i=Y.content.ownerDocument)}var X=W(V,o),$=X&&Le?X.createHTML(""):"",Z=i,J=Z.implementation,Q=Z.createNodeIterator,ee=Z.getElementsByTagName,te=Z.createDocumentFragment,ne=o.importNode,re={};try{re=x(i).documentMode?i.documentMode:{}}catch(e){}var oe={};n.isSupported=J&&void 0!==J.createHTMLDocument&&9!==re;var ie=N,ae=R,le=F,ce=C,se=z,ue=I,de=H,fe=null,pe=A({},[].concat(U(S),U(k),U(_),U(D),U(E))),me=null,ye=A({},[].concat(U(L),U(w),U(M),U(O))),he=null,ge=null,ve=!0,be=!0,Te=!1,Ae=!1,xe=!1,Se=!1,ke=!1,_e=!1,De=!1,Ee=!1,Le=!1,we=!0,Me=!0,Oe=!1,Ne={},Re=A({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","plaintext","script","style","svg","template","thead","title","video","xmp"]),Fe=null,Ce=A({},["audio","video","img","source","image","track"]),He=null,ze=A({},["alt","class","for","id","label","name","pattern","placeholder","summary","title","value","style","xmlns"]),Ie=null,je=i.createElement("form"),Ue=function(e){Ie&&Ie===e||(e&&"object"===(void 0===e?"undefined":j(e))||(e={}),e=x(e),fe="ALLOWED_TAGS"in e?A({},e.ALLOWED_TAGS):pe,me="ALLOWED_ATTR"in e?A({},e.ALLOWED_ATTR):ye,He="ADD_URI_SAFE_ATTR"in e?A(x(ze),e.ADD_URI_SAFE_ATTR):ze,Fe="ADD_DATA_URI_TAGS"in e?A(x(Ce),e.ADD_DATA_URI_TAGS):Ce,he="FORBID_TAGS"in e?A({},e.FORBID_TAGS):{},ge="FORBID_ATTR"in e?A({},e.FORBID_ATTR):{},Ne="USE_PROFILES"in e&&e.USE_PROFILES,ve=!1!==e.ALLOW_ARIA_ATTR,be=!1!==e.ALLOW_DATA_ATTR,Te=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Ae=e.SAFE_FOR_TEMPLATES||!1,xe=e.WHOLE_DOCUMENT||!1,_e=e.RETURN_DOM||!1,De=e.RETURN_DOM_FRAGMENT||!1,Ee=e.RETURN_DOM_IMPORT||!1,Le=e.RETURN_TRUSTED_TYPE||!1,ke=e.FORCE_BODY||!1,we=!1!==e.SANITIZE_DOM,Me=!1!==e.KEEP_CONTENT,Oe=e.IN_PLACE||!1,de=e.ALLOWED_URI_REGEXP||de,Ae&&(be=!1),De&&(_e=!0),Ne&&(fe=A({},[].concat(U(E))),me=[],!0===Ne.html&&(A(fe,S),A(me,L)),!0===Ne.svg&&(A(fe,k),A(me,w),A(me,O)),!0===Ne.svgFilters&&(A(fe,_),A(me,w),A(me,O)),!0===Ne.mathMl&&(A(fe,D),A(me,M),A(me,O))),e.ADD_TAGS&&(fe===pe&&(fe=x(fe)),A(fe,e.ADD_TAGS)),e.ADD_ATTR&&(me===ye&&(me=x(me)),A(me,e.ADD_ATTR)),e.ADD_URI_SAFE_ATTR&&A(He,e.ADD_URI_SAFE_ATTR),Me&&(fe["#text"]=!0),xe&&A(fe,["html","head","body"]),fe.table&&(A(fe,["tbody"]),delete he.tbody),r&&r(e),Ie=e)},Pe=function(e){f(n.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.outerHTML=$}},We=function(e,t){try{f(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){f(n.removed,{attribute:null,from:t})}t.removeAttribute(e)},Be=function(e){var t=void 0,n=void 0;if(ke)e=""+e;else{var r=m(e,/^[\r\n\t ]+/);n=r&&r[0]}var o=X?X.createHTML(e):e;try{t=(new K).parseFromString(o,"text/html")}catch(e){}if(!t||!t.documentElement){var a=(t=J.createHTMLDocument("")).body;a.parentNode.removeChild(a.parentNode.firstElementChild),a.outerHTML=o}return e&&n&&t.body.insertBefore(i.createTextNode(n),t.body.childNodes[0]||null),ee.call(t,xe?"html":"body")[0]},Ge=function(e){return Q.call(e.ownerDocument||e,e,s.SHOW_ELEMENT|s.SHOW_COMMENT|s.SHOW_TEXT,(function(){return s.FILTER_ACCEPT}),!1)},qe=function(e){return!(e instanceof G||e instanceof q)&&!("string"==typeof e.nodeName&&"string"==typeof e.textContent&&"function"==typeof e.removeChild&&e.attributes instanceof B&&"function"==typeof e.removeAttribute&&"function"==typeof e.setAttribute&&"string"==typeof e.namespaceURI)},Ke=function(e){return"object"===(void 0===c?"undefined":j(c))?e instanceof c:e&&"object"===(void 0===e?"undefined":j(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},Ve=function(e,t,r){oe[e]&&u(oe[e],(function(e){e.call(n,t,r,Ie)}))},Ye=function(e){var t=void 0;if(Ve("beforeSanitizeElements",e,null),qe(e))return Pe(e),!0;if(m(e.nodeName,/[\u0080-\uFFFF]/))return Pe(e),!0;var r=p(e.nodeName);if(Ve("uponSanitizeElement",e,{tagName:r,allowedTags:fe}),("svg"===r||"math"===r)&&0!==e.querySelectorAll("p, br").length)return Pe(e),!0;if(!Ke(e.firstElementChild)&&(!Ke(e.content)||!Ke(e.content.firstElementChild))&&v(/<[!/\w]/g,e.innerHTML)&&v(/<[!/\w]/g,e.textContent))return Pe(e),!0;if(!fe[r]||he[r]){if(Me&&!Re[r]&&"function"==typeof e.insertAdjacentHTML)try{var o=e.innerHTML;e.insertAdjacentHTML("AfterEnd",X?X.createHTML(o):o)}catch(e){}return Pe(e),!0}return"noscript"!==r&&"noembed"!==r||!v(/<\/no(script|embed)/i,e.innerHTML)?(Ae&&3===e.nodeType&&(t=e.textContent,t=y(t,ie," "),t=y(t,ae," "),e.textContent!==t&&(f(n.removed,{element:e.cloneNode()}),e.textContent=t)),Ve("afterSanitizeElements",e,null),!1):(Pe(e),!0)},Xe=function(e,t,n){if(we&&("id"===t||"name"===t)&&(n in i||n in je))return!1;if(be&&v(le,t));else if(ve&&v(ce,t));else{if(!me[t]||ge[t])return!1;if(He[t]);else if(v(de,y(n,ue,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==h(n,"data:")||!Fe[e]){if(Te&&!v(se,y(n,ue,"")));else if(n)return!1}else;}return!0},$e=function(e){var t=void 0,r=void 0,o=void 0,i=void 0;Ve("beforeSanitizeAttributes",e,null);var a=e.attributes;if(a){var l={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:me};for(i=a.length;i--;){var c=t=a[i],s=c.name,u=c.namespaceURI;if(r=g(t.value),o=p(s),l.attrName=o,l.attrValue=r,l.keepAttr=!0,l.forceKeepAttr=void 0,Ve("uponSanitizeAttribute",e,l),r=l.attrValue,!l.forceKeepAttr&&(We(s,e),l.keepAttr))if(v(/\/>/i,r))We(s,e);else{Ae&&(r=y(r,ie," "),r=y(r,ae," "));var f=e.nodeName.toLowerCase();if(Xe(f,o,r))try{u?e.setAttributeNS(u,s,r):e.setAttribute(s,r),d(n.removed)}catch(e){}}}Ve("afterSanitizeAttributes",e,null)}},Ze=function e(t){var n=void 0,r=Ge(t);for(Ve("beforeSanitizeShadowDOM",t,null);n=r.nextNode();)Ve("uponSanitizeShadowNode",n,null),Ye(n)||(n.content instanceof a&&e(n.content),$e(n));Ve("afterSanitizeShadowDOM",t,null)};return n.sanitize=function(e,r){var i=void 0,l=void 0,s=void 0,u=void 0,d=void 0;if(e||(e="\x3c!--\x3e"),"string"!=typeof e&&!Ke(e)){if("function"!=typeof e.toString)throw b("toString is not a function");if("string"!=typeof(e=e.toString()))throw b("dirty is not a string, aborting")}if(!n.isSupported){if("object"===j(t.toStaticHTML)||"function"==typeof t.toStaticHTML){if("string"==typeof e)return t.toStaticHTML(e);if(Ke(e))return t.toStaticHTML(e.outerHTML)}return e}if(Se||Ue(r),n.removed=[],"string"==typeof e&&(Oe=!1),Oe);else if(e instanceof c)1===(l=(i=Be("\x3c!----\x3e")).ownerDocument.importNode(e,!0)).nodeType&&"BODY"===l.nodeName||"HTML"===l.nodeName?i=l:i.appendChild(l);else{if(!_e&&!Ae&&!xe&&-1===e.indexOf("<"))return X&&Le?X.createHTML(e):e;if(!(i=Be(e)))return _e?null:$}i&&ke&&Pe(i.firstChild);for(var f=Ge(Oe?e:i);s=f.nextNode();)3===s.nodeType&&s===u||Ye(s)||(s.content instanceof a&&Ze(s.content),$e(s),u=s);if(u=null,Oe)return e;if(_e){if(De)for(d=te.call(i.ownerDocument);i.firstChild;)d.appendChild(i.firstChild);else d=i;return Ee&&(d=ne.call(o,d,!0)),d}var p=xe?i.outerHTML:i.innerHTML;return Ae&&(p=y(p,ie," "),p=y(p,ae," ")),X&&Le?X.createHTML(p):p},n.setConfig=function(e){Ue(e),Se=!0},n.clearConfig=function(){Ie=null,Se=!1},n.isValidAttribute=function(e,t,n){Ie||Ue({});var r=p(e),o=p(t);return Xe(r,o,n)},n.addHook=function(e,t){"function"==typeof t&&(oe[e]=oe[e]||[],f(oe[e],t))},n.removeHook=function(e){oe[e]&&d(oe[e])},n.removeHooks=function(e){oe[e]&&(oe[e]=[])},n.removeAllHooks=function(){oe={}},n}()})); +//# sourceMappingURL=purify.min.js.map diff --git a/style.css b/style.css index b210f59..bff520e 100644 --- a/style.css +++ b/style.css @@ -4,4 +4,4 @@ .messageCreator{ margin-bottom: 1em; -} \ No newline at end of file +}