From 7fddefeb05d837e41e4ebf313eec2563fb912883 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jan 2024 10:36:59 +0100 Subject: [PATCH 1/8] password Signed-off-by: Tobias Gurtzick --- js/privatebin.js | 50 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index a3756f21..41ef9da0 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -228,7 +228,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { '<': '<', '>': '>', '"': '"', - "'": ''', + '\'': ''', '/': '/', '`': '`', '=': '=' @@ -2197,7 +2197,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @function * @param {Event} event */ - function submitPasswordModal(event) + async function submitPasswordModal(event) { event.preventDefault(); @@ -2207,6 +2207,19 @@ jQuery.PrivateBin = (function($, RawDeflate) { // hide modal $passwordModal.modal('hide'); + // check if protected pathname + const url = new URL(window.location); + + // if protected request password + if(url.pathname === '/protected') { + const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + const cipherdata = [enc.ct, enc.adata]; + + const plaindata = await CryptTool.decipher(enc.k, password, cipherdata); + window.location.replace(Helper.baseUri() + plaindata); + return; + } + PasteDecrypter.run(); } @@ -4778,16 +4791,32 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @param {int} status * @param {object} data */ - function showCreatedPaste(status, data) { + async function showCreatedPaste(status, data) { Alert.hideLoading(); Alert.hideMessages(); // show notification const baseUri = Helper.baseUri() + '?', - url = baseUri + data.id + '#' + CryptTool.base58encode(data.encryptionKey), - deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; + deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; PasteStatus.createPasteNotification(url, deleteUrl); + const pw = TopNav.getPassword() + const sm = CryptTool.getSymmetricKey(); + + let openUri = + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); + let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); + + let dt = {} + dt['v'] = 2; + dt['ct'] = cipherResult[0]; + dt['adata'] = cipherResult[1]; + dt['k'] = sm; + + const encUrl = CryptTool.base58encode(JSON.stringify(dt)) + + const url = baseUri + 'protected/#' + encUrl; + + // show new URL in browser bar history.pushState({type: 'newpaste'}, document.title, url); @@ -5518,6 +5547,17 @@ jQuery.PrivateBin = (function($, RawDeflate) { try { Model.getPasteId(); } catch (e) { + + // check if protected pathname + const url = new URL(window.location); + + // if protected request password + if(url.pathname === '/protected') { + const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + return Prompt.requestPassword(); + + } + // otherwise create a new paste return me.newPaste(); } From 2cc2cf0de769cee96311f639a3b338a7da50b0f9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jan 2024 12:28:41 +0100 Subject: [PATCH 2/8] working browser password Signed-off-by: Tobias Gurtzick --- js/privatebin.js | 80 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index bd5466f2..ed94a356 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -1512,7 +1512,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.getPasteKey = function() { if (symmetricKey === null) { - let newKey = window.location.hash.substring(1); + let pos = 1; + const pt = '#protected/'; + if(window.location.hash.startsWith(pt)) { + pos = pt.length; + } + let newKey = window.location.hash.substring(pos); if (newKey === '') { throw 'no encryption key given'; } @@ -2229,13 +2234,28 @@ jQuery.PrivateBin = (function($, RawDeflate) { const url = new URL(window.location); // if protected request password - if(url.pathname === '/protected') { - const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); - const cipherdata = [enc.ct, enc.adata]; + if(url.hash.startsWith('#protected/')) { + const pt = '#protected/'; + let pos = pt.length; + let newKey = window.location.hash.substring(pos); + if (newKey === '') { + throw 'no encryption key given'; + } - const plaindata = await CryptTool.decipher(enc.k, password, cipherdata); + // Some web 2.0 services and redirectors add data AFTER the anchor + // (such as &utm_source=...). We will strip any additional data. + let ampersandPos = newKey.indexOf('&'); + if (ampersandPos > -1) + { + newKey = newKey.substring(0, ampersandPos); + } + const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + const dt = JSON.parse(enc); + const cipherdata = [dt.ct, dt.adata] + + const plaindata = await CryptTool.decipher(dt.k, password, cipherdata); window.location.replace(Helper.baseUri() + plaindata); - return; + return; } PasteDecrypter.run(); @@ -4814,25 +4834,36 @@ jQuery.PrivateBin = (function($, RawDeflate) { Alert.hideMessages(); // show notification - const baseUri = Helper.baseUri() + '?', - deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; - PasteStatus.createPasteNotification(url, deleteUrl); + const baseUri = Helper.baseUri(), + deleteUrl = baseUri + '?pasteid=' + data.id + '&deletetoken=' + data.deletetoken; + let url; const pw = TopNav.getPassword() - const sm = CryptTool.getSymmetricKey(); - - let openUri = + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); - let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); - let dt = {} - dt['v'] = 2; - dt['ct'] = cipherResult[0]; - dt['adata'] = cipherResult[1]; - dt['k'] = sm; + if(pw && pw.length) { + + const sm = CryptTool.getSymmetricKey(); + + let openUri = '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); + let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); + + let dt = {} + dt['v'] = 2; + dt['ct'] = cipherResult[0]; + dt['adata'] = cipherResult[1]; + dt['k'] = sm; + + const encUrl = CryptTool.base58encode(JSON.stringify(dt)) + + url = baseUri + '#protected/' + encUrl; + } else { + url = baseUri + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); + } + + PasteStatus.createPasteNotification(url, deleteUrl); + - const encUrl = CryptTool.base58encode(JSON.stringify(dt)) - const url = baseUri + 'protected/#' + encUrl; // show new URL in browser bar @@ -4979,7 +5010,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { // prepare server interaction ServerInteraction.prepare(); - ServerInteraction.setCryptParameters(TopNav.getPassword()); + // This is not needed when encrypting browser side + // ServerInteraction.setCryptParameters(TopNav.getPassword()); + ServerInteraction.setCryptParameters(''); // set success/fail functions ServerInteraction.setSuccess(showCreatedPaste); @@ -5565,13 +5598,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { try { Model.getPasteId(); } catch (e) { - + // check if protected pathname const url = new URL(window.location); // if protected request password - if(url.pathname === '/protected') { - const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + if(url.hash.startsWith('#protected/')) { return Prompt.requestPassword(); } From 2a508cb7bfa541193901e8f89dd720635e334c63 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jan 2024 12:38:48 +0100 Subject: [PATCH 3/8] burn after reading only Signed-off-by: Tobias Gurtzick --- js/privatebin.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index 4fd5f1c7..23a4fe20 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -4862,7 +4862,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { const pw = TopNav.getPassword() - if(pw && pw.length) { + // only execute when it is a single time view + if(pw && pw.length && TopNav.getBurnAfterReading()) { const sm = CryptTool.getSymmetricKey(); @@ -5032,9 +5033,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { // prepare server interaction ServerInteraction.prepare(); - // This is not needed when encrypting browser side - // ServerInteraction.setCryptParameters(TopNav.getPassword()); - ServerInteraction.setCryptParameters(''); + if(!TopNav.getBurnAfterReading()) { + ServerInteraction.setCryptParameters(TopNav.getPassword()); + } else { + // not needed in this scenario + ServerInteraction.setCryptParameters(''); + } // set success/fail functions ServerInteraction.setSuccess(showCreatedPaste); From 0d2376cd8829d40f52c2fe9ecee47e273be21fc5 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 27 Jan 2024 11:33:54 +0100 Subject: [PATCH 4/8] bump libraries to DOMpurify 3.0.8 & zlib 1.3.1, increase compression level to 9 --- CHANGELOG.md | 3 ++- js/common.js | 6 +++--- js/purify-3.0.6.js | 2 -- js/purify-3.0.8.js | 2 ++ js/{zlib-1.3.js => zlib-1.3.1.js} | 2 +- js/{zlib-1.3.wasm => zlib-1.3.1.wasm} | Bin 58825 -> 58827 bytes tpl/bootstrap.php | 4 ++-- tpl/page.php | 4 ++-- 8 files changed, 12 insertions(+), 11 deletions(-) delete mode 100644 js/purify-3.0.6.js create mode 100644 js/purify-3.0.8.js rename js/{zlib-1.3.js => zlib-1.3.1.js} (99%) rename js/{zlib-1.3.wasm => zlib-1.3.1.wasm} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d39cd30..d1a6bdc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ## 1.6.3 (not yet released) * ADDED: Detect and report on damaged pastes (#1218) -* CHANGED: Upgrading libraries to: zlib 1.3 +* CHANGED: Increase zlib compression level from 7 to 9 +* CHANGED: Upgrading libraries to: DOMpurify 3.0.8 & zlib 1.3.1 * FIXED: Support more types of valid URLs for shorteners, incl. IDN ones (#1224) ## 1.6.2 (2023-12-15) diff --git a/js/common.js b/js/common.js index d3953d36..4519030f 100644 --- a/js/common.js +++ b/js/common.js @@ -12,12 +12,12 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test global.$ = global.jQuery = require('./jquery-3.7.0'); global.RawDeflate = require('./rawinflate-0.3').RawDeflate; -global.zlib = require('./zlib-1.3').zlib; +global.zlib = require('./zlib-1.3.1').zlib; require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; global.showdown = require('./showdown-2.1.0'); -global.DOMPurify = require('./purify-3.0.6'); +global.DOMPurify = require('./purify-3.0.8'); global.baseX = require('./base-x-4.0.0').baseX; global.Legacy = require('./legacy').Legacy; require('./bootstrap-3.4.1'); @@ -151,4 +151,4 @@ exports.urlToString = function (url) { return url.schema + '://' + url.address.join('') + '/' + (url.query ? '?' + encodeURI(url.query.join('').replace(/^&+|&+$/gm,'')) : '') + (url.fragment ? '#' + encodeURI(url.fragment) : ''); -}; \ No newline at end of file +}; diff --git a/js/purify-3.0.6.js b/js/purify-3.0.6.js deleted file mode 100644 index 65b3163d..00000000 --- a/js/purify-3.0.6.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! @license DOMPurify 3.0.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.6/LICENSE */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=N(Array.prototype.forEach),m=N(Array.prototype.pop),f=N(Array.prototype.push),p=N(String.prototype.toLowerCase),d=N(String.prototype.toString),h=N(String.prototype.match),g=N(String.prototype.replace),T=N(String.prototype.indexOf),y=N(String.prototype.trim),E=N(RegExp.prototype.test),A=(_=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:p;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function S(t){const n=l(null);for(const[o,i]of e(t))void 0!==r(t,o)&&(n[o]=i);return n}function R(e,t){for(;null!==e;){const n=r(e,t);if(n){if(n.get)return N(n.get);if("function"==typeof n.value)return N(n.value)}e=o(e)}return function(e){return console.warn("fallback value for",e),null}}const w=i(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),D=i(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),L=i(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),v=i(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),x=i(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),k=i(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),C=i(["#text"]),O=i(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","face","for","headers","height","hidden","high","href","hreflang","id","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","playsinline","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","xmlns","slot"]),I=i(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),M=i(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),U=i(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),P=a(/\{\{[\w\W]*|[\w\W]*\}\}/gm),F=a(/<%[\w\W]*|[\w\W]*%>/gm),H=a(/\${[\w\W]*}/gm),z=a(/^data-[\-\w.\u00B7-\uFFFF]/),B=a(/^aria-[\-\w]+$/),W=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),G=a(/^(?:\w+script|data):/i),Y=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),j=a(/^html$/i);var q=Object.freeze({__proto__:null,MUSTACHE_EXPR:P,ERB_EXPR:F,TMPLIT_EXPR:H,DATA_ATTR:z,ARIA_ATTR:B,IS_ALLOWED_URI:W,IS_SCRIPT_OR_DATA:G,ATTR_WHITESPACE:Y,DOCTYPE_NAME:j});const X=function(){return"undefined"==typeof window?null:window},K=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}};var V=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:X();const o=e=>t(e);if(o.version="3.0.6",o.removed=[],!n||!n.document||9!==n.document.nodeType)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:_,Node:N,Element:P,NodeFilter:F,NamedNodeMap:H=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:z,DOMParser:B,trustedTypes:G}=n,Y=P.prototype,V=R(Y,"cloneNode"),$=R(Y,"nextSibling"),Z=R(Y,"childNodes"),J=R(Y,"parentNode");if("function"==typeof _){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let Q,ee="";const{implementation:te,createNodeIterator:ne,createDocumentFragment:oe,getElementsByTagName:re}=r,{importNode:ie}=a;let ae={};o.isSupported="function"==typeof e&&"function"==typeof J&&te&&void 0!==te.createHTMLDocument;const{MUSTACHE_EXPR:le,ERB_EXPR:ce,TMPLIT_EXPR:se,DATA_ATTR:ue,ARIA_ATTR:me,IS_SCRIPT_OR_DATA:fe,ATTR_WHITESPACE:pe}=q;let{IS_ALLOWED_URI:de}=q,he=null;const ge=b({},[...w,...D,...L,...x,...C]);let Te=null;const ye=b({},[...O,...I,...M,...U]);let Ee=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ae=null,_e=null,Ne=!0,be=!0,Se=!1,Re=!0,we=!1,De=!1,Le=!1,ve=!1,xe=!1,ke=!1,Ce=!1,Oe=!0,Ie=!1;const Me="user-content-";let Ue=!0,Pe=!1,Fe={},He=null;const ze=b({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Be=null;const We=b({},["audio","video","img","source","image","track"]);let Ge=null;const Ye=b({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),je="http://www.w3.org/1998/Math/MathML",qe="http://www.w3.org/2000/svg",Xe="http://www.w3.org/1999/xhtml";let Ke=Xe,Ve=!1,$e=null;const Ze=b({},[je,qe,Xe],d);let Je=null;const Qe=["application/xhtml+xml","text/html"],et="text/html";let tt=null,nt=null;const ot=r.createElement("form"),rt=function(e){return e instanceof RegExp||e instanceof Function},it=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!nt||nt!==e){if(e&&"object"==typeof e||(e={}),e=S(e),Je=Je=-1===Qe.indexOf(e.PARSER_MEDIA_TYPE)?et:e.PARSER_MEDIA_TYPE,tt="application/xhtml+xml"===Je?d:p,he="ALLOWED_TAGS"in e?b({},e.ALLOWED_TAGS,tt):ge,Te="ALLOWED_ATTR"in e?b({},e.ALLOWED_ATTR,tt):ye,$e="ALLOWED_NAMESPACES"in e?b({},e.ALLOWED_NAMESPACES,d):Ze,Ge="ADD_URI_SAFE_ATTR"in e?b(S(Ye),e.ADD_URI_SAFE_ATTR,tt):Ye,Be="ADD_DATA_URI_TAGS"in e?b(S(We),e.ADD_DATA_URI_TAGS,tt):We,He="FORBID_CONTENTS"in e?b({},e.FORBID_CONTENTS,tt):ze,Ae="FORBID_TAGS"in e?b({},e.FORBID_TAGS,tt):{},_e="FORBID_ATTR"in e?b({},e.FORBID_ATTR,tt):{},Fe="USE_PROFILES"in e&&e.USE_PROFILES,Ne=!1!==e.ALLOW_ARIA_ATTR,be=!1!==e.ALLOW_DATA_ATTR,Se=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Re=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,we=e.SAFE_FOR_TEMPLATES||!1,De=e.WHOLE_DOCUMENT||!1,xe=e.RETURN_DOM||!1,ke=e.RETURN_DOM_FRAGMENT||!1,Ce=e.RETURN_TRUSTED_TYPE||!1,ve=e.FORCE_BODY||!1,Oe=!1!==e.SANITIZE_DOM,Ie=e.SANITIZE_NAMED_PROPS||!1,Ue=!1!==e.KEEP_CONTENT,Pe=e.IN_PLACE||!1,de=e.ALLOWED_URI_REGEXP||W,Ke=e.NAMESPACE||Xe,Ee=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ee.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ee.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ee.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),we&&(be=!1),ke&&(xe=!0),Fe&&(he=b({},[...C]),Te=[],!0===Fe.html&&(b(he,w),b(Te,O)),!0===Fe.svg&&(b(he,D),b(Te,I),b(Te,U)),!0===Fe.svgFilters&&(b(he,L),b(Te,I),b(Te,U)),!0===Fe.mathMl&&(b(he,x),b(Te,M),b(Te,U))),e.ADD_TAGS&&(he===ge&&(he=S(he)),b(he,e.ADD_TAGS,tt)),e.ADD_ATTR&&(Te===ye&&(Te=S(Te)),b(Te,e.ADD_ATTR,tt)),e.ADD_URI_SAFE_ATTR&&b(Ge,e.ADD_URI_SAFE_ATTR,tt),e.FORBID_CONTENTS&&(He===ze&&(He=S(He)),b(He,e.FORBID_CONTENTS,tt)),Ue&&(he["#text"]=!0),De&&b(he,["html","head","body"]),he.table&&(b(he,["tbody"]),delete Ae.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');Q=e.TRUSTED_TYPES_POLICY,ee=Q.createHTML("")}else void 0===Q&&(Q=K(G,c)),null!==Q&&"string"==typeof ee&&(ee=Q.createHTML(""));i&&i(e),nt=e}},at=b({},["mi","mo","mn","ms","mtext"]),lt=b({},["foreignobject","desc","title","annotation-xml"]),ct=b({},["title","style","font","a","script"]),st=b({},D);b(st,L),b(st,v);const ut=b({},x);b(ut,k);const mt=function(e){let t=J(e);t&&t.tagName||(t={namespaceURI:Ke,tagName:"template"});const n=p(e.tagName),o=p(t.tagName);return!!$e[e.namespaceURI]&&(e.namespaceURI===qe?t.namespaceURI===Xe?"svg"===n:t.namespaceURI===je?"svg"===n&&("annotation-xml"===o||at[o]):Boolean(st[n]):e.namespaceURI===je?t.namespaceURI===Xe?"math"===n:t.namespaceURI===qe?"math"===n&<[o]:Boolean(ut[n]):e.namespaceURI===Xe?!(t.namespaceURI===qe&&!lt[o])&&(!(t.namespaceURI===je&&!at[o])&&(!ut[n]&&(ct[n]||!st[n]))):!("application/xhtml+xml"!==Je||!$e[e.namespaceURI]))},ft=function(e){f(o.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.remove()}},pt=function(e,t){try{f(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){f(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Te[e])if(xe||ke)try{ft(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},dt=function(e){let t=null,n=null;if(ve)e=""+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===Je&&Ke===Xe&&(e=''+e+"");const o=Q?Q.createHTML(e):e;if(Ke===Xe)try{t=(new B).parseFromString(o,Je)}catch(e){}if(!t||!t.documentElement){t=te.createDocument(Ke,"template",null);try{t.documentElement.innerHTML=Ve?ee:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),Ke===Xe?re.call(t,De?"html":"body")[0]:De?t.documentElement:i},ht=function(e){return ne.call(e.ownerDocument||e,e,F.SHOW_ELEMENT|F.SHOW_COMMENT|F.SHOW_TEXT,null)},gt=function(e){return e instanceof z&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof H)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Tt=function(e){return"function"==typeof N&&e instanceof N},yt=function(e,t,n){ae[e]&&u(ae[e],(e=>{e.call(o,t,n,nt)}))},Et=function(e){let t=null;if(yt("beforeSanitizeElements",e,null),gt(e))return ft(e),!0;const n=tt(e.nodeName);if(yt("uponSanitizeElement",e,{tagName:n,allowedTags:he}),e.hasChildNodes()&&!Tt(e.firstElementChild)&&E(/<[/\w]/g,e.innerHTML)&&E(/<[/\w]/g,e.textContent))return ft(e),!0;if(!he[n]||Ae[n]){if(!Ae[n]&&_t(n)){if(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n))return!1;if(Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))return!1}if(Ue&&!He[n]){const t=J(e)||e.parentNode,n=Z(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o)t.insertBefore(V(n[o],!0),$(e))}}return ft(e),!0}return e instanceof P&&!mt(e)?(ft(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!E(/<\/no(script|embed|frames)/i,e.innerHTML)?(we&&3===e.nodeType&&(t=e.textContent,u([le,ce,se],(e=>{t=g(t,e," ")})),e.textContent!==t&&(f(o.removed,{element:e.cloneNode()}),e.textContent=t)),yt("afterSanitizeElements",e,null),!1):(ft(e),!0)},At=function(e,t,n){if(Oe&&("id"===t||"name"===t)&&(n in r||n in ot))return!1;if(be&&!_e[t]&&E(ue,t));else if(Ne&&E(me,t));else if(!Te[t]||_e[t]){if(!(_t(e)&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,e)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(e))&&(Ee.attributeNameCheck instanceof RegExp&&E(Ee.attributeNameCheck,t)||Ee.attributeNameCheck instanceof Function&&Ee.attributeNameCheck(t))||"is"===t&&Ee.allowCustomizedBuiltInElements&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))))return!1}else if(Ge[t]);else if(E(de,g(n,pe,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!Be[e]){if(Se&&!E(fe,g(n,pe,"")));else if(n)return!1}else;return!0},_t=function(e){return e.indexOf("-")>0},Nt=function(e){yt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Te};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=tt(a);let f="value"===a?c:y(c);if(n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,yt("uponSanitizeAttribute",e,n),f=n.attrValue,n.forceKeepAttr)continue;if(pt(a,e),!n.keepAttr)continue;if(!Re&&E(/\/>/i,f)){pt(a,e);continue}we&&u([le,ce,se],(e=>{f=g(f,e," ")}));const p=tt(e.nodeName);if(At(p,s,f)){if(!Ie||"id"!==s&&"name"!==s||(pt(a,e),f=Me+f),Q&&"object"==typeof G&&"function"==typeof G.getAttributeType)if(l);else switch(G.getAttributeType(p,s)){case"TrustedHTML":f=Q.createHTML(f);break;case"TrustedScriptURL":f=Q.createScriptURL(f)}try{l?e.setAttributeNS(l,a,f):e.setAttribute(a,f),m(o.removed)}catch(e){}}}yt("afterSanitizeAttributes",e,null)},bt=function e(t){let n=null;const o=ht(t);for(yt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)yt("uponSanitizeShadowNode",n,null),Et(n)||(n.content instanceof s&&e(n.content),Nt(n));yt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(Ve=!e,Ve&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Tt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Le||it(t),o.removed=[],"string"==typeof e&&(Pe=!1),Pe){if(e.nodeName){const t=tt(e.nodeName);if(!he[t]||Ae[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof N)n=dt("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),1===r.nodeType&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!xe&&!we&&!De&&-1===e.indexOf("<"))return Q&&Ce?Q.createHTML(e):e;if(n=dt(e),!n)return xe?null:Ce?ee:""}n&&ve&&ft(n.firstChild);const c=ht(Pe?e:n);for(;i=c.nextNode();)Et(i)||(i.content instanceof s&&bt(i.content),Nt(i));if(Pe)return e;if(xe){if(ke)for(l=oe.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Te.shadowroot||Te.shadowrootmode)&&(l=ie.call(a,l,!0)),l}let m=De?n.outerHTML:n.innerHTML;return De&&he["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&E(j,n.ownerDocument.doctype.name)&&(m="\n"+m),we&&u([le,ce,se],(e=>{m=g(m,e," ")})),Q&&Ce?Q.createHTML(m):m},o.setConfig=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};it(e),Le=!0},o.clearConfig=function(){nt=null,Le=!1},o.isValidAttribute=function(e,t,n){nt||it({});const o=tt(e),r=tt(t);return At(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(ae[e]=ae[e]||[],f(ae[e],t))},o.removeHook=function(e){if(ae[e])return m(ae[e])},o.removeHooks=function(e){ae[e]&&(ae[e]=[])},o.removeAllHooks=function(){ae={}},o}();return V})); diff --git a/js/purify-3.0.8.js b/js/purify-3.0.8.js new file mode 100644 index 00000000..9f090115 --- /dev/null +++ b/js/purify-3.0.8.js @@ -0,0 +1,2 @@ +/*! @license DOMPurify 3.0.8 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.8/LICENSE */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=b(Array.prototype.forEach),m=b(Array.prototype.pop),f=b(Array.prototype.push),p=b(String.prototype.toLowerCase),d=b(String.prototype.toString),h=b(String.prototype.match),g=b(String.prototype.replace),T=b(String.prototype.indexOf),y=b(String.prototype.trim),E=b(RegExp.prototype.test),A=(_=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:p;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function S(e){for(let t=0;t/gm),z=a(/\${[\w\W]*}/gm),B=a(/^data-[\-\w.\u00B7-\uFFFF]/),W=a(/^aria-[\-\w]+$/),G=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Y=a(/^(?:\w+script|data):/i),j=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),q=a(/^html$/i);var X=Object.freeze({__proto__:null,MUSTACHE_EXPR:F,ERB_EXPR:H,TMPLIT_EXPR:z,DATA_ATTR:B,ARIA_ATTR:W,IS_ALLOWED_URI:G,IS_SCRIPT_OR_DATA:Y,ATTR_WHITESPACE:j,DOCTYPE_NAME:q});const K=function(){return"undefined"==typeof window?null:window},V=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}};var $=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:K();const o=e=>t(e);if(o.version="3.0.8",o.removed=[],!n||!n.document||9!==n.document.nodeType)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:_,Node:b,Element:S,NodeFilter:F,NamedNodeMap:H=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:z,DOMParser:B,trustedTypes:W}=n,Y=S.prototype,j=w(Y,"cloneNode"),$=w(Y,"nextSibling"),Z=w(Y,"childNodes"),J=w(Y,"parentNode");if("function"==typeof _){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let Q,ee="";const{implementation:te,createNodeIterator:ne,createDocumentFragment:oe,getElementsByTagName:re}=r,{importNode:ie}=a;let ae={};o.isSupported="function"==typeof e&&"function"==typeof J&&te&&void 0!==te.createHTMLDocument;const{MUSTACHE_EXPR:le,ERB_EXPR:ce,TMPLIT_EXPR:se,DATA_ATTR:ue,ARIA_ATTR:me,IS_SCRIPT_OR_DATA:fe,ATTR_WHITESPACE:pe}=X;let{IS_ALLOWED_URI:de}=X,he=null;const ge=N({},[...D,...L,...v,...k,...O]);let Te=null;const ye=N({},[...I,...M,...U,...P]);let Ee=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ae=null,_e=null,be=!0,Ne=!0,Se=!1,Re=!0,we=!1,De=!1,Le=!1,ve=!1,xe=!1,ke=!1,Ce=!1,Oe=!0,Ie=!1;const Me="user-content-";let Ue=!0,Pe=!1,Fe={},He=null;const ze=N({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Be=null;const We=N({},["audio","video","img","source","image","track"]);let Ge=null;const Ye=N({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),je="http://www.w3.org/1998/Math/MathML",qe="http://www.w3.org/2000/svg",Xe="http://www.w3.org/1999/xhtml";let Ke=Xe,Ve=!1,$e=null;const Ze=N({},[je,qe,Xe],d);let Je=null;const Qe=["application/xhtml+xml","text/html"],et="text/html";let tt=null,nt=null;const ot=r.createElement("form"),rt=function(e){return e instanceof RegExp||e instanceof Function},it=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!nt||nt!==e){if(e&&"object"==typeof e||(e={}),e=R(e),Je=-1===Qe.indexOf(e.PARSER_MEDIA_TYPE)?et:e.PARSER_MEDIA_TYPE,tt="application/xhtml+xml"===Je?d:p,he="ALLOWED_TAGS"in e?N({},e.ALLOWED_TAGS,tt):ge,Te="ALLOWED_ATTR"in e?N({},e.ALLOWED_ATTR,tt):ye,$e="ALLOWED_NAMESPACES"in e?N({},e.ALLOWED_NAMESPACES,d):Ze,Ge="ADD_URI_SAFE_ATTR"in e?N(R(Ye),e.ADD_URI_SAFE_ATTR,tt):Ye,Be="ADD_DATA_URI_TAGS"in e?N(R(We),e.ADD_DATA_URI_TAGS,tt):We,He="FORBID_CONTENTS"in e?N({},e.FORBID_CONTENTS,tt):ze,Ae="FORBID_TAGS"in e?N({},e.FORBID_TAGS,tt):{},_e="FORBID_ATTR"in e?N({},e.FORBID_ATTR,tt):{},Fe="USE_PROFILES"in e&&e.USE_PROFILES,be=!1!==e.ALLOW_ARIA_ATTR,Ne=!1!==e.ALLOW_DATA_ATTR,Se=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Re=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,we=e.SAFE_FOR_TEMPLATES||!1,De=e.WHOLE_DOCUMENT||!1,xe=e.RETURN_DOM||!1,ke=e.RETURN_DOM_FRAGMENT||!1,Ce=e.RETURN_TRUSTED_TYPE||!1,ve=e.FORCE_BODY||!1,Oe=!1!==e.SANITIZE_DOM,Ie=e.SANITIZE_NAMED_PROPS||!1,Ue=!1!==e.KEEP_CONTENT,Pe=e.IN_PLACE||!1,de=e.ALLOWED_URI_REGEXP||G,Ke=e.NAMESPACE||Xe,Ee=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ee.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ee.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ee.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),we&&(Ne=!1),ke&&(xe=!0),Fe&&(he=N({},O),Te=[],!0===Fe.html&&(N(he,D),N(Te,I)),!0===Fe.svg&&(N(he,L),N(Te,M),N(Te,P)),!0===Fe.svgFilters&&(N(he,v),N(Te,M),N(Te,P)),!0===Fe.mathMl&&(N(he,k),N(Te,U),N(Te,P))),e.ADD_TAGS&&(he===ge&&(he=R(he)),N(he,e.ADD_TAGS,tt)),e.ADD_ATTR&&(Te===ye&&(Te=R(Te)),N(Te,e.ADD_ATTR,tt)),e.ADD_URI_SAFE_ATTR&&N(Ge,e.ADD_URI_SAFE_ATTR,tt),e.FORBID_CONTENTS&&(He===ze&&(He=R(He)),N(He,e.FORBID_CONTENTS,tt)),Ue&&(he["#text"]=!0),De&&N(he,["html","head","body"]),he.table&&(N(he,["tbody"]),delete Ae.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');Q=e.TRUSTED_TYPES_POLICY,ee=Q.createHTML("")}else void 0===Q&&(Q=V(W,c)),null!==Q&&"string"==typeof ee&&(ee=Q.createHTML(""));i&&i(e),nt=e}},at=N({},["mi","mo","mn","ms","mtext"]),lt=N({},["foreignobject","desc","title","annotation-xml"]),ct=N({},["title","style","font","a","script"]),st=N({},[...L,...v,...x]),ut=N({},[...k,...C]),mt=function(e){let t=J(e);t&&t.tagName||(t={namespaceURI:Ke,tagName:"template"});const n=p(e.tagName),o=p(t.tagName);return!!$e[e.namespaceURI]&&(e.namespaceURI===qe?t.namespaceURI===Xe?"svg"===n:t.namespaceURI===je?"svg"===n&&("annotation-xml"===o||at[o]):Boolean(st[n]):e.namespaceURI===je?t.namespaceURI===Xe?"math"===n:t.namespaceURI===qe?"math"===n&<[o]:Boolean(ut[n]):e.namespaceURI===Xe?!(t.namespaceURI===qe&&!lt[o])&&(!(t.namespaceURI===je&&!at[o])&&(!ut[n]&&(ct[n]||!st[n]))):!("application/xhtml+xml"!==Je||!$e[e.namespaceURI]))},ft=function(e){f(o.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.remove()}},pt=function(e,t){try{f(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){f(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Te[e])if(xe||ke)try{ft(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},dt=function(e){let t=null,n=null;if(ve)e=""+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===Je&&Ke===Xe&&(e=''+e+"");const o=Q?Q.createHTML(e):e;if(Ke===Xe)try{t=(new B).parseFromString(o,Je)}catch(e){}if(!t||!t.documentElement){t=te.createDocument(Ke,"template",null);try{t.documentElement.innerHTML=Ve?ee:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),Ke===Xe?re.call(t,De?"html":"body")[0]:De?t.documentElement:i},ht=function(e){return ne.call(e.ownerDocument||e,e,F.SHOW_ELEMENT|F.SHOW_COMMENT|F.SHOW_TEXT,null)},gt=function(e){return e instanceof z&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof H)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Tt=function(e){return"function"==typeof b&&e instanceof b},yt=function(e,t,n){ae[e]&&u(ae[e],(e=>{e.call(o,t,n,nt)}))},Et=function(e){let t=null;if(yt("beforeSanitizeElements",e,null),gt(e))return ft(e),!0;const n=tt(e.nodeName);if(yt("uponSanitizeElement",e,{tagName:n,allowedTags:he}),e.hasChildNodes()&&!Tt(e.firstElementChild)&&E(/<[/\w]/g,e.innerHTML)&&E(/<[/\w]/g,e.textContent))return ft(e),!0;if(!he[n]||Ae[n]){if(!Ae[n]&&_t(n)){if(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n))return!1;if(Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))return!1}if(Ue&&!He[n]){const t=J(e)||e.parentNode,n=Z(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o)t.insertBefore(j(n[o],!0),$(e))}}return ft(e),!0}return e instanceof S&&!mt(e)?(ft(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!E(/<\/no(script|embed|frames)/i,e.innerHTML)?(we&&3===e.nodeType&&(t=e.textContent,u([le,ce,se],(e=>{t=g(t,e," ")})),e.textContent!==t&&(f(o.removed,{element:e.cloneNode()}),e.textContent=t)),yt("afterSanitizeElements",e,null),!1):(ft(e),!0)},At=function(e,t,n){if(Oe&&("id"===t||"name"===t)&&(n in r||n in ot))return!1;if(Ne&&!_e[t]&&E(ue,t));else if(be&&E(me,t));else if(!Te[t]||_e[t]){if(!(_t(e)&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,e)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(e))&&(Ee.attributeNameCheck instanceof RegExp&&E(Ee.attributeNameCheck,t)||Ee.attributeNameCheck instanceof Function&&Ee.attributeNameCheck(t))||"is"===t&&Ee.allowCustomizedBuiltInElements&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))))return!1}else if(Ge[t]);else if(E(de,g(n,pe,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!Be[e]){if(Se&&!E(fe,g(n,pe,"")));else if(n)return!1}else;return!0},_t=function(e){return e.indexOf("-")>0},bt=function(e){yt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Te};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=tt(a);let f="value"===a?c:y(c);if(n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,yt("uponSanitizeAttribute",e,n),f=n.attrValue,n.forceKeepAttr)continue;if(pt(a,e),!n.keepAttr)continue;if(!Re&&E(/\/>/i,f)){pt(a,e);continue}we&&u([le,ce,se],(e=>{f=g(f,e," ")}));const p=tt(e.nodeName);if(At(p,s,f)){if(!Ie||"id"!==s&&"name"!==s||(pt(a,e),f=Me+f),Q&&"object"==typeof W&&"function"==typeof W.getAttributeType)if(l);else switch(W.getAttributeType(p,s)){case"TrustedHTML":f=Q.createHTML(f);break;case"TrustedScriptURL":f=Q.createScriptURL(f)}try{l?e.setAttributeNS(l,a,f):e.setAttribute(a,f),m(o.removed)}catch(e){}}}yt("afterSanitizeAttributes",e,null)},Nt=function e(t){let n=null;const o=ht(t);for(yt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)yt("uponSanitizeShadowNode",n,null),Et(n)||(n.content instanceof s&&e(n.content),bt(n));yt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(Ve=!e,Ve&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Tt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Le||it(t),o.removed=[],"string"==typeof e&&(Pe=!1),Pe){if(e.nodeName){const t=tt(e.nodeName);if(!he[t]||Ae[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof b)n=dt("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),1===r.nodeType&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!xe&&!we&&!De&&-1===e.indexOf("<"))return Q&&Ce?Q.createHTML(e):e;if(n=dt(e),!n)return xe?null:Ce?ee:""}n&&ve&&ft(n.firstChild);const c=ht(Pe?e:n);for(;i=c.nextNode();)Et(i)||(i.content instanceof s&&Nt(i.content),bt(i));if(Pe)return e;if(xe){if(ke)for(l=oe.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Te.shadowroot||Te.shadowrootmode)&&(l=ie.call(a,l,!0)),l}let m=De?n.outerHTML:n.innerHTML;return De&&he["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&E(q,n.ownerDocument.doctype.name)&&(m="\n"+m),we&&u([le,ce,se],(e=>{m=g(m,e," ")})),Q&&Ce?Q.createHTML(m):m},o.setConfig=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};it(e),Le=!0},o.clearConfig=function(){nt=null,Le=!1},o.isValidAttribute=function(e,t,n){nt||it({});const o=tt(e),r=tt(t);return At(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(ae[e]=ae[e]||[],f(ae[e],t))},o.removeHook=function(e){if(ae[e])return m(ae[e])},o.removeHooks=function(e){ae[e]&&(ae[e]=[])},o.removeAllHooks=function(){ae={}},o}();return $})); diff --git a/js/zlib-1.3.js b/js/zlib-1.3.1.js similarity index 99% rename from js/zlib-1.3.js rename to js/zlib-1.3.1.js index 268d0841..fbfb7154 100644 --- a/js/zlib-1.3.js +++ b/js/zlib-1.3.1.js @@ -6,7 +6,7 @@ async function initialize() { if (ret) return ret; - const COMPRESSION_LEVEL = 7; + const COMPRESSION_LEVEL = 9; const NO_ZLIB_HEADER = -1; const CHUNK_SIZE = 32 * 1024; const map = {}; diff --git a/js/zlib-1.3.wasm b/js/zlib-1.3.1.wasm similarity index 99% rename from js/zlib-1.3.wasm rename to js/zlib-1.3.1.wasm index c954fbd400e2f4cecc5d8c4188a451b1a93c6ca2..2fbc9169aa9773114c878399fddd11eb94890301 100644 GIT binary patch delta 42 ycmX?kn)&o;<_+I=ieI?i(7<5M;K;(wv>}wiQGlD(P|sM;a5ML=-P+8j8GHe6cn+rk delta 40 ycmV+@0N4M^%LB>F1F-hF70%ayfB-iDK?Dl|uvGv-5DNn_E;F+Yy1Od_#sJGz=MKF9 diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 0cf27f5f..cea3da44 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) : - + @@ -71,7 +71,7 @@ if ($MARKDOWN) : - + diff --git a/tpl/page.php b/tpl/page.php index 7e62f37e..011415be 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY): - + - + From d0e03e5167f5714da720a088915df75509356f42 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 27 Jan 2024 18:26:19 +0100 Subject: [PATCH 5/8] change logic into asking for loading confirmation also: - fixes #1039 - email buttons overlapping in some languages - fixes #1191 - language change URL mangling - adds focus to password input in modal - prevents needless reload on visiting default URL --- i18n/ar.json | 4 +- i18n/bg.json | 4 +- i18n/ca.json | 4 +- i18n/co.json | 4 +- i18n/cs.json | 4 +- i18n/de.json | 4 +- i18n/el.json | 4 +- i18n/en.json | 4 +- i18n/es.json | 4 +- i18n/et.json | 4 +- i18n/fi.json | 4 +- i18n/fr.json | 4 +- i18n/he.json | 4 +- i18n/hi.json | 4 +- i18n/hu.json | 4 +- i18n/id.json | 4 +- i18n/it.json | 4 +- i18n/ja.json | 4 +- i18n/jbo.json | 4 +- i18n/ku.json | 4 +- i18n/la.json | 4 +- i18n/lt.json | 4 +- i18n/nl.json | 4 +- i18n/no.json | 4 +- i18n/oc.json | 4 +- i18n/pl.json | 4 +- i18n/pt.json | 4 +- i18n/ru.json | 4 +- i18n/sk.json | 4 +- i18n/sl.json | 4 +- i18n/sv.json | 4 +- i18n/th.json | 4 +- i18n/tr.json | 4 +- i18n/uk.json | 4 +- i18n/zh.json | 4 +- js/privatebin.js | 152 +++++++++++++++++++--------------------------- tpl/bootstrap.php | 52 +++++++++------- tpl/page.php | 2 +- 38 files changed, 196 insertions(+), 150 deletions(-) diff --git a/i18n/ar.json b/i18n/ar.json index 06d50166..3752a362 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "عنوان IP الخاص بك غير مصرح له بإنشاء لصُق.", "Trying to shorten a URL that isn't pointing at our instance.": "محاولة تقصير عنوان URL لا يشير إلى خادمنا.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "خطأ في الاتصال بـ YOURLS. ربما تكون هناك مشكلة في التضبيط، مثل \"apiurl\" أو \"التوقيع\" الخاطئ أو المفقود.", - "Error parsing YOURLS response.": "خطأ في تحليل استجابة YOURLS." + "Error parsing YOURLS response.": "خطأ في تحليل استجابة YOURLS.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/bg.json b/i18n/bg.json index 9327467a..e7cb35a3 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ca.json b/i18n/ca.json index b9c5efbd..7ed9846b 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/co.json b/i18n/co.json index 0be1ff54..b848f0ef 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà l’appiccichi.", "Trying to shorten a URL that isn't pointing at our instance.": "Pruvate d’ammuzzà un indirizzu web chì ùn punta micca versu a vostra instanza.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una \"apiurl\" o \"signature\" falsa o assente.", - "Error parsing YOURLS response.": "Sbagliu durante l’analisa di a risposta di YOURLS." + "Error parsing YOURLS response.": "Sbagliu durante l’analisa di a risposta di YOURLS.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/cs.json b/i18n/cs.json index c049c733..49afae50 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/de.json b/i18n/de.json index fce60cc3..8e81f73c 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Deine IP ist nicht berechtigt, Texte zu erstellen.", "Trying to shorten a URL that isn't pointing at our instance.": "Versuch eine URL zu verkürzen, die nicht auf unsere Instanz zeigt.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Fehler beim Aufruf von YOURLS. Wahrscheinlich ein Konfigurationsproblem, wie eine falsche oder fehlende \"apiurl\" oder \"signature\".", - "Error parsing YOURLS response.": "Fehler beim Verarbeiten der YOURLS-Antwort." + "Error parsing YOURLS response.": "Fehler beim Verarbeiten der YOURLS-Antwort.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/el.json b/i18n/el.json index 388edec6..94e13fb9 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/en.json b/i18n/en.json index 68ff1aae..6ef3280b 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/es.json b/i18n/es.json index 97fab2fb..e5e4c9b5 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Tu IP no está autorizada para crear contenido.", "Trying to shorten a URL that isn't pointing at our instance.": "Intentando acortar una URL que no apunta a nuestra instancia.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/et.json b/i18n/et.json index 3cc47d55..e123e7f9 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/fi.json b/i18n/fi.json index 063df4a3..da935c52 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", "Trying to shorten a URL that isn't pointing at our instance.": "Yritetään lyhentää URL-osoite, joka ei osoita meidän instanssiiin.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Virhe kutsuttaessa YOURLS. Luultavasti asetusongelma kuten väärä tai puuttuuva \"apiurl\" tai \"signature\".", - "Error parsing YOURLS response.": "Virhe jäsennettäessä YOURLS-vastausta." + "Error parsing YOURLS response.": "Virhe jäsennettäessä YOURLS-vastausta.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/fr.json b/i18n/fr.json index ad9012db..d90f8578 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Votre adresse IP n'est pas autorisée à créer des pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/he.json b/i18n/he.json index 93509e63..658e586b 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/hi.json b/i18n/hi.json index 68ff1aae..6ef3280b 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/hu.json b/i18n/hu.json index 9384be7e..d9161090 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/id.json b/i18n/id.json index 85439d03..a0e844e8 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/it.json b/i18n/it.json index f12ed03b..c23b1655 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Il tuo IP non è autorizzato a creare dei messaggi.", "Trying to shorten a URL that isn't pointing at our instance.": "Tantativo in corso di accorciare un URL che non punta alla nostra istanza.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Errore nella chiamata a YOURLS. Probabilmente un problema di configurazione, come un \"apiurl\" o una \"signature\" sbagliati o mancanti.", - "Error parsing YOURLS response.": "Errore nell'analizzare la risposta YOURLS." + "Error parsing YOURLS response.": "Errore nell'analizzare la risposta YOURLS.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ja.json b/i18n/ja.json index f06f37be..07323772 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "あなたのIPアドレスにはペーストを作成する権限がありません。", "Trying to shorten a URL that isn't pointing at our instance.": "このインスタンスを指していないURLを短縮しようとしています。", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "YOURLSの呼び出し中にエラーが発生しました。\"apiurl\"または\"signature\"等の設定に問題がある可能性があります。", - "Error parsing YOURLS response.": "YOURLSレスポンスの解析中にエラーが発生しました。" + "Error parsing YOURLS response.": "YOURLSレスポンスの解析中にエラーが発生しました。", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/jbo.json b/i18n/jbo.json index a8105510..f729f613 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ku.json b/i18n/ku.json index 68ff1aae..6ef3280b 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/la.json b/i18n/la.json index 8ee0d6db..895f0b02 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/lt.json b/i18n/lt.json index 25364269..81dfe123 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų.", "Trying to shorten a URL that isn't pointing at our instance.": "Bandoma sutrumpinti URL adresą, kuris nenurodo į mūsų egzempliorių.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Klaida iškviečiant YOURLS. Tikriausiai, konfigūracijos klaida, pavyzdžiui, neteisingi „apiurl“ ar „signature“, arba jų nėra.", - "Error parsing YOURLS response.": "Klaida nagrinėjant YOURLS atsaką." + "Error parsing YOURLS response.": "Klaida nagrinėjant YOURLS atsaką.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/nl.json b/i18n/nl.json index d7a26664..fc058a20 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Je IP-adres is niet gemachtigd om pastes te maken.", "Trying to shorten a URL that isn't pointing at our instance.": "Proberen om een URL te verkorten dat niet naar ons systeem wijst.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Foutmelding ophalen YOURLS. Waarschijnlijk een configuratiefout, zoals een verkeerde of missende \"apiurl\" of \"signature\".", - "Error parsing YOURLS response.": "Foutmelding bij parsen van YOURLS respons." + "Error parsing YOURLS response.": "Foutmelding bij parsen van YOURLS respons.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/no.json b/i18n/no.json index fbbd5dc5..00417f24 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/oc.json b/i18n/oc.json index 4c5c40f2..7553fb0e 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Vòstra adreça IP a pas l’autorizacion de crear de tèxtes.", "Trying to shorten a URL that isn't pointing at our instance.": "Ensag d’abracar una URL que mena pas a nòstra instància.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error en cridant YOURLS. Es probablament un problèma de configuracion, quicòm coma « apirul » o « signature » marrit o absent.", - "Error parsing YOURLS response.": "Error d'analisi de la responsa YOURLS." + "Error parsing YOURLS response.": "Error d'analisi de la responsa YOURLS.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/pl.json b/i18n/pl.json index 6bd76b99..ec1930dd 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/pt.json b/i18n/pt.json index 4adb56c4..3b7866db 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Seu IP não está autorizado a criar cópias.", "Trying to shorten a URL that isn't pointing at our instance.": "Tentando encurtar uma URL que não aponta para a nossa instância.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ru.json b/i18n/ru.json index 54f8239f..00084dc8 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Вашему IP адресу не разрешено создавать записи.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/sk.json b/i18n/sk.json index bab0ab36..c73fe638 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky.", "Trying to shorten a URL that isn't pointing at our instance.": "Pokúšate sa skrátiť adresu URL, ktorá neukazuje na túto inštanciu.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/sl.json b/i18n/sl.json index 1a93bed5..f3baab91 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/sv.json b/i18n/sv.json index 68ff1aae..6ef3280b 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/th.json b/i18n/th.json index 48237005..4325ab1d 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "IP ของคุณไม่ได้รับอนุญาตให้สร้างการฝากโค้ด", "Trying to shorten a URL that isn't pointing at our instance.": "กำลังพยายามใช้เครื่องมือสร้างลิงก์ย่อ ที่ไม่ได้ชี้ไปที่อินสแตนซ์ของเรา", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "เกิดข้อผิดพลาดในการเรียก YOURLS อาจเป็นปัญหามาจากการกำหนดค่า เช่น \"apiurl\" หรือ \"signature\" ไม่ถูกต้องหรือขาดหายไป", - "Error parsing YOURLS response.": "เกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองของ YOURLS" + "Error parsing YOURLS response.": "เกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองของ YOURLS", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/tr.json b/i18n/tr.json index 4dc8c4a4..5164aee6 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/uk.json b/i18n/uk.json index ad80289f..0d514b5a 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Вашому IP не дозволено створювати вставки.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Error parsing YOURLS response.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/zh.json b/i18n/zh.json index 61b32cbd..421622f5 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "您的 IP 无权创建粘贴。", "Trying to shorten a URL that isn't pointing at our instance.": "尝试缩短一个不指向我们实例的URL。", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "调用 YOURLS 时出错。可能是配置问题,例如“apiurl”或“signature”错误或缺失。", - "Error parsing YOURLS response.": "解析 YOURLS 响应时出错。" + "Error parsing YOURLS response.": "解析 YOURLS 响应时出错。", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/js/privatebin.js b/js/privatebin.js index 23a4fe20..83865562 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -77,6 +77,13 @@ jQuery.PrivateBin = (function($, RawDeflate) { } }; + /** + * URL fragment prefix requiring load confirmation + * + * @private + */ + const loadConfirmPrefix = '#?'; + /** * CryptoData class * @@ -1512,15 +1519,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.getPasteKey = function() { if (symmetricKey === null) { - let pos = 1; - const pt = '#protected/'; - if(window.location.hash.startsWith(pt)) { - pos = pt.length; - } - let newKey = window.location.hash.substring(pos); - if (newKey === '') { - throw 'no encryption key given'; + let startPos = 1; + if(window.location.hash.startsWith(loadConfirmPrefix)) { + startPos = loadConfirmPrefix.length; } + let newKey = window.location.hash.substring(startPos); // Some web 2.0 services and redirectors add data AFTER the anchor // (such as &utm_source=...). We will strip any additional data. @@ -1529,6 +1532,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { { newKey = newKey.substring(0, ampersandPos); } + if (newKey === '') { + throw 'no encryption key given'; + } // version 2 uses base58, version 1 uses base64 without decoding try { @@ -2242,7 +2248,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @function * @param {Event} event */ - async function submitPasswordModal(event) + function submitPasswordModal(event) { event.preventDefault(); @@ -2252,37 +2258,37 @@ jQuery.PrivateBin = (function($, RawDeflate) { // hide modal $passwordModal.modal('hide'); - // check if protected pathname - const url = new URL(window.location); - - // if protected request password - if(url.hash.startsWith('#protected/')) { - const pt = '#protected/'; - let pos = pt.length; - let newKey = window.location.hash.substring(pos); - if (newKey === '') { - throw 'no encryption key given'; - } - - // Some web 2.0 services and redirectors add data AFTER the anchor - // (such as &utm_source=...). We will strip any additional data. - let ampersandPos = newKey.indexOf('&'); - if (ampersandPos > -1) - { - newKey = newKey.substring(0, ampersandPos); - } - const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); - const dt = JSON.parse(enc); - const cipherdata = [dt.ct, dt.adata] - - const plaindata = await CryptTool.decipher(dt.k, password, cipherdata); - window.location.replace(Helper.baseUri() + plaindata); - return; - } - PasteDecrypter.run(); } + /** + * Request users confirmation to load possibly burn after reading paste + * + * @name Prompt.requestLoadConfirmation + * @function + */ + me.requestLoadConfirmation = function() + { + const $loadconfirmmodal = $('#loadconfirmmodal'); + if ($loadconfirmmodal.length > 0) { + const $loadconfirmOpenNow = $loadconfirmmodal.find('#loadconfirm-open-now'); + $loadconfirmOpenNow.off('click.loadPaste'); + $loadconfirmOpenNow.on('click.loadPaste', PasteDecrypter.run); + const $loadconfirmClose = $loadconfirmmodal.find('.close'); + $loadconfirmClose.off('click.close'); + $loadconfirmClose.on('click.close', Controller.newPaste); + $loadconfirmmodal.modal('show'); + } else { + if (window.confirm( + I18n._('Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?') + )) { + PasteDecrypter.run(); + } else { + Controller.newPaste(); + } + } + } + /** * ask the user for the password and set it * @@ -2297,6 +2303,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { backdrop: 'static', keyboard: false }); + $passwordDecrypt.focus(); return; } @@ -3844,6 +3851,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { { document.cookie = 'lang=' + $(event.target).data('lang') + ';secure'; UiHelper.reloadHome(); + event.preventDefault(); } /** @@ -3999,10 +4007,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { const $emailconfirmmodal = $('#emailconfirmmodal'); if ($emailconfirmmodal.length > 0) { if (expirationDate !== null) { - I18n._( - $emailconfirmmodal.find('#emailconfirm-display'), - 'Recipient may become aware of your timezone, convert time to UTC?' - ); const $emailconfirmTimezoneCurrent = $emailconfirmmodal.find('#emailconfirm-timezone-current'); const $emailconfirmTimezoneUtc = $emailconfirmmodal.find('#emailconfirm-timezone-utc'); $emailconfirmTimezoneCurrent.off('click.sendEmailCurrentTimezone'); @@ -4851,44 +4855,16 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @param {int} status * @param {object} data */ - async function showCreatedPaste(status, data) { + function showCreatedPaste(status, data) { Alert.hideLoading(); Alert.hideMessages(); // show notification - const baseUri = Helper.baseUri(), - deleteUrl = baseUri + '?pasteid=' + data.id + '&deletetoken=' + data.deletetoken; - let url; - - const pw = TopNav.getPassword() - - // only execute when it is a single time view - if(pw && pw.length && TopNav.getBurnAfterReading()) { - - const sm = CryptTool.getSymmetricKey(); - - let openUri = '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); - let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); - - let dt = {} - dt['v'] = 2; - dt['ct'] = cipherResult[0]; - dt['adata'] = cipherResult[1]; - dt['k'] = sm; - - const encUrl = CryptTool.base58encode(JSON.stringify(dt)) - - url = baseUri + '#protected/' + encUrl; - } else { - url = baseUri + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); - } - + const baseUri = Helper.baseUri() + '?', + url = baseUri + data.id + (TopNav.getBurnAfterReading() ? loadConfirmPrefix : '#') + CryptTool.base58encode(data.encryptionKey), + deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; PasteStatus.createPasteNotification(url, deleteUrl); - - - - // show new URL in browser bar history.pushState({type: 'newpaste'}, document.title, url); @@ -5033,12 +5009,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // prepare server interaction ServerInteraction.prepare(); - if(!TopNav.getBurnAfterReading()) { - ServerInteraction.setCryptParameters(TopNav.getPassword()); - } else { - // not needed in this scenario - ServerInteraction.setCryptParameters(''); - } + ServerInteraction.setCryptParameters(TopNav.getPassword()); // set success/fail functions ServerInteraction.setSuccess(showCreatedPaste); @@ -5309,7 +5280,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { Alert.hideMessages(); Alert.showLoading('Decrypting paste…', 'cloud-download'); - if (typeof paste === 'undefined') { + if (typeof paste === 'undefined' || paste.type === 'click') { // get cipher data and wait until it is available Model.getPasteData(me.run); return; @@ -5416,7 +5387,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { AttachmentViewer.removeAttachmentData(); Alert.hideLoading(); - history.pushState({type: 'create'}, document.title, Helper.baseUri()); + // only push new state if we are coming from a different one + if (Helper.baseUri() != window.location) { + history.pushState({type: 'create'}, document.title, Helper.baseUri()); + } // clear discussion DiscussionViewer.prepareNewDiscussion(); @@ -5442,6 +5416,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { } } + // check if we should request loading confirmation + if(window.location.hash.startsWith(loadConfirmPrefix)) { + Prompt.requestLoadConfirmation(); + return; + } + // show proper elements on screen PasteDecrypter.run(); }; @@ -5624,16 +5604,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { try { Model.getPasteId(); } catch (e) { - - // check if protected pathname - const url = new URL(window.location); - - // if protected request password - if(url.hash.startsWith('#protected/')) { - return Prompt.requestPassword(); - - } - // otherwise create a new paste return me.newPaste(); } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index d1a54fcb..70b1b0cf 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + @@ -123,22 +123,32 @@ if (count($class)) { + -