diff --git a/.github/workflows/snyk-scan.yml b/.github/workflows/snyk-scan.yml index 9c5cb4fa..af6359a8 100644 --- a/.github/workflows/snyk-scan.yml +++ b/.github/workflows/snyk-scan.yml @@ -25,8 +25,6 @@ jobs: github.event.pull_request.author_association == 'OWNER' ) steps: - uses: actions/checkout@v6 - - name: Install Google Cloud Storage - run: composer require --no-update google/cloud-storage && composer update --no-dev - name: Run Snyk to check for vulnerabilities uses: snyk/actions/php@master continue-on-error: true # To make sure that SARIF upload gets called diff --git a/.github/workflows/test-results.yml b/.github/workflows/test-results.yml index 56dc11a5..f74251bb 100644 --- a/.github/workflows/test-results.yml +++ b/.github/workflows/test-results.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Download and Extract Artifacts - uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 + uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 with: run_id: ${{ github.event.workflow_run.id }} path: artifacts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f32c5ca..0fdc1d04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ * ADDED: Translations for Swedish & Persian * CHANGED: Deduplicate JSON error message translations * CHANGED: Refactored translation of exception messages -* CHANGED: Upgrading libraries to: DOMpurify 3.3.2, ip-lib 1.22.0 & polyfill-php80 1.34.0 +* CHANGED: Upgrading libraries to: DOMpurify 3.4.1, ip-lib 1.22.0, polyfill-php80 1.34.0 & zlib 1.3.2 * CHANGED: Remove obsolete X-XSS-Protection header (#1825) * FIXED: Some exceptions not getting translated * FIXED: Attachment disappears after a "paste" in the message area (#1731) diff --git a/composer.json b/composer.json index 36ce0c4e..e376696c 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,7 @@ }, "config" : { "audit": { + "block-insecure": false, "ignore": { "CVE-2025-45769": "disputed on the basis that key lengths are expected to be set by an application, not by this library" } diff --git a/composer.lock b/composer.lock index b6197f7d..9f33c691 100644 --- a/composer.lock +++ b/composer.lock @@ -215,7 +215,7 @@ "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/yzalis/Identicon.git", + "url": "https://github.com/yzalis/Identicon", "reference": "ff5ed090129cab9bfa2a322857d4a01d107aa0ae" }, "dist": { @@ -260,11 +260,6 @@ "identicon", "image" ], - "support": { - "issues": "https://github.com/yzalis/Identicon/issues", - "source": "https://github.com/yzalis/Identicon/tree/master" - }, - "abandoned": true, "time": "2019-10-14T09:30:57+00:00" } ], @@ -896,16 +891,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.33", + "version": "9.6.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fea06253ecc0a32faf787bd31b261f56f351d049" + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fea06253ecc0a32faf787bd31b261f56f351d049", - "reference": "fea06253ecc0a32faf787bd31b261f56f351d049", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", "shasum": "" }, "require": { @@ -979,7 +974,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.33" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" }, "funding": [ { @@ -1003,7 +998,7 @@ "type": "tidelift" } ], - "time": "2026-01-27T05:25:09+00:00" + "time": "2026-01-27T05:45:00+00:00" }, { "name": "sebastian/cli-parser", @@ -2069,15 +2064,15 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^7.4 || ^8.0" }, - "platform-dev": {}, + "platform-dev": [], "platform-overrides": { "php": "7.4" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.3.0" } diff --git a/js/common.js b/js/common.js index 36b5cdaa..8cd0992d 100644 --- a/js/common.js +++ b/js/common.js @@ -10,12 +10,12 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test global.$ = global.jQuery = require('./jquery-3.7.1'); -global.zlib = require('./zlib-1.3.1-2').zlib; +global.zlib = require('./zlib').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.3.2'); +global.DOMPurify = require('./purify-3.4.1'); global.baseX = require('./base-x-5.0.1').baseX; global.Legacy = require('./legacy').Legacy; require('./privatebin'); diff --git a/js/eslint.config.js b/js/eslint.config.js index 786d49e0..32ed4033 100644 --- a/js/eslint.config.js +++ b/js/eslint.config.js @@ -1,7 +1,7 @@ const globals = require('globals'); const { globalIgnores } = require('eslint/config') -module.exports = [globalIgnores(["./*.js", "!./privatebin.js"]), { +module.exports = [globalIgnores(["./*.*js", "!./privatebin.js"]), { languageOptions: { globals: { ...globals.amd, diff --git a/js/purify-3.3.2.js b/js/purify-3.3.2.js deleted file mode 100644 index 3ae5c6c0..00000000 --- a/js/purify-3.3.2.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! @license DOMPurify 3.3.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.2/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){for(var n=arguments.length,o=new Array(n>2?n-2:0),r=2;r1?t-1:0),o=1;o1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:h;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 w(e){for(let t=0;t/gm),W=a(/\$\{[\w\W]*/gm),Y=a(/^data-[\-\w.\u00B7-\uFFFF]+$/),j=a(/^aria-[\-\w]+$/),X=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),q=a(/^(?:\w+script|data):/i),$=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),K=a(/^html$/i),V=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var Z=Object.freeze({__proto__:null,ARIA_ATTR:j,ATTR_WHITESPACE:$,CUSTOM_ELEMENT:V,DATA_ATTR:Y,DOCTYPE_NAME:K,ERB_EXPR:G,IS_ALLOWED_URI:X,IS_SCRIPT_OR_DATA:q,MUSTACHE_EXPR:B,TMPLIT_EXPR:W});const J=1,Q=3,ee=7,te=8,ne=9,oe=function(){return"undefined"==typeof window?null:window};var re=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:oe();const o=e=>t(e);if(o.version="3.3.2",o.removed=[],!n||!n.document||n.document.nodeType!==ne||!n.Element)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:N,Node:D,Element:w,NodeFilter:B,NamedNodeMap:G=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:W,DOMParser:Y,trustedTypes:j}=n,q=w.prototype,$=O(q,"cloneNode"),V=O(q,"remove"),re=O(q,"nextSibling"),ie=O(q,"childNodes"),ae=O(q,"parentNode");if("function"==typeof N){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let le,ce="";const{implementation:se,createNodeIterator:ue,createDocumentFragment:me,getElementsByTagName:pe}=r,{importNode:fe}=a;let de={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};o.isSupported="function"==typeof e&&"function"==typeof ae&&se&&void 0!==se.createHTMLDocument;const{MUSTACHE_EXPR:he,ERB_EXPR:ge,TMPLIT_EXPR:Te,DATA_ATTR:ye,ARIA_ATTR:Ee,IS_SCRIPT_OR_DATA:Ae,ATTR_WHITESPACE:_e,CUSTOM_ELEMENT:be}=Z;let{IS_ALLOWED_URI:Se}=Z,Ne=null;const De=R({},[...v,...k,...x,...I,...U]);let Re=null;const we=R({},[...z,...P,...F,...H]);let Ce=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}})),Oe=null,ve=null;const ke=Object.seal(l(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let xe=!0,Le=!0,Ie=!1,Me=!0,Ue=!1,ze=!0,Pe=!1,Fe=!1,He=!1,Be=!1,Ge=!1,We=!1,Ye=!0,je=!1,Xe=!0,qe=!1,$e={},Ke=null;const Ve=R({},["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 Ze=null;const Je=R({},["audio","video","img","source","image","track"]);let Qe=null;const et=R({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),tt="http://www.w3.org/1998/Math/MathML",nt="http://www.w3.org/2000/svg",ot="http://www.w3.org/1999/xhtml";let rt=ot,it=!1,at=null;const lt=R({},[tt,nt,ot],g);let ct=R({},["mi","mo","mn","ms","mtext"]),st=R({},["annotation-xml"]);const ut=R({},["title","style","font","a","script"]);let mt=null;const pt=["application/xhtml+xml","text/html"];let ft=null,dt=null;const ht=r.createElement("form"),gt=function(e){return e instanceof RegExp||e instanceof Function},Tt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!dt||dt!==e){if(e&&"object"==typeof e||(e={}),e=C(e),mt=-1===pt.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,ft="application/xhtml+xml"===mt?g:h,Ne=_(e,"ALLOWED_TAGS")?R({},e.ALLOWED_TAGS,ft):De,Re=_(e,"ALLOWED_ATTR")?R({},e.ALLOWED_ATTR,ft):we,at=_(e,"ALLOWED_NAMESPACES")?R({},e.ALLOWED_NAMESPACES,g):lt,Qe=_(e,"ADD_URI_SAFE_ATTR")?R(C(et),e.ADD_URI_SAFE_ATTR,ft):et,Ze=_(e,"ADD_DATA_URI_TAGS")?R(C(Je),e.ADD_DATA_URI_TAGS,ft):Je,Ke=_(e,"FORBID_CONTENTS")?R({},e.FORBID_CONTENTS,ft):Ve,Oe=_(e,"FORBID_TAGS")?R({},e.FORBID_TAGS,ft):C({}),ve=_(e,"FORBID_ATTR")?R({},e.FORBID_ATTR,ft):C({}),$e=!!_(e,"USE_PROFILES")&&e.USE_PROFILES,xe=!1!==e.ALLOW_ARIA_ATTR,Le=!1!==e.ALLOW_DATA_ATTR,Ie=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Me=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,Ue=e.SAFE_FOR_TEMPLATES||!1,ze=!1!==e.SAFE_FOR_XML,Pe=e.WHOLE_DOCUMENT||!1,Be=e.RETURN_DOM||!1,Ge=e.RETURN_DOM_FRAGMENT||!1,We=e.RETURN_TRUSTED_TYPE||!1,He=e.FORCE_BODY||!1,Ye=!1!==e.SANITIZE_DOM,je=e.SANITIZE_NAMED_PROPS||!1,Xe=!1!==e.KEEP_CONTENT,qe=e.IN_PLACE||!1,Se=e.ALLOWED_URI_REGEXP||X,rt=e.NAMESPACE||ot,ct=e.MATHML_TEXT_INTEGRATION_POINTS||ct,st=e.HTML_INTEGRATION_POINTS||st,Ce=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&>(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ce.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&>(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ce.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ce.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Ue&&(Le=!1),Ge&&(Be=!0),$e&&(Ne=R({},U),Re=l(null),!0===$e.html&&(R(Ne,v),R(Re,z)),!0===$e.svg&&(R(Ne,k),R(Re,P),R(Re,H)),!0===$e.svgFilters&&(R(Ne,x),R(Re,P),R(Re,H)),!0===$e.mathMl&&(R(Ne,I),R(Re,F),R(Re,H))),_(e,"ADD_TAGS")||(ke.tagCheck=null),_(e,"ADD_ATTR")||(ke.attributeCheck=null),e.ADD_TAGS&&("function"==typeof e.ADD_TAGS?ke.tagCheck=e.ADD_TAGS:(Ne===De&&(Ne=C(Ne)),R(Ne,e.ADD_TAGS,ft))),e.ADD_ATTR&&("function"==typeof e.ADD_ATTR?ke.attributeCheck=e.ADD_ATTR:(Re===we&&(Re=C(Re)),R(Re,e.ADD_ATTR,ft))),e.ADD_URI_SAFE_ATTR&&R(Qe,e.ADD_URI_SAFE_ATTR,ft),e.FORBID_CONTENTS&&(Ke===Ve&&(Ke=C(Ke)),R(Ke,e.FORBID_CONTENTS,ft)),e.ADD_FORBID_CONTENTS&&(Ke===Ve&&(Ke=C(Ke)),R(Ke,e.ADD_FORBID_CONTENTS,ft)),Xe&&(Ne["#text"]=!0),Pe&&R(Ne,["html","head","body"]),Ne.table&&(R(Ne,["tbody"]),delete Oe.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw S('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw S('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');le=e.TRUSTED_TYPES_POLICY,ce=le.createHTML("")}else void 0===le&&(le=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}}(j,c)),null!==le&&"string"==typeof ce&&(ce=le.createHTML(""));i&&i(e),dt=e}},yt=R({},[...k,...x,...L]),Et=R({},[...I,...M]),At=function(e){f(o.removed,{element:e});try{ae(e).removeChild(e)}catch(t){V(e)}},_t=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)if(Be||Ge)try{At(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},bt=function(e){let t=null,n=null;if(He)e=""+e;else{const t=T(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===mt&&rt===ot&&(e=''+e+"");const o=le?le.createHTML(e):e;if(rt===ot)try{t=(new Y).parseFromString(o,mt)}catch(e){}if(!t||!t.documentElement){t=se.createDocument(rt,"template",null);try{t.documentElement.innerHTML=it?ce:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),rt===ot?pe.call(t,Pe?"html":"body")[0]:Pe?t.documentElement:i},St=function(e){return ue.call(e.ownerDocument||e,e,B.SHOW_ELEMENT|B.SHOW_COMMENT|B.SHOW_TEXT|B.SHOW_PROCESSING_INSTRUCTION|B.SHOW_CDATA_SECTION,null)},Nt=function(e){return e instanceof W&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof G)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Dt=function(e){return"function"==typeof D&&e instanceof D};function Rt(e,t,n){u(e,(e=>{e.call(o,t,n,dt)}))}const wt=function(e){let t=null;if(Rt(de.beforeSanitizeElements,e,null),Nt(e))return At(e),!0;const n=ft(e.nodeName);if(Rt(de.uponSanitizeElement,e,{tagName:n,allowedTags:Ne}),ze&&e.hasChildNodes()&&!Dt(e.firstElementChild)&&b(/<[/\w!]/g,e.innerHTML)&&b(/<[/\w!]/g,e.textContent))return At(e),!0;if(e.nodeType===ee)return At(e),!0;if(ze&&e.nodeType===te&&b(/<[/\w]/g,e.data))return At(e),!0;if(!(ke.tagCheck instanceof Function&&ke.tagCheck(n))&&(!Ne[n]||Oe[n])){if(!Oe[n]&&Ot(n)){if(Ce.tagNameCheck instanceof RegExp&&b(Ce.tagNameCheck,n))return!1;if(Ce.tagNameCheck instanceof Function&&Ce.tagNameCheck(n))return!1}if(Xe&&!Ke[n]){const t=ae(e)||e.parentNode,n=ie(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=$(n[o],!0);r.__removalCount=(e.__removalCount||0)+1,t.insertBefore(r,re(e))}}}return At(e),!0}return e instanceof w&&!function(e){let t=ae(e);t&&t.tagName||(t={namespaceURI:rt,tagName:"template"});const n=h(e.tagName),o=h(t.tagName);return!!at[e.namespaceURI]&&(e.namespaceURI===nt?t.namespaceURI===ot?"svg"===n:t.namespaceURI===tt?"svg"===n&&("annotation-xml"===o||ct[o]):Boolean(yt[n]):e.namespaceURI===tt?t.namespaceURI===ot?"math"===n:t.namespaceURI===nt?"math"===n&&st[o]:Boolean(Et[n]):e.namespaceURI===ot?!(t.namespaceURI===nt&&!st[o])&&!(t.namespaceURI===tt&&!ct[o])&&!Et[n]&&(ut[n]||!yt[n]):!("application/xhtml+xml"!==mt||!at[e.namespaceURI]))}(e)?(At(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!b(/<\/no(script|embed|frames)/i,e.innerHTML)?(Ue&&e.nodeType===Q&&(t=e.textContent,u([he,ge,Te],(e=>{t=y(t,e," ")})),e.textContent!==t&&(f(o.removed,{element:e.cloneNode()}),e.textContent=t)),Rt(de.afterSanitizeElements,e,null),!1):(At(e),!0)},Ct=function(e,t,n){if(ve[t])return!1;if(Ye&&("id"===t||"name"===t)&&(n in r||n in ht))return!1;if(Le&&!ve[t]&&b(ye,t));else if(xe&&b(Ee,t));else if(ke.attributeCheck instanceof Function&&ke.attributeCheck(t,e));else if(!Re[t]||ve[t]){if(!(Ot(e)&&(Ce.tagNameCheck instanceof RegExp&&b(Ce.tagNameCheck,e)||Ce.tagNameCheck instanceof Function&&Ce.tagNameCheck(e))&&(Ce.attributeNameCheck instanceof RegExp&&b(Ce.attributeNameCheck,t)||Ce.attributeNameCheck instanceof Function&&Ce.attributeNameCheck(t,e))||"is"===t&&Ce.allowCustomizedBuiltInElements&&(Ce.tagNameCheck instanceof RegExp&&b(Ce.tagNameCheck,n)||Ce.tagNameCheck instanceof Function&&Ce.tagNameCheck(n))))return!1}else if(Qe[t]);else if(b(Se,y(n,_e,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==E(n,"data:")||!Ze[e]){if(Ie&&!b(Ae,y(n,_e,"")));else if(n)return!1}else;return!0},Ot=function(e){return"annotation-xml"!==e&&T(e,be)},vt=function(e){Rt(de.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t||Nt(e))return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Re,forceKeepAttr:void 0};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=ft(a),m=c;let f="value"===a?m:A(m);if(n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,Rt(de.uponSanitizeAttribute,e,n),f=n.attrValue,!je||"id"!==s&&"name"!==s||(_t(a,e),f="user-content-"+f),ze&&b(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,f)){_t(a,e);continue}if("attributename"===s&&T(f,"href")){_t(a,e);continue}if(n.forceKeepAttr)continue;if(!n.keepAttr){_t(a,e);continue}if(!Me&&b(/\/>/i,f)){_t(a,e);continue}Ue&&u([he,ge,Te],(e=>{f=y(f,e," ")}));const d=ft(e.nodeName);if(Ct(d,s,f)){if(le&&"object"==typeof j&&"function"==typeof j.getAttributeType)if(l);else switch(j.getAttributeType(d,s)){case"TrustedHTML":f=le.createHTML(f);break;case"TrustedScriptURL":f=le.createScriptURL(f)}if(f!==m)try{l?e.setAttributeNS(l,a,f):e.setAttribute(a,f),Nt(e)?At(e):p(o.removed)}catch(t){_t(a,e)}}else _t(a,e)}Rt(de.afterSanitizeAttributes,e,null)},kt=function e(t){let n=null;const o=St(t);for(Rt(de.beforeSanitizeShadowDOM,t,null);n=o.nextNode();)Rt(de.uponSanitizeShadowNode,n,null),wt(n),vt(n),n.content instanceof s&&e(n.content);Rt(de.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(it=!e,it&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Dt(e)){if("function"!=typeof e.toString)throw S("toString is not a function");if("string"!=typeof(e=e.toString()))throw S("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Fe||Tt(t),o.removed=[],"string"==typeof e&&(qe=!1),qe){if(e.nodeName){const t=ft(e.nodeName);if(!Ne[t]||Oe[t])throw S("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof D)n=bt("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===J&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!Be&&!Ue&&!Pe&&-1===e.indexOf("<"))return le&&We?le.createHTML(e):e;if(n=bt(e),!n)return Be?null:We?ce:""}n&&He&&At(n.firstChild);const c=St(qe?e:n);for(;i=c.nextNode();)wt(i),vt(i),i.content instanceof s&&kt(i.content);if(qe)return e;if(Be){if(Ge)for(l=me.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Re.shadowroot||Re.shadowrootmode)&&(l=fe.call(a,l,!0)),l}let m=Pe?n.outerHTML:n.innerHTML;return Pe&&Ne["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&b(K,n.ownerDocument.doctype.name)&&(m="\n"+m),Ue&&u([he,ge,Te],(e=>{m=y(m,e," ")})),le&&We?le.createHTML(m):m},o.setConfig=function(){Tt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Fe=!0},o.clearConfig=function(){dt=null,Fe=!1},o.isValidAttribute=function(e,t,n){dt||Tt({});const o=ft(e),r=ft(t);return Ct(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&f(de[e],t)},o.removeHook=function(e,t){if(void 0!==t){const n=m(de[e],t);return-1===n?void 0:d(de[e],n,1)[0]}return p(de[e])},o.removeHooks=function(e){de[e]=[]},o.removeAllHooks=function(){de={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},o}();return re})); diff --git a/js/purify-3.4.1.js b/js/purify-3.4.1.js new file mode 100644 index 00000000..45bdb2da --- /dev/null +++ b/js/purify-3.4.1.js @@ -0,0 +1,3 @@ +/*! @license DOMPurify 3.4.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.1/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){for(var n=arguments.length,o=new Array(n>2?n-2:0),r=2;r1?t-1:0),o=1;o1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:T;if(t&&t(e,null),!h(o))return e;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 x(e){for(let t=0;t/gm),K=a(/\$\{[\w\W]*/gm),V=a(/^data-[\-\w.\u00B7-\uFFFF]+$/),Z=a(/^aria-[\-\w]+$/),J=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Q=a(/^(?:\w+script|data):/i),ee=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),te=a(/^html$/i),ne=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var oe=Object.freeze({__proto__:null,ARIA_ATTR:Z,ATTR_WHITESPACE:ee,CUSTOM_ELEMENT:ne,DATA_ATTR:V,DOCTYPE_NAME:te,ERB_EXPR:$,IS_ALLOWED_URI:J,IS_SCRIPT_OR_DATA:Q,MUSTACHE_EXPR:q,TMPLIT_EXPR:K});const re=1,ie=3,ae=7,le=8,ce=9,se=function(){return"undefined"==typeof window?null:window};var ue=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:se();const o=e=>t(e);if(o.version="3.4.1",o.removed=[],!n||!n.document||n.document.nodeType!==ce||!n.Element)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:C,Node:L,Element:x,NodeFilter:q,NamedNodeMap:$=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:K,DOMParser:V,trustedTypes:Z}=n,Q=x.prototype,ee=M(Q,"cloneNode"),ne=M(Q,"remove"),ue=M(Q,"nextSibling"),me=M(Q,"childNodes"),fe=M(Q,"parentNode");if("function"==typeof C){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let pe,de="";const{implementation:he,createNodeIterator:Te,createDocumentFragment:ge,getElementsByTagName:ye}=r,{importNode:Ae}=a;let Ee={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};o.isSupported="function"==typeof e&&"function"==typeof fe&&he&&void 0!==he.createHTMLDocument;const{MUSTACHE_EXPR:_e,ERB_EXPR:Se,TMPLIT_EXPR:be,DATA_ATTR:Ne,ARIA_ATTR:Re,IS_SCRIPT_OR_DATA:De,ATTR_WHITESPACE:Oe,CUSTOM_ELEMENT:Ie}=oe;let{IS_ALLOWED_URI:we}=oe,Ce=null;const Le=k({},[...P,...U,...z,...H,...G]);let ke=null;const xe=k({},[...W,...j,...Y,...X]);let ve=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}})),Me=null,Pe=null;const Ue=Object.seal(l(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let ze=!0,Fe=!0,He=!1,Be=!0,Ge=!1,We=!0,je=!1,Ye=!1,Xe=!1,qe=!1,$e=!1,Ke=!1,Ve=!0,Ze=!1;const Je="user-content-";let Qe=!0,et=!1,tt={},nt=null;const ot=k({},["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 rt=null;const it=k({},["audio","video","img","source","image","track"]);let at=null;const lt=k({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),ct="http://www.w3.org/1998/Math/MathML",st="http://www.w3.org/2000/svg",ut="http://www.w3.org/1999/xhtml";let mt=ut,ft=!1,pt=null;const dt=k({},[ct,st,ut],g);let ht=k({},["mi","mo","mn","ms","mtext"]),Tt=k({},["annotation-xml"]);const gt=k({},["title","style","font","a","script"]);let yt=null;const At=["application/xhtml+xml","text/html"];let Et=null,_t=null;const St=r.createElement("form"),bt=function(e){return e instanceof RegExp||e instanceof Function},Nt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(_t&&_t===e)return;e&&"object"==typeof e||(e={}),e=v(e),yt=-1===At.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,Et="application/xhtml+xml"===yt?g:T,Ce=D(e,"ALLOWED_TAGS")&&h(e.ALLOWED_TAGS)?k({},e.ALLOWED_TAGS,Et):Le,ke=D(e,"ALLOWED_ATTR")&&h(e.ALLOWED_ATTR)?k({},e.ALLOWED_ATTR,Et):xe,pt=D(e,"ALLOWED_NAMESPACES")&&h(e.ALLOWED_NAMESPACES)?k({},e.ALLOWED_NAMESPACES,g):dt,at=D(e,"ADD_URI_SAFE_ATTR")&&h(e.ADD_URI_SAFE_ATTR)?k(v(lt),e.ADD_URI_SAFE_ATTR,Et):lt,rt=D(e,"ADD_DATA_URI_TAGS")&&h(e.ADD_DATA_URI_TAGS)?k(v(it),e.ADD_DATA_URI_TAGS,Et):it,nt=D(e,"FORBID_CONTENTS")&&h(e.FORBID_CONTENTS)?k({},e.FORBID_CONTENTS,Et):ot,Me=D(e,"FORBID_TAGS")&&h(e.FORBID_TAGS)?k({},e.FORBID_TAGS,Et):v({}),Pe=D(e,"FORBID_ATTR")&&h(e.FORBID_ATTR)?k({},e.FORBID_ATTR,Et):v({}),tt=!!D(e,"USE_PROFILES")&&(e.USE_PROFILES&&"object"==typeof e.USE_PROFILES?v(e.USE_PROFILES):e.USE_PROFILES),ze=!1!==e.ALLOW_ARIA_ATTR,Fe=!1!==e.ALLOW_DATA_ATTR,He=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Be=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,Ge=e.SAFE_FOR_TEMPLATES||!1,We=!1!==e.SAFE_FOR_XML,je=e.WHOLE_DOCUMENT||!1,qe=e.RETURN_DOM||!1,$e=e.RETURN_DOM_FRAGMENT||!1,Ke=e.RETURN_TRUSTED_TYPE||!1,Xe=e.FORCE_BODY||!1,Ve=!1!==e.SANITIZE_DOM,Ze=e.SANITIZE_NAMED_PROPS||!1,Qe=!1!==e.KEEP_CONTENT,et=e.IN_PLACE||!1,we=function(e){try{return I(e,""),!0}catch(e){return!1}}(e.ALLOWED_URI_REGEXP)?e.ALLOWED_URI_REGEXP:J,mt="string"==typeof e.NAMESPACE?e.NAMESPACE:ut,ht=D(e,"MATHML_TEXT_INTEGRATION_POINTS")&&e.MATHML_TEXT_INTEGRATION_POINTS&&"object"==typeof e.MATHML_TEXT_INTEGRATION_POINTS?v(e.MATHML_TEXT_INTEGRATION_POINTS):k({},["mi","mo","mn","ms","mtext"]),Tt=D(e,"HTML_INTEGRATION_POINTS")&&e.HTML_INTEGRATION_POINTS&&"object"==typeof e.HTML_INTEGRATION_POINTS?v(e.HTML_INTEGRATION_POINTS):k({},["annotation-xml"]);const t=D(e,"CUSTOM_ELEMENT_HANDLING")&&e.CUSTOM_ELEMENT_HANDLING&&"object"==typeof e.CUSTOM_ELEMENT_HANDLING?v(e.CUSTOM_ELEMENT_HANDLING):l(null);if(ve=l(null),D(t,"tagNameCheck")&&bt(t.tagNameCheck)&&(ve.tagNameCheck=t.tagNameCheck),D(t,"attributeNameCheck")&&bt(t.attributeNameCheck)&&(ve.attributeNameCheck=t.attributeNameCheck),D(t,"allowCustomizedBuiltInElements")&&"boolean"==typeof t.allowCustomizedBuiltInElements&&(ve.allowCustomizedBuiltInElements=t.allowCustomizedBuiltInElements),Ge&&(Fe=!1),$e&&(qe=!0),tt&&(Ce=k({},G),ke=l(null),!0===tt.html&&(k(Ce,P),k(ke,W)),!0===tt.svg&&(k(Ce,U),k(ke,j),k(ke,X)),!0===tt.svgFilters&&(k(Ce,z),k(ke,j),k(ke,X)),!0===tt.mathMl&&(k(Ce,H),k(ke,Y),k(ke,X))),Ue.tagCheck=null,Ue.attributeCheck=null,D(e,"ADD_TAGS")&&("function"==typeof e.ADD_TAGS?Ue.tagCheck=e.ADD_TAGS:h(e.ADD_TAGS)&&(Ce===Le&&(Ce=v(Ce)),k(Ce,e.ADD_TAGS,Et))),D(e,"ADD_ATTR")&&("function"==typeof e.ADD_ATTR?Ue.attributeCheck=e.ADD_ATTR:h(e.ADD_ATTR)&&(ke===xe&&(ke=v(ke)),k(ke,e.ADD_ATTR,Et))),D(e,"ADD_URI_SAFE_ATTR")&&h(e.ADD_URI_SAFE_ATTR)&&k(at,e.ADD_URI_SAFE_ATTR,Et),D(e,"FORBID_CONTENTS")&&h(e.FORBID_CONTENTS)&&(nt===ot&&(nt=v(nt)),k(nt,e.FORBID_CONTENTS,Et)),D(e,"ADD_FORBID_CONTENTS")&&h(e.ADD_FORBID_CONTENTS)&&(nt===ot&&(nt=v(nt)),k(nt,e.ADD_FORBID_CONTENTS,Et)),Qe&&(Ce["#text"]=!0),je&&k(Ce,["html","head","body"]),Ce.table&&(k(Ce,["tbody"]),delete Me.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw w('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw w('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');pe=e.TRUSTED_TYPES_POLICY,de=pe.createHTML("")}else void 0===pe&&(pe=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}}(Z,c)),null!==pe&&"string"==typeof de&&(de=pe.createHTML(""));i&&i(e),_t=e},Rt=k({},[...U,...z,...F]),Dt=k({},[...H,...B]),Ot=function(e){p(o.removed,{element:e});try{fe(e).removeChild(e)}catch(t){ne(e)}},It=function(e,t){try{p(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e)if(qe||$e)try{Ot(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},wt=function(e){let t=null,n=null;if(Xe)e=""+e;else{const t=y(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===yt&&mt===ut&&(e=''+e+"");const o=pe?pe.createHTML(e):e;if(mt===ut)try{t=(new V).parseFromString(o,yt)}catch(e){}if(!t||!t.documentElement){t=he.createDocument(mt,"template",null);try{t.documentElement.innerHTML=ft?de:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),mt===ut?ye.call(t,je?"html":"body")[0]:je?t.documentElement:i},Ct=function(e){return Te.call(e.ownerDocument||e,e,q.SHOW_ELEMENT|q.SHOW_COMMENT|q.SHOW_TEXT|q.SHOW_PROCESSING_INSTRUCTION|q.SHOW_CDATA_SECTION,null)},Lt=function(e){return e instanceof K&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof $)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},kt=function(e){return"function"==typeof L&&e instanceof L};function xt(e,t,n){u(e,e=>{e.call(o,t,n,_t)})}const vt=function(e){let t=null;if(xt(Ee.beforeSanitizeElements,e,null),Lt(e))return Ot(e),!0;const n=Et(e.nodeName);if(xt(Ee.uponSanitizeElement,e,{tagName:n,allowedTags:Ce}),We&&e.hasChildNodes()&&!kt(e.firstElementChild)&&I(/<[/\w!]/g,e.innerHTML)&&I(/<[/\w!]/g,e.textContent))return Ot(e),!0;if(We&&e.namespaceURI===ut&&"style"===n&&kt(e.firstElementChild))return Ot(e),!0;if(e.nodeType===ae)return Ot(e),!0;if(We&&e.nodeType===le&&I(/<[/\w]/g,e.data))return Ot(e),!0;if(Me[n]||!(Ue.tagCheck instanceof Function&&Ue.tagCheck(n))&&!Ce[n]){if(!Me[n]&&Ut(n)){if(ve.tagNameCheck instanceof RegExp&&I(ve.tagNameCheck,n))return!1;if(ve.tagNameCheck instanceof Function&&ve.tagNameCheck(n))return!1}if(Qe&&!nt[n]){const t=fe(e)||e.parentNode,n=me(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=ee(n[o],!0);t.insertBefore(r,ue(e))}}}return Ot(e),!0}return e instanceof x&&!function(e){let t=fe(e);t&&t.tagName||(t={namespaceURI:mt,tagName:"template"});const n=T(e.tagName),o=T(t.tagName);return!!pt[e.namespaceURI]&&(e.namespaceURI===st?t.namespaceURI===ut?"svg"===n:t.namespaceURI===ct?"svg"===n&&("annotation-xml"===o||ht[o]):Boolean(Rt[n]):e.namespaceURI===ct?t.namespaceURI===ut?"math"===n:t.namespaceURI===st?"math"===n&&Tt[o]:Boolean(Dt[n]):e.namespaceURI===ut?!(t.namespaceURI===st&&!Tt[o])&&!(t.namespaceURI===ct&&!ht[o])&&!Dt[n]&&(gt[n]||!Rt[n]):!("application/xhtml+xml"!==yt||!pt[e.namespaceURI]))}(e)?(Ot(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!I(/<\/no(script|embed|frames)/i,e.innerHTML)?(Ge&&e.nodeType===ie&&(t=e.textContent,u([_e,Se,be],e=>{t=A(t,e," ")}),e.textContent!==t&&(p(o.removed,{element:e.cloneNode()}),e.textContent=t)),xt(Ee.afterSanitizeElements,e,null),!1):(Ot(e),!0)},Mt=function(e,t,n){if(Pe[t])return!1;if(Ve&&("id"===t||"name"===t)&&(n in r||n in St))return!1;if(Fe&&!Pe[t]&&I(Ne,t));else if(ze&&I(Re,t));else if(Ue.attributeCheck instanceof Function&&Ue.attributeCheck(t,e));else if(!ke[t]||Pe[t]){if(!(Ut(e)&&(ve.tagNameCheck instanceof RegExp&&I(ve.tagNameCheck,e)||ve.tagNameCheck instanceof Function&&ve.tagNameCheck(e))&&(ve.attributeNameCheck instanceof RegExp&&I(ve.attributeNameCheck,t)||ve.attributeNameCheck instanceof Function&&ve.attributeNameCheck(t,e))||"is"===t&&ve.allowCustomizedBuiltInElements&&(ve.tagNameCheck instanceof RegExp&&I(ve.tagNameCheck,n)||ve.tagNameCheck instanceof Function&&ve.tagNameCheck(n))))return!1}else if(at[t]);else if(I(we,A(n,Oe,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==E(n,"data:")||!rt[e]){if(He&&!I(De,A(n,Oe,"")));else if(n)return!1}else;return!0},Pt=k({},["annotation-xml","color-profile","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","missing-glyph"]),Ut=function(e){return!Pt[T(e)]&&I(Ie,e)},zt=function(e){xt(Ee.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t||Lt(e))return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:ke,forceKeepAttr:void 0};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=Et(a),m=c;let p="value"===a?m:_(m);if(n.attrName=s,n.attrValue=p,n.keepAttr=!0,n.forceKeepAttr=void 0,xt(Ee.uponSanitizeAttribute,e,n),p=n.attrValue,!Ze||"id"!==s&&"name"!==s||0===E(p,Je)||(It(a,e),p=Je+p),We&&I(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,p)){It(a,e);continue}if("attributename"===s&&y(p,"href")){It(a,e);continue}if(n.forceKeepAttr)continue;if(!n.keepAttr){It(a,e);continue}if(!Be&&I(/\/>/i,p)){It(a,e);continue}Ge&&u([_e,Se,be],e=>{p=A(p,e," ")});const d=Et(e.nodeName);if(Mt(d,s,p)){if(pe&&"object"==typeof Z&&"function"==typeof Z.getAttributeType)if(l);else switch(Z.getAttributeType(d,s)){case"TrustedHTML":p=pe.createHTML(p);break;case"TrustedScriptURL":p=pe.createScriptURL(p)}if(p!==m)try{l?e.setAttributeNS(l,a,p):e.setAttribute(a,p),Lt(e)?Ot(e):f(o.removed)}catch(t){It(a,e)}}else It(a,e)}xt(Ee.afterSanitizeAttributes,e,null)},Ft=function(e){let t=null;const n=Ct(e);for(xt(Ee.beforeSanitizeShadowDOM,e,null);t=n.nextNode();)xt(Ee.uponSanitizeShadowNode,t,null),vt(t),zt(t),t.content instanceof s&&Ft(t.content);xt(Ee.afterSanitizeShadowDOM,e,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(ft=!e,ft&&(e="\x3c!--\x3e"),"string"!=typeof e&&!kt(e)&&"string"!=typeof(e=function(e){switch(typeof e){case"string":return e;case"number":return S(e);case"boolean":return b(e);case"bigint":return N?N(e):"0";case"symbol":return R?R(e):"Symbol()";case"undefined":default:return O(e);case"function":case"object":{if(null===e)return O(e);const t=e,n=M(t,"toString");if("function"==typeof n){const e=n(t);return"string"==typeof e?e:O(e)}return O(e)}}}(e)))throw w("dirty is not a string, aborting");if(!o.isSupported)return e;if(Ye||Nt(t),o.removed=[],"string"==typeof e&&(et=!1),et){const t=e.nodeName;if("string"==typeof t){const e=Et(t);if(!Ce[e]||Me[e])throw w("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof L)n=wt("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===re&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!qe&&!Ge&&!je&&-1===e.indexOf("<"))return pe&&Ke?pe.createHTML(e):e;if(n=wt(e),!n)return qe?null:Ke?de:""}n&&Xe&&Ot(n.firstChild);const c=Ct(et?e:n);for(;i=c.nextNode();)vt(i),zt(i),i.content instanceof s&&Ft(i.content);if(et)return e;if(qe){if(Ge){n.normalize();let e=n.innerHTML;u([_e,Se,be],t=>{e=A(e,t," ")}),n.innerHTML=e}if($e)for(l=ge.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(ke.shadowroot||ke.shadowrootmode)&&(l=Ae.call(a,l,!0)),l}let m=je?n.outerHTML:n.innerHTML;return je&&Ce["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&I(te,n.ownerDocument.doctype.name)&&(m="\n"+m),Ge&&u([_e,Se,be],e=>{m=A(m,e," ")}),pe&&Ke?pe.createHTML(m):m},o.setConfig=function(){Nt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Ye=!0},o.clearConfig=function(){_t=null,Ye=!1},o.isValidAttribute=function(e,t,n){_t||Nt({});const o=Et(e),r=Et(t);return Mt(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&p(Ee[e],t)},o.removeHook=function(e,t){if(void 0!==t){const n=m(Ee[e],t);return-1===n?void 0:d(Ee[e],n,1)[0]}return f(Ee[e])},o.removeHooks=function(e){Ee[e]=[]},o.removeAllHooks=function(){Ee={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},o}();return ue}); +//# sourceMappingURL=purify.min.js.map diff --git a/js/zlib-1.3.1.wasm b/js/zlib-1.3.1.wasm deleted file mode 100644 index 2fbc9169..00000000 Binary files a/js/zlib-1.3.1.wasm and /dev/null differ diff --git a/js/zlib-1.3.2.js b/js/zlib-1.3.2.js new file mode 100644 index 00000000..0a5acd00 --- /dev/null +++ b/js/zlib-1.3.2.js @@ -0,0 +1,2 @@ +async function Module(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("node:module");var require=createRequire(import.meta.url)}var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var _scriptName=import.meta.url;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");if(_scriptName.startsWith("file:")){scriptDirectory=require("node:path").dirname(require("node:url").fileURLToPath(_scriptName))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["d"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("zlib-1.3.2.wasm")}return new URL("zlib-1.3.2.wasm",import.meta.url).href}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}function writeToJs(ptr,dst,size){const o=Module.map[ptr];if(o&&typeof o.onData==="function"){o.onData(Module.HEAPU8.subarray(dst,dst+size))}else{console.error("No handler found for pointer:",ptr)}}var __malloc,__free,__createDeflateContext,__deflate,__freeDeflateContext,__createInflateContext,__inflate,__freeInflateContext,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){__malloc=Module["__malloc"]=wasmExports["e"];__free=Module["__free"]=wasmExports["f"];__createDeflateContext=Module["__createDeflateContext"]=wasmExports["g"];__deflate=Module["__deflate"]=wasmExports["h"];__freeDeflateContext=Module["__freeDeflateContext"]=wasmExports["i"];__createInflateContext=Module["__createInflateContext"]=wasmExports["j"];__inflate=Module["__inflate"]=wasmExports["k"];__freeInflateContext=Module["__freeInflateContext"]=wasmExports["l"];memory=wasmMemory=wasmExports["c"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={b:_emscripten_resize_heap,a:writeToJs};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +;return moduleRtn}export default Module; diff --git a/js/zlib-1.3.2.wasm b/js/zlib-1.3.2.wasm new file mode 100644 index 00000000..7c5b0674 Binary files /dev/null and b/js/zlib-1.3.2.wasm differ diff --git a/js/zlib-1.3.1-2.js b/js/zlib.js similarity index 58% rename from js/zlib-1.3.1-2.js rename to js/zlib.js index 3e38c3ea..5509c05f 100644 --- a/js/zlib-1.3.1-2.js +++ b/js/zlib.js @@ -9,37 +9,22 @@ const COMPRESSION_LEVEL = 7; const NO_ZLIB_HEADER = -1; const CHUNK_SIZE = 32 * 1024; - const map = {}; - const memory = new WebAssembly.Memory({ - initial: 1, - maximum: 1024, // 64MB - }); - const env = { - memory, - writeToJs(ptr, size) { - const o = map[ptr]; - o.onData(new Uint8Array(memory.buffer, dstPtr, size)); - }, - _abort: errno => { console.error(`Error: ${errno}`) }, - _grow: () => { }, - }; - const ins = (await WebAssembly.instantiateStreaming(fetch('js/zlib-1.3.1.wasm'), { env })).instance; - - const srcPtr = ins.exports._malloc(CHUNK_SIZE); - const dstPtr = ins.exports._malloc(CHUNK_SIZE); + const createModule = (await import('./zlib-1.3.2.js')).default; + const Module = await createModule({map: {}}); + const srcPtr = Module.__malloc(CHUNK_SIZE); + const dstPtr = Module.__malloc(CHUNK_SIZE); class RawDef { constructor() { - this.zstreamPtr = ins.exports._createDeflateContext(COMPRESSION_LEVEL, NO_ZLIB_HEADER); - map[this.zstreamPtr] = this; + this.zstreamPtr = Module.__createDeflateContext(COMPRESSION_LEVEL, NO_ZLIB_HEADER); + Module.map[this.zstreamPtr] = this; this.offset = 0; this.buff = new Uint8Array(CHUNK_SIZE); } deflate(chunk, flush) { - const src = new Uint8Array(memory.buffer, srcPtr, chunk.length); - src.set(chunk); - ins.exports._deflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE, flush); + Module.HEAPU8.set(chunk, srcPtr); + Module.__deflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE, flush); } onData(chunk) { @@ -53,32 +38,27 @@ } destroy() { - ins.exports._freeDeflateContext(this.zstreamPtr); - delete map[this.zstreamPtr]; + Module.__freeDeflateContext(this.zstreamPtr); + delete Module.map[this.zstreamPtr]; this.buff = null; } getBuffer() { - const res = new Uint8Array(this.offset); - for (let i = 0; i < this.offset; ++i) { - res[i] = this.buff[i]; - } - return res; + return this.buff.slice(0, this.offset); } } class RawInf { constructor() { - this.zstreamPtr = ins.exports._createInflateContext(NO_ZLIB_HEADER); - map[this.zstreamPtr] = this; + this.zstreamPtr = Module.__createInflateContext(NO_ZLIB_HEADER); + Module.map[this.zstreamPtr] = this; this.offset = 0; this.buff = new Uint8Array(CHUNK_SIZE); } inflate(chunk) { - const src = new Uint8Array(memory.buffer, srcPtr, chunk.length); - src.set(chunk); - ins.exports._inflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE); + Module.HEAPU8.set(chunk, srcPtr); + Module.__inflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE); } onData(chunk) { @@ -92,17 +72,13 @@ } destroy() { - ins.exports._freeInflateContext(this.zstreamPtr); - delete map[this.zstreamPtr]; + Module.__freeInflateContext(this.zstreamPtr); + delete Module.map[this.zstreamPtr]; this.buff = null; } getBuffer() { - const res = new Uint8Array(this.offset); - for (let i = 0; i < this.offset; ++i) { - res[i] = this.buff[i]; - } - return res; + return this.buff.slice(0, this.offset); } } diff --git a/lib/Configuration.php b/lib/Configuration.php index 950cf069..744dd90d 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -123,9 +123,10 @@ class Configuration 'js/legacy.js' => 'sha512-RQEo1hxpNc37i+jz/D9/JiAZhG8GFx3+SNxjYnI7jUgirDIqrCSj6QPAAZeaidditcWzsJ3jxfEj5lVm7ZwTRQ==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', 'js/privatebin.js' => 'sha512-6SwOJniNN8RBmAK7yCt4ly2qYyH8OALxB74/K1AJgw+YnZgRCfTDVq1qY1K5Y2QCxCODGGTpAjTqQRExzCqV7g==', - 'js/purify-3.3.2.js' => 'sha512-I6igPVpf3xNghG92mujwqB6Zi3LpUTsni4bRuLnMThEGH6BDbsumv7373+AXHzA4OUlxGsym8ZxKFHy4xjYvkQ==', + 'js/purify-3.4.1.js' => 'sha512-280a/Vb6fVFsYaeRrkuDp4EDmdYlt2XS+dlDEO/U9qljPrAraA2bIzHTNmP+9dpwPDDwTML+RS+h5iaagPwTzA==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', - 'js/zlib-1.3.1-2.js' => 'sha512-4gT+v+BkBqdVBbKOO4qKGOAzuay+v1FmOLksS+bMgQ08Oo4xEb3X48Xq1Kv2b4HtiCQA7xq9dFRzxal7jmQI7w==', + 'js/zlib-1.3.2.js' => 'sha512-RAhJgxg9siMIA8ky4c10Rc2zUgnK80olHB8Tt1IOYWY4Eh1WmrviQkDn+sgBlb38ZHq3tzufGC41kP360gmosQ==', + 'js/zlib.js' => 'sha512-QOaEwssHqHRRcWJ2Un3Kl2Zhyprzl7T8zmsKN2FppFxW3VR+8UChYOx2iuL0HbXK42fuBWJm5PNQJxufulrt/w==', ), ); diff --git a/lib/View.php b/lib/View.php index 514ac2b1..adb8d5ef 100644 --- a/lib/View.php +++ b/lib/View.php @@ -62,6 +62,48 @@ class View include $path; } + /** + * get cache buster query string + * + * if the file isn't versioned (ends in a digit), adds our own version as a query string + * + * @access private + * @param string $file + */ + private function _getCacheBuster($file) + { + if ((bool) preg_match('#[0-9]\.m?js$#', (string) $file)) { + return ''; + } + return '?' . rawurlencode($this->_variables['VERSION']); + } + + /** + * get SRI hash for given file + * + * @access private + * @param string $file + */ + private function _getSri($file) + { + if (array_key_exists($file, $this->_variables['SRI'])) { + return ' integrity="' . $this->_variables['SRI'][$file] . '"'; + } + return ''; + } + + /** + * echo module preload link tag incl. SRI hash for given script file + * + * @access private + * @param string $file + */ + private function _linkTag($file) + { + echo '_getSri($file), ' />', PHP_EOL; + } + /** * echo script tag incl. SRI hash for given script file * @@ -71,13 +113,9 @@ class View */ private function _scriptTag($file, $attributes = '') { - $sri = array_key_exists($file, $this->_variables['SRI']) ? - ' integrity="' . $this->_variables['SRI'][$file] . '"' : ''; - // if the file isn't versioned (ends in a digit), add our own version - $cacheBuster = (bool) preg_match('#[0-9]\.js$#', (string) $file) ? - '' : '?' . rawurlencode($this->_variables['VERSION']); echo '', PHP_EOL; + $this->_getCacheBuster($file), '"', $this->_getSri($file), + ' crossorigin="anonymous">', PHP_EOL; } } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 283c84ab..315dbd0c 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -42,6 +42,7 @@ if ($SYNTAXHIGHLIGHTING) : endif; ?> + _linkTag('js/zlib-1.3.2.js'); ?> _scriptTag('js/jquery-3.7.1.js', 'defer'); ?> - _scriptTag('js/zlib-1.3.1-2.js', 'defer'); ?> + _scriptTag('js/zlib.js', 'defer'); ?> _scriptTag('js/base-x-5.0.1.js', 'defer'); ?> _scriptTag('js/bootstrap-3.4.1.js', 'defer'); ?> - _scriptTag('js/purify-3.3.2.js', 'defer'); ?> + _scriptTag('js/purify-3.4.1.js', 'defer'); ?> _scriptTag('js/legacy.js', 'defer'); ?> _scriptTag('js/privatebin.js', 'defer'); ?> diff --git a/tpl/bootstrap5.php b/tpl/bootstrap5.php index dc523dff..e90907f9 100644 --- a/tpl/bootstrap5.php +++ b/tpl/bootstrap5.php @@ -25,6 +25,7 @@ if ($SYNTAXHIGHLIGHTING) : endif; ?> + _linkTag('js/zlib-1.3.2.js'); ?> _scriptTag('js/jquery-3.7.1.js', 'defer'); ?> - _scriptTag('js/zlib-1.3.1-2.js', 'defer'); ?> + _scriptTag('js/zlib.js', 'defer'); ?> _scriptTag('js/base-x-5.0.1.js', 'defer'); ?> _scriptTag('js/bootstrap-5.3.8.js', 'defer'); ?> _scriptTag('js/dark-mode-switch.js', 'defer'); ?> @@ -49,7 +50,7 @@ if ($MARKDOWN) : - _scriptTag('js/purify-3.3.2.js', 'defer'); ?> + _scriptTag('js/purify-3.4.1.js', 'defer'); ?> _scriptTag('js/legacy.js', 'defer'); ?> _scriptTag('js/privatebin.js', 'defer'); ?> diff --git a/tst/Bootstrap.php b/tst/Bootstrap.php index ea83e791..0c24da89 100644 --- a/tst/Bootstrap.php +++ b/tst/Bootstrap.php @@ -341,7 +341,7 @@ class Helper */ public static function updateSubresourceIntegrity(): void { - foreach (new GlobIterator(PATH . 'js' . DIRECTORY_SEPARATOR . '*.js') as $file) { + foreach (new GlobIterator(PATH . 'js' . DIRECTORY_SEPARATOR . '*.*js') as $file) { if ($file->getBasename() === 'common.js' || $file->getBasename() === 'eslint.config.js') { continue; // ignore JS unit test bootstrap } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index f619d450..9d92f906 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'privatebin/privatebin', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '8eb39b4ffa8daed3d8ff0279c9870ee5b6b0bd95', + 'reference' => '67baf8cca4b7aa1bc57e631b47ab561695c8ce2b', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -20,9 +20,9 @@ 'dev_requirement' => false, ), 'mlocati/ip-lib' => array( - 'pretty_version' => '1.21.0', - 'version' => '1.21.0.0', - 'reference' => 'b5d38cdcbfc1516604d821a1f3f4a1638f327267', + 'pretty_version' => '1.22.0', + 'version' => '1.22.0.0', + 'reference' => '4e40ffd3bf9989db19403d89c4d8be44b87b8a91', 'type' => 'library', 'install_path' => __DIR__ . '/../mlocati/ip-lib', 'aliases' => array(), @@ -31,16 +31,16 @@ 'privatebin/privatebin' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '8eb39b4ffa8daed3d8ff0279c9870ee5b6b0bd95', + 'reference' => '67baf8cca4b7aa1bc57e631b47ab561695c8ce2b', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php80' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8', + 'pretty_version' => 'v1.34.0', + 'version' => '1.34.0.0', + 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), diff --git a/vendor/mlocati/ip-lib/src/Address/AddressInterface.php b/vendor/mlocati/ip-lib/src/Address/AddressInterface.php index 0dcae827..28a625ca 100644 --- a/vendor/mlocati/ip-lib/src/Address/AddressInterface.php +++ b/vendor/mlocati/ip-lib/src/Address/AddressInterface.php @@ -63,6 +63,8 @@ interface AddressInterface * Get the type of the IP address. * * @return int One of the \IPLib\Address\Type::T_... constants + * + * @phpstan-return \IPLib\Address\Type::T_IPv4|\IPLib\Address\Type::T_IPv6 */ public function getAddressType(); @@ -110,7 +112,7 @@ interface AddressInterface /** * Get the address at a certain distance from this address. * - * @param int|numeric-string $n the distance of the address (can be negative) + * @param int|numeric-string|mixed $n the distance of the address (can be negative) * * @return \IPLib\Address\AddressInterface|null return NULL if $n is not an integer or NULL if $n is neither an integer nor a string containing a valid integer, or if the final address would be invalid * diff --git a/vendor/mlocati/ip-lib/src/Address/IPv4.php b/vendor/mlocati/ip-lib/src/Address/IPv4.php index c59f0025..c5f691e2 100644 --- a/vendor/mlocati/ip-lib/src/Address/IPv4.php +++ b/vendor/mlocati/ip-lib/src/Address/IPv4.php @@ -11,6 +11,8 @@ use IPLib\Service\NumberInChunks; /** * An IPv4 address. + * + * @phpstan-consistent-constructor */ class IPv4 implements AddressInterface { @@ -40,14 +42,14 @@ class IPv4 implements AddressInterface /** * A string representation of this address than can be used when comparing addresses and ranges. * - * @var string + * @var string|null */ protected $comparableString; /** * An array containing RFC designated address ranges. * - * @var array|null + * @var \IPLib\Address\AssignedRange[]|null */ private static $reservedRanges; @@ -181,7 +183,7 @@ class IPv4 implements AddressInterface /** * Parse an array of bytes and returns an IPv4 instance if the array is valid, or null otherwise. * - * @param int[]|array $bytes + * @param array $bytes * * @return static|null */ @@ -367,10 +369,14 @@ class IPv4 implements AddressInterface $exceptions = array(); if (isset($data[1])) { foreach ($data[1] as $exceptionRange => $exceptionType) { - $exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType); + $subnet = Subnet::parseString($exceptionRange); + /** @var Subnet $subnet */ + $exceptions[] = new AssignedRange($subnet, $exceptionType); } } - $reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions); + $subnet = Subnet::parseString($range); + /** @var Subnet $subnet */ + $reservedRanges[] = new AssignedRange($subnet, $data[0], $exceptions); } self::$reservedRanges = $reservedRanges; } @@ -407,8 +413,10 @@ class IPv4 implements AddressInterface public function toIPv6() { $myBytes = $this->getBytes(); + $ipv6 = IPv6::parseString('2002:' . sprintf('%02x', $myBytes[0]) . sprintf('%02x', $myBytes[1]) . ':' . sprintf('%02x', $myBytes[2]) . sprintf('%02x', $myBytes[3]) . '::'); + /** @var IPv6 $ipv6 */ - return IPv6::parseString('2002:' . sprintf('%02x', $myBytes[0]) . sprintf('%02x', $myBytes[1]) . ':' . sprintf('%02x', $myBytes[2]) . sprintf('%02x', $myBytes[3]) . '::'); + return $ipv6; } /** @@ -420,7 +428,10 @@ class IPv4 implements AddressInterface */ public function toIPv6IPv4Mapped() { - return IPv6::fromBytes(array_merge(array(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff), $this->getBytes())); + $ipv6 = IPv6::fromBytes(array_merge(array(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff), $this->getBytes())); + /** @var IPv6 $ipv6 */ + + return $ipv6; } /** diff --git a/vendor/mlocati/ip-lib/src/Address/IPv6.php b/vendor/mlocati/ip-lib/src/Address/IPv6.php index 80749e33..149becdf 100644 --- a/vendor/mlocati/ip-lib/src/Address/IPv6.php +++ b/vendor/mlocati/ip-lib/src/Address/IPv6.php @@ -11,6 +11,8 @@ use IPLib\Service\NumberInChunks; /** * An IPv6 address. + * + * @phpstan-consistent-constructor */ class IPv6 implements AddressInterface { @@ -56,7 +58,7 @@ class IPv6 implements AddressInterface /** * An array containing RFC designated address ranges. * - * @var array|null + * @var \IPLib\Address\AssignedRange[]|null */ private static $reservedRanges; @@ -144,7 +146,7 @@ class IPv6 implements AddressInterface } } $result = null; - if (is_string($address) && strpos($address, ':') !== false && strpos($address, ':::') === false) { + if (strpos($address, ':') !== false && strpos($address, ':::') === false) { if ($flags & ParseStringFlag::MAY_INCLUDE_PORT && $address[0] === '[' && preg_match('/^\[(.+)]:\d+$/', $address, $matches)) { $address = $matches[1]; } @@ -212,7 +214,7 @@ class IPv6 implements AddressInterface /** * Parse an array of bytes and returns an IPv6 instance if the array is valid, or null otherwise. * - * @param int[]|array $bytes + * @param array $bytes * * @return static|null */ @@ -244,7 +246,7 @@ class IPv6 implements AddressInterface /** * Parse an array of words and returns an IPv6 instance if the array is valid, or null otherwise. * - * @param int[]|array $words + * @param array $words * * @return static|null */ @@ -353,7 +355,7 @@ class IPv6 implements AddressInterface if ($this->words === null) { $this->words = array_map( function ($chunk) { - return hexdec($chunk); + return (int) hexdec($chunk); }, explode(':', $this->longAddress) ); @@ -441,10 +443,14 @@ class IPv6 implements AddressInterface $exceptions = array(); if (isset($data[1])) { foreach ($data[1] as $exceptionRange => $exceptionType) { - $exceptions[] = new AssignedRange(Subnet::parseString($exceptionRange), $exceptionType); + $subnet = Subnet::parseString($exceptionRange); + /** @var Subnet $subnet */ + $exceptions[] = new AssignedRange($subnet, $exceptionType); } } - $reservedRanges[] = new AssignedRange(Subnet::parseString($range), $data[0], $exceptions); + $subnet = Subnet::parseString($range); + /** @var Subnet $subnet */ + $reservedRanges[] = new AssignedRange($subnet, $data[0], $exceptions); } self::$reservedRanges = $reservedRanges; } @@ -517,11 +523,17 @@ class IPv6 implements AddressInterface { $myBytes = $this->getBytes(); $ipv6Bytes = array_merge(array_slice($myBytes, 0, 12), array(0xff, 0xff, 0xff, 0xff)); - $ipv6String = static::fromBytes($ipv6Bytes)->toString($ipV6Long); + $ipv6 = static::fromBytes($ipv6Bytes); + /** @var IPv6 $ipv6 */ + $ipv6String = $ipv6->toString($ipV6Long); $ipv4Bytes = array_slice($myBytes, 12, 4); - $ipv4String = IPv4::fromBytes($ipv4Bytes)->toString($ipV4Long); + $ipv4 = IPv4::fromBytes($ipv4Bytes); + /** @var IPv4 $ipv4 */ + $ipv4String = $ipv4->toString($ipV4Long); + $result = preg_replace('/((ffff:ffff)|(\d+(\.\d+){3}))$/i', $ipv4String, $ipv6String); + /** @var string $result */ - return preg_replace('/((ffff:ffff)|(\d+(\.\d+){3}))$/i', $ipv4String, $ipv6String); + return $result; } /** @@ -627,8 +639,11 @@ class IPv6 implements AddressInterface $paddedBits = substr($paddedBits, $absBits) . $pad; } $bytes = array_map('bindec', str_split($paddedBits, 16)); + /** @var int[] $bytes */ + $result = static::fromWords($bytes); + /** @var IPv6 $result */ - return static::fromWords($bytes); + return $result; } /** diff --git a/vendor/mlocati/ip-lib/src/Address/Type.php b/vendor/mlocati/ip-lib/src/Address/Type.php index 17488f38..da5d2b3a 100644 --- a/vendor/mlocati/ip-lib/src/Address/Type.php +++ b/vendor/mlocati/ip-lib/src/Address/Type.php @@ -24,7 +24,7 @@ class Type /** * Get the name of a type. * - * @param int $type + * @param int|mixed $type * * @return string * @@ -38,7 +38,7 @@ class Type case static::T_IPv6: return 'IP v6'; default: - return sprintf('Unknown type (%s)', $type); + return $type === null ? 'Unknown type' : sprintf('Unknown type (%s)', print_r($type, true)); } } } diff --git a/vendor/mlocati/ip-lib/src/Factory.php b/vendor/mlocati/ip-lib/src/Factory.php index 9338a2d6..3e92b234 100644 --- a/vendor/mlocati/ip-lib/src/Factory.php +++ b/vendor/mlocati/ip-lib/src/Factory.php @@ -48,35 +48,33 @@ class Factory */ public static function parseAddressString($address, $flags = 0) { - $result = null; - if ($result === null) { - $result = Address\IPv4::parseString($address, $flags); + if (($result = Address\IPv4::parseString($address, $flags)) !== null) { + return $result; } - if ($result === null) { - $result = Address\IPv6::parseString($address, $flags); + if (($result = Address\IPv6::parseString($address, $flags)) !== null) { + return $result; } - return $result; + return null; } /** * Convert a byte array to an address instance. * - * @param int[]|array $bytes + * @param array $bytes * * @return \IPLib\Address\AddressInterface|null */ public static function addressFromBytes(array $bytes) { - $result = null; - if ($result === null) { - $result = Address\IPv4::fromBytes($bytes); + if (($result = Address\IPv4::fromBytes($bytes)) !== null) { + return $result; } - if ($result === null) { - $result = Address\IPv6::fromBytes($bytes); + if (($result = Address\IPv6::fromBytes($bytes)) !== null) { + return $result; } - return $result; + return null; } /** @@ -100,7 +98,7 @@ class Factory /** * Parse an IP range string. * - * @param string $range + * @param string|mixed $range * @param int $flags A combination or zero or more flags * * @return \IPLib\Range\RangeInterface|null @@ -110,10 +108,7 @@ class Factory */ public static function parseRangeString($range, $flags = 0) { - $result = null; - if ($result === null) { - $result = Range\Subnet::parseString($range, $flags); - } + $result = Range\Subnet::parseString($range, $flags); if ($result === null) { $result = Range\Pattern::parseString($range, $flags); } @@ -133,7 +128,7 @@ class Factory * @param string|\IPLib\Address\AddressInterface|mixed $to * @param bool $supportNonDecimalIPv4 * - * @return \IPLib\Address\AddressInterface|null + * @return \IPLib\Range\RangeInterface|null * * @see \IPLib\Factory::getRangeFromBoundaries() * @since 1.2.0 @@ -163,6 +158,53 @@ class Factory return $from === false || $to === false ? null : static::rangeFromBoundaryAddresses($from, $to); } + /** + * Calculate the minimal range that contains all the specified addresses. + * + * @param array $addresses + * @param int $flags + * + * @return \IPLib\Range\RangeInterface|null Returns NULL if $addresses is empty, if it contains invalid addresses, or if the addresses aren't compatible (for example, both IPv4 and IPv6 addresses) + * + * @since 1.22.0 + */ + public static function getRangeFromAddresses(array $addresses, $flags = 0) + { + $min = null; + $max = null; + $numberOfBits = null; + foreach ($addresses as $address) { + if (!$address instanceof AddressInterface) { + $address = Factory::parseAddressString($address, $flags); + if ($address === null) { + return null; + } + } + if ($numberOfBits === null) { + $min = $address; + $max = $address; + $numberOfBits = $address->getNumberOfBits(); + } elseif ($numberOfBits !== $address->getNumberOfBits()) { + return null; + } else { + /** @var AddressInterface $min */ + /** @var AddressInterface $max */ + $comparable = $address->getComparableString(); + if ($min->getComparableString() > $comparable) { + $min = $address; + } + if ($max->getComparableString() < $comparable) { + $max = $address; + } + } + } + if ($numberOfBits === null) { + return null; + } + + return static::rangeFromBoundaryAddresses($min, $max); + } + /** * @deprecated since 1.17.0: use the getRangesFromBoundaries() method instead. * For upgrading: @@ -185,8 +227,8 @@ class Factory /** * Create a list of Range instances that exactly describes all the addresses between the two provided addresses. * - * @param string|\IPLib\Address\AddressInterface $from - * @param string|\IPLib\Address\AddressInterface $to + * @param string|\IPLib\Address\AddressInterface|mixed $from + * @param string|\IPLib\Address\AddressInterface|mixed $to * @param int $flags A combination or zero or more flags * * @return \IPLib\Range\Subnet[]|null return NULL if $from and/or $to are invalid addresses, or if both are NULL or empty strings, or if they are addresses of different types @@ -202,6 +244,7 @@ class Factory } if ($from === null || $to === null) { $address = $from ? $from : $to; + /** @var AddressInterface $address */ return array(new Subnet($address, $address, $address->getNumberOfBits())); } @@ -265,11 +308,11 @@ class Factory } /** - * @param string|\IPLib\Address\AddressInterface $from - * @param string|\IPLib\Address\AddressInterface $to + * @param string|\IPLib\Address\AddressInterface|mixed $from + * @param string|\IPLib\Address\AddressInterface|mixed $to * @param int $flags * - * @return \IPLib\Address\AddressInterface[]|null[]|false[] + * @return array{\IPLib\Address\AddressInterface|false|null, \IPLib\Address\AddressInterface|false|null} */ private static function parseBoundaries($from, $to, $flags = 0) { @@ -277,7 +320,7 @@ class Factory foreach (array('from', 'to') as $param) { $value = $$param; if (!($value instanceof AddressInterface)) { - $value = (string) $value; + $value = is_object($value) && method_exists($value, '__toString') || is_scalar($value) ? (string) $value : ''; if ($value === '') { $value = null; } else { @@ -289,6 +332,7 @@ class Factory } $result[] = $value; } + /** @var array{\IPLib\Address\AddressInterface|false|null, \IPLib\Address\AddressInterface|false|null} $result */ if ($result[0] && $result[1] && strcmp($result[0]->getComparableString(), $result[1]->getComparableString()) > 0) { $result = array($result[1], $result[0]); } diff --git a/vendor/mlocati/ip-lib/src/Range/AbstractRange.php b/vendor/mlocati/ip-lib/src/Range/AbstractRange.php index 9faea570..019349cf 100644 --- a/vendor/mlocati/ip-lib/src/Range/AbstractRange.php +++ b/vendor/mlocati/ip-lib/src/Range/AbstractRange.php @@ -22,10 +22,18 @@ abstract class AbstractRange implements RangeInterface */ public function getRangeType() { + /** @var \IPLib\Range\Pattern|\IPLib\Range\Subnet $this */ + // @phpstan-ignore varTag.nativeType if ($this->rangeType === null) { $addressType = $this->getAddressType(); if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) { - $this->rangeType = Factory::getRangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType(); + $fromAddress = $this->fromAddress; + /** @var IPv6 $fromAddress */ + $toAddress = $this->toAddress; + /** @var IPv6 $toAddress */ + $range = Factory::getRangeFromBoundaries($fromAddress->toIPv4(), $toAddress->toIPv4()); + /** @var RangeInterface $range */ + $this->rangeType = $range->getRangeType(); } else { switch ($addressType) { case AddressType::T_IPv4: @@ -36,8 +44,6 @@ abstract class AbstractRange implements RangeInterface $defaultType = IPv6::getDefaultReservedRangeType(); $reservedRanges = IPv6::getReservedRanges(); break; - default: - throw new \Exception('@todo'); // @codeCoverageIgnore } $rangeType = null; foreach ($reservedRanges as $reservedRange) { @@ -62,23 +68,20 @@ abstract class AbstractRange implements RangeInterface { if (is_int($n)) { $positive = $n >= 0; - if ($positive === false) { - $nPlus1 = $n + 1; - } } elseif (($s = BinaryMath::getInstance()->normalizeIntegerString($n)) !== '') { $n = $s; $positive = $n[0] !== '-'; - if ($positive === false) { - $nPlus1 = BinaryMath::getInstance()->add1ToIntegerString($n); - } } else { return null; } if ($positive) { $start = Factory::parseAddressString($this->getComparableStartString()); + /** @var \IPLib\Address\AddressInterface $start */ $address = $start->getAddressAtOffset($n); } else { $end = Factory::parseAddressString($this->getComparableEndString()); + /** @var \IPLib\Address\AddressInterface $end */ + $nPlus1 = is_int($n) ? $n + 1 : BinaryMath::getInstance()->add1ToIntegerString($n); $address = $end->getAddressAtOffset($nPlus1); } @@ -156,15 +159,20 @@ abstract class AbstractRange implements RangeInterface if ($networkPrefix > $maxPrefix) { throw new OutOfBoundsException("The value of the \$networkPrefix parameter can't be larger than the maximum network prefix of the range ({$maxPrefix})"); } - if ($startIp instanceof IPv4) { - $one = IPv4::fromBytes(array(0, 0, 0, 1)); - } elseif ($startIp instanceof IPv6) { - $one = IPv6::fromBytes(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)); + switch ($startIp->getAddressType()) { + case AddressType::T_IPv4: + $one = IPv4::fromBytes(array(0, 0, 0, 1)); + break; + case AddressType::T_IPv6: + $one = IPv6::fromBytes(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)); + break; } + /** @var \IPLib\Address\AddressInterface $one */ $delta = $one->shift($networkPrefix - $maxPrefix); $result = array(); while (true) { $range = Subnet::parseString("{$startIp}/{$networkPrefix}"); + /** @var Subnet $range */ if (!$forceSubnet && $this instanceof Pattern) { $range = $range->asPattern() ?: $range; } diff --git a/vendor/mlocati/ip-lib/src/Range/Pattern.php b/vendor/mlocati/ip-lib/src/Range/Pattern.php index b14e744c..9b6b2eee 100644 --- a/vendor/mlocati/ip-lib/src/Range/Pattern.php +++ b/vendor/mlocati/ip-lib/src/Range/Pattern.php @@ -14,6 +14,8 @@ use IPLib\Service\BinaryMath; * * @example 127.0.*.* * @example ::/8 + * + * @phpstan-consistent-constructor */ class Pattern extends AbstractRange { @@ -106,10 +108,20 @@ class Pattern extends AbstractRange return null; } if ($range === '*.*.*.*') { - return new static(IPv4::parseString('0.0.0.0'), IPv4::parseString('255.255.255.255'), 4); + $fromAddress = IPv4::parseString('0.0.0.0'); + /** @var \IPLib\Address\IPv4 $fromAddress */ + $toAddress = IPv4::parseString('255.255.255.255'); + /** @var \IPLib\Address\IPv4 $toAddress */ + + return new static($fromAddress, $toAddress, 4); } if ($range === '*:*:*:*:*:*:*:*') { - return new static(IPv6::parseString('::'), IPv6::parseString('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 8); + $fromAddress = IPv6::parseString('::'); + /** @var \IPLib\Address\IPv6 $fromAddress */ + $toAddress = IPv6::parseString('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'); + /** @var \IPLib\Address\IPv6 $toAddress */ + + return new static($fromAddress, $toAddress, 8); } $matches = null; if (strpos($range, '.') !== false && preg_match('/^[^*]+((?:\.\*)+)$/', $range, $matches)) { @@ -128,6 +140,7 @@ class Pattern extends AbstractRange $fixedBytes = array_slice($fromAddress->getBytes(), 0, -$asterisksCount); $otherBytes = array_fill(0, $asterisksCount, 255); $toAddress = IPv4::fromBytes(array_merge($fixedBytes, $otherBytes)); + /** @var \IPLib\Address\IPv4 $toAddress */ return new static($fromAddress, $toAddress, $asterisksCount); } @@ -140,6 +153,7 @@ class Pattern extends AbstractRange $fixedWords = array_slice($fromAddress->getWords(), 0, -$asterisksCount); $otherWords = array_fill(0, $asterisksCount, 0xffff); $toAddress = IPv6::fromWords(array_merge($fixedWords, $otherWords)); + /** @var \IPLib\Address\IPv6 $toAddress */ return new static($fromAddress, $toAddress, $asterisksCount); } @@ -177,6 +191,7 @@ class Pattern extends AbstractRange $bytes = array_slice($bytes, 0, -$this->asterisksCount * 2); $bytes = array_pad($bytes, 16, 1); $address = IPv6::fromBytes($bytes); + /** @var IPv6 $address */ $before = substr($address->toString(false), 0, -strlen(':101') * $this->asterisksCount); $result = $before . str_repeat(':*', $this->asterisksCount); } diff --git a/vendor/mlocati/ip-lib/src/Range/RangeInterface.php b/vendor/mlocati/ip-lib/src/Range/RangeInterface.php index 4b27cd18..78468218 100644 --- a/vendor/mlocati/ip-lib/src/Range/RangeInterface.php +++ b/vendor/mlocati/ip-lib/src/Range/RangeInterface.php @@ -31,13 +31,15 @@ interface RangeInterface * Get the type of the IP addresses contained in this range. * * @return int One of the \IPLib\Address\Type::T_... constants + * + * @phpstan-return \IPLib\Address\Type::T_IPv4|\IPLib\Address\Type::T_IPv6 */ public function getAddressType(); /** * Get the type of range of the IP address. * - * @return int One of the \IPLib\Range\Type::T_... constants + * @return int|null One of the \IPLib\Range\Type::T_... constants, or null if this range crosses multiple range types * * @since 1.5.0 */ @@ -46,7 +48,7 @@ interface RangeInterface /** * Get the address at a certain offset of this range. * - * @param int|numeric-string $n the offset of the address (support negative offset) + * @param int|numeric-string|mixed $n the offset of the address (support negative offset) * * @return \IPLib\Address\AddressInterface|null return NULL if $n is neither an integer nor a string containing a valid integer, or if the offset out of range * diff --git a/vendor/mlocati/ip-lib/src/Range/Single.php b/vendor/mlocati/ip-lib/src/Range/Single.php index bcc6960a..8d5973f8 100644 --- a/vendor/mlocati/ip-lib/src/Range/Single.php +++ b/vendor/mlocati/ip-lib/src/Range/Single.php @@ -13,6 +13,8 @@ use IPLib\ParseStringFlag; * * @example 127.0.0.1 * @example ::1 + * + * @phpstan-consistent-constructor */ class Single extends AbstractRange { diff --git a/vendor/mlocati/ip-lib/src/Range/Subnet.php b/vendor/mlocati/ip-lib/src/Range/Subnet.php index 4dcbb54c..e6e7f3d7 100644 --- a/vendor/mlocati/ip-lib/src/Range/Subnet.php +++ b/vendor/mlocati/ip-lib/src/Range/Subnet.php @@ -14,6 +14,8 @@ use IPLib\Service\BinaryMath; * * @example 127.0.0.1/32 * @example ::/8 + * + * @phpstan-consistent-constructor */ class Subnet extends AbstractRange { @@ -146,15 +148,15 @@ class Subnet extends AbstractRange $startSameBits = $networkPrefix % 8; if ($startSameBits !== 0) { $varyingByte = $addressBytes[$numSameBytes]; - $differentBytesStart[0] = $varyingByte & bindec(str_pad(str_repeat('1', $startSameBits), 8, '0', STR_PAD_RIGHT)); - $differentBytesEnd[0] = $differentBytesStart[0] + bindec(str_repeat('1', 8 - $startSameBits)); + $differentBytesStart[0] = $varyingByte & (int) bindec(str_pad(str_repeat('1', $startSameBits), 8, '0', STR_PAD_RIGHT)); + $differentBytesEnd[0] = $differentBytesStart[0] + (int) bindec(str_repeat('1', 8 - $startSameBits)); } + $fromAddress = Factory::addressFromBytes(array_merge($sameBytes, $differentBytesStart)); + /** @var \IPLib\Address\AddressInterface $fromAddress */ + $toAddress = Factory::addressFromBytes(array_merge($sameBytes, $differentBytesEnd)); + /** @var \IPLib\Address\AddressInterface $toAddress */ - return new static( - Factory::addressFromBytes(array_merge($sameBytes, $differentBytesStart)), - Factory::addressFromBytes(array_merge($sameBytes, $differentBytesEnd)), - $networkPrefix - ); + return new static($fromAddress, $toAddress, $networkPrefix); } /** @@ -255,7 +257,9 @@ class Subnet extends AbstractRange public static function get6to4() { if (self::$sixToFour === null) { - self::$sixToFour = self::parseString('2002::/16'); + $subnet = self::parseString('2002::/16'); + /** @var Subnet $subnet */ + self::$sixToFour = $subnet; } return self::$sixToFour; @@ -327,10 +331,11 @@ class Subnet extends AbstractRange $result = array(); $unitsToRemove = $maxUnits - $prefixUnits; $initialPointer = preg_replace("/^(({$rxUnit})\.){{$unitsToRemove}}/", '', $this->getStartAddress()->getReverseDNSLookupName()); + /** @var string $initialPointer */ $chunks = explode('.', $initialPointer, 2); for ($index = 0; $index < $numVariants; $index++) { if ($index !== 0) { - $chunks[0] = $isHex ? dechex(1 + hexdec($chunks[0])) : (string) (1 + (int) $chunks[0]); + $chunks[0] = $isHex ? dechex(1 + (int) hexdec($chunks[0])) : (string) (1 + (int) $chunks[0]); } $result[] = implode('.', $chunks); } diff --git a/vendor/mlocati/ip-lib/src/Range/Type.php b/vendor/mlocati/ip-lib/src/Range/Type.php index 9c1b290f..20d96753 100644 --- a/vendor/mlocati/ip-lib/src/Range/Type.php +++ b/vendor/mlocati/ip-lib/src/Range/Type.php @@ -110,7 +110,7 @@ class Type /** * Get the name of a type. * - * @param int $type + * @param int|mixed $type * * @return string */ @@ -146,7 +146,7 @@ class Type case static::T_CGNAT: return 'Carrier-grade NAT'; default: - return $type === null ? 'Unknown type' : sprintf('Unknown type (%s)', $type); + return $type === null ? 'Unknown type' : sprintf('Unknown type (%s)', print_r($type, true)); } } } diff --git a/vendor/mlocati/ip-lib/src/Service/BinaryMath.php b/vendor/mlocati/ip-lib/src/Service/BinaryMath.php index 30bb94b6..fe762c9c 100644 --- a/vendor/mlocati/ip-lib/src/Service/BinaryMath.php +++ b/vendor/mlocati/ip-lib/src/Service/BinaryMath.php @@ -9,6 +9,9 @@ namespace IPLib\Service; */ class BinaryMath { + /** + * @var \IPLib\Service\BinaryMath|null + */ private static $instance; /** @@ -119,7 +122,7 @@ class BinaryMath * * @param int $exponent The non-negative exponent * - * @return int|string + * @return int|numeric-string */ public function pow2string($exponent) { @@ -138,14 +141,16 @@ class BinaryMath $digits[] = $carry; } } + $result = implode('', array_reverse($digits)); + /** @var numeric-string $result */ - return implode('', array_reverse($digits)); + return $result; } /** * @param numeric-string|mixed $value * - * @return string empty string if $value is not a valid numeric string + * @return numeric-string|'' empty string if $value is not a valid numeric string */ public function normalizeIntegerString($value) { @@ -160,14 +165,19 @@ class BinaryMath if (!preg_match('/^0*([0-9]+)$/', $value, $matches)) { return ''; } + $numericString = $matches[1]; + if ($sign === '-' && $numericString !== '0') { + $numericString = '-' . $numericString; + } + /** @var numeric-string $numericString */ - return ($sign === '-' && $matches[1] !== '0' ? $sign : '') . $matches[1]; + return $numericString; } /** * @param numeric-string $value a string that has been normalized with normalizeIntegerString() * - * @return string + * @return numeric-string */ public function add1ToIntegerString($value) { @@ -189,8 +199,10 @@ class BinaryMath if ($imploded[0] === '0') { $imploded = substr($imploded, 1); } + $result = '-' . $imploded; + /** @var numeric-string $result */ - return '-' . $imploded; + return $result; // @phpstan-ignore varTag.nativeType } $digits = str_split($value); $carry = 1; @@ -205,8 +217,10 @@ class BinaryMath array_unshift($digits, (string) $carry); } } + $result = implode('', $digits); + /** @var numeric-string $result */ - return implode('', $digits); + return $result; } /** @@ -215,7 +229,7 @@ class BinaryMath * @param string $num1 * @param string $num2 * - * @return string[],int[] The first array element is $num1 (padded), the first array element is $num2 (padded), the third array element is the number of bits + * @return array{string, string, int} The first array element is $num1 (padded), the first array element is $num2 (padded), the third array element is the number of bits */ private function toSameLength($num1, $num2) { diff --git a/vendor/mlocati/ip-lib/src/Service/NumberInChunks.php b/vendor/mlocati/ip-lib/src/Service/NumberInChunks.php index 67fc6e80..21762086 100644 --- a/vendor/mlocati/ip-lib/src/Service/NumberInChunks.php +++ b/vendor/mlocati/ip-lib/src/Service/NumberInChunks.php @@ -88,7 +88,8 @@ class NumberInChunks $negative = $int < 0; if ($negative) { $positiveInt = -$int; - if (is_float($positiveInt)) { // -PHP_INT_MIN is bigger than PHP_INT_MAX + /** @var int|float $positiveInt may be float because -PHP_INT_MIN is bigger than PHP_INT_MAX */ + if (is_float($positiveInt)) { return self::fromNumericString((string) $int, $chunkSize); } $int = $positiveInt; @@ -197,7 +198,7 @@ class NumberInChunks * @param int[] $subtrahend * @param int $chunkSize * - * @return array + * @return array{bool, int[]} */ private static function substractChunks(array $minuend, array $subtrahend, $chunkSize) { diff --git a/vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php b/vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php index f26e94b6..4eaeb4e4 100644 --- a/vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php +++ b/vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php @@ -80,6 +80,8 @@ class RangesFromBoundaryCalculator * Set the number of bits used to represent addresses (32 for IPv4, 128 for IPv6). * * @param int $numBits + * + * @return void */ private function setNumBits($numBits) { @@ -102,6 +104,8 @@ class RangesFromBoundaryCalculator * @param string $end the end address (represented in reduced bit form) * @param int $position the number of bits in the mask we are comparing at this cycle * @param \IPLib\Range\Subnet[] $result found ranges will be added to this variable + * + * @return void */ private function calculate($start, $end, $position, array &$result) { @@ -110,6 +114,7 @@ class RangesFromBoundaryCalculator return; } + $startMasked = ''; for ($index = $position - 1; $index >= 0; $index--) { $startMasked = $this->math->andX($start, $this->masks[$index]); $endMasked = $this->math->andX($end, $this->masks[$index]); @@ -140,10 +145,12 @@ class RangesFromBoundaryCalculator $bits = str_pad($bits, $this->numBits, '0', STR_PAD_LEFT); $bytes = array(); foreach (explode("\n", trim(chunk_split($bits, 8, "\n"))) as $byteBits) { - $bytes[] = bindec($byteBits); + $bytes[] = (int) bindec($byteBits); } + $result = Factory::addressFromBytes($bytes); + /** @var AddressInterface $result */ - return Factory::addressFromBytes($bytes); + return $result; } /** diff --git a/vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php b/vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php index 3179f746..03dd5ea2 100644 --- a/vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php +++ b/vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php @@ -67,6 +67,7 @@ class UnsignedIntegerMath $value = str_pad($value, $valueLength + 8 - $remainderBits, '0', STR_PAD_LEFT); } $bytes = array_map('bindec', str_split($value, 8)); + /** @var int[] $bytes */ return array_pad($bytes, -$numBytes, 0); } @@ -86,14 +87,14 @@ class UnsignedIntegerMath '', array_map( function ($octalDigit) { - return str_pad(decbin(octdec($octalDigit)), 3, '0', STR_PAD_LEFT); + return str_pad(decbin((int) octdec($octalDigit)), 3, '0', STR_PAD_LEFT); }, str_split($value, 1) ) ); $bits = ltrim($bits, '0'); - return $bits === '' ? array_fill(0, $numBytes, 0) : static::getBytesFromBits($bits, $numBytes); + return $bits === '' ? array_fill(0, $numBytes, 0) : self::getBytesFromBits($bits, $numBytes); } /** @@ -165,6 +166,7 @@ class UnsignedIntegerMath } $value = str_pad($value, $valueLength + $valueLength % 2, '0', STR_PAD_LEFT); $bytes = array_map('hexdec', str_split($value, 2)); + /** @var int[] $bytes */ return array_pad($bytes, -$numBytes, 0); } diff --git a/vendor/symfony/polyfill-php80/Php80.php b/vendor/symfony/polyfill-php80/Php80.php index 362dd1a9..68fac391 100644 --- a/vendor/symfony/polyfill-php80/Php80.php +++ b/vendor/symfony/polyfill-php80/Php80.php @@ -60,7 +60,7 @@ final class Php80 public static function get_resource_id($res): int { if (!\is_resource($res) && null === @get_resource_type($res)) { - throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); + throw new \TypeError(\sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); } return (int) $res; diff --git a/vendor/symfony/polyfill-php80/PhpToken.php b/vendor/symfony/polyfill-php80/PhpToken.php index fe6e6910..cd78c4cc 100644 --- a/vendor/symfony/polyfill-php80/PhpToken.php +++ b/vendor/symfony/polyfill-php80/PhpToken.php @@ -29,7 +29,7 @@ class PhpToken implements \Stringable public $text; /** - * @var int + * @var -1|positive-int */ public $line; @@ -38,6 +38,9 @@ class PhpToken implements \Stringable */ public $pos; + /** + * @param -1|positive-int $line + */ public function __construct(int $id, string $text, int $line = -1, int $position = -1) { $this->id = $id; @@ -80,7 +83,7 @@ class PhpToken implements \Stringable } /** - * @return static[] + * @return list */ public static function tokenize(string $code, int $flags = 0): array {