url-sanitizer 5.3.5 → 5.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/dist/url-sanitizer-wo-dompurify.min.js +1 -1
- package/dist/url-sanitizer-wo-dompurify.min.js.map +2 -2
- package/dist/url-sanitizer.min.js +2 -2
- package/dist/url-sanitizer.min.js.map +2 -2
- package/package.json +10 -6
- package/src/lib/iana/uri-schemes.json +1 -1
- package/src/mjs/constant.js +1 -1
- package/src/mjs/filter.js +2 -2
- package/src/mjs/sanitize.js +5 -3
package/README.md
CHANGED
|
@@ -441,10 +441,6 @@ This strict blocking prevents non-existent or hallucinated schemes from inadvert
|
|
|
441
441
|
|
|
442
442
|
Execution times were measured using [mitata](https://github.com/evanwashere/mitata) on Node.js.
|
|
443
443
|
|
|
444
|
-
## Performance
|
|
445
|
-
|
|
446
|
-
Execution times were measured using [mitata](https://github.com/evanwashere/mitata) on Node.js.
|
|
447
|
-
|
|
448
444
|
### Benchmark Results
|
|
449
445
|
|
|
450
446
|
| URL Type | `url-sanitizer` | [@braintree/sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) | [strict-url-sanitise](https://www.npmjs.com/package/strict-url-sanitise) |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var M="http://dummy.local",w={allow:Object.freeze([]),deny:Object.freeze([]),only:Object.freeze([]),allowRelative:!1,debug:!1,revokeObjectURL:!1,maxBlobSize:16777216,maxLength:65536,schemes:new Set};var y=n=>Object.prototype.toString.call(n).slice(8,-1),p=n=>typeof n=="string"||n instanceof String,h=(n,e)=>{console.warn(`[URLSanitizer Debug] ${n}`,e)};var ue=Object.freeze(["addHook","removeHook","removeAllHooks","setConfig"]),T=[],S=new Proxy({},{get(n,e,t){let s=globalThis.DOMPurify||globalThis.window?.DOMPurify;if(s){if(T.length){for(let{prop:o,args:a}of T)typeof s[o]=="function"&&s[o](...a);T.length=0}let r=s[e];return typeof r=="function"?r.bind(s):r}return(...r)=>{if(ue.includes(e))return T.push({prop:e,args:r}),t;throw new Error("DOMPurify is not available. Ensure DOMPurify is exposed globally (e.g., window.DOMPurify).")}}});var H=/&/gi,j=/&(?=[#a-z0-9])(?![a-z0-9]+=)/i;var F=/#$/,X=/^(?:application\/(?:[\w.-]+\+)?xml|image\/svg\+xml|text\/(?:html|xml))(?:\s*;\s*|$)/i;var V=/\P{ASCII}/u,Y=/&#(x0*[\dA-F]{1,2}|0*\d{1,3});?/gi,q=/(?:%[\dA-F]{2})+/gi,Q=/^((?:[^#%]|%(?!23))*)\?$/,A=/^[a-z][\da-z+.-]*$/,W=/^(?:web\+[a-z]+|ext\+[a-z][\da-z.-]*)$/,R=/^(?:java|vb)script$/i,_=/^(?:(?:java|vb)script|blob)$/i,k=/["'<>]|%(?:22|27|3C|3E)|&(?:apos|lt|gt|quot|#0*(?:34|39|60|62)|#x0*(?:22|27|3C|3E));/i,Z=/^%[\dA-F]{2}$/i,K=/^(?:\/{2,}|\\|[a-z][a-z\d+\-.]*:[^/])/i;var J=[9,10,13,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];var P=new Set(J),B=new Map([[128,8364],[130,8218],[131,402],[132,8222],[133,8230],[134,8224],[135,8225],[136,710],[137,8240],[138,352],[139,8249],[140,338],[142,381],[145,8216],[146,8217],[147,8220],[148,8221],[149,8226],[150,8211],[151,8212],[152,732],[153,8482],[154,353],[155,8250],[156,339],[158,382],[159,376]]),ge=()=>{let n=new Map;for(let e=0;e<256;e++)!P.has(e)&&!B.has(e)&&n.set(e,`\\x${e.toString(16).padStart(2,"0").toUpperCase()}`);return n},G=ge();var[E,Re,ye,Ee,xe,we]=["&","#","<",">",'"',"'"].map(n=>`%${n.charCodeAt(0).toString(16).toUpperCase()}`),_e={[E]:`${E}amp;`,[ye]:`${E}lt;`,[Ee]:`${E}gt;`,[xe]:`${E}quot;`,[we]:`${E}${Re}39;`},Xe=Array.from({length:256},(n,e)=>`%${e.toString(16).padStart(2,"0").toUpperCase()}`),ne=globalThis.process?.versions?.node!==void 0,oe=`[${[...G.values()].join("")}]`,Ue=new RegExp(oe),Le=new RegExp(oe,"g"),Te=new Uint8Array(65536),Ve=new TextEncoder,Se=new TextDecoder("utf-8",{fatal:!0}),f=(n,e=!1)=>{if(!p(n))return null;let t=V.test(n)?n.normalize("NFKC"):n;return e?t.trim().toLowerCase().replace(/:$/,""):t},d=(n,e,t=!1)=>{if(!p(n)||n==="")return null;let s=n,r=e&&p(e)?e:"";if(t&&(s=f(s),r&&(r=f(r))),typeof URL.parse=="function")return r?URL.parse(s,r):URL.parse(s);try{return r?new URL(s,r):new URL(s)}catch{return null}},ae=n=>p(n)?n.replace(/:$/,"").split("+"):[];var ie=n=>{if(!p(n))return n;let e=Z.test(n)?n.toUpperCase():n;return _e[e]??n},u=n=>{let e=p(n)?n:String(n);return e.length>64?`${e.slice(0,64)}...`:e},ce=n=>p(n)?n.replace(F,"").replace(Q,"$1"):n,Ae=(n,e)=>{let t=/^x/i.test(e)?Number.parseInt(e.slice(1),16):Number.parseInt(e,10);if(!Number.isInteger(t)||t<0||t>=256)return n;if(G.has(t))return"";if(P.has(t))return String.fromCharCode(t);let s=B.get(t);return String.fromCodePoint(s)},le=(n,e=0)=>{if(!p(n))throw new TypeError(`Expected String but got ${y(n)}.`);if(!Number.isInteger(e))throw new TypeError(`Expected Number but got ${y(e)}.`);let t;try{t=decodeURIComponent(n)}catch{t=n.replace(q,r=>{try{return decodeURIComponent(r)}catch{return r}})}t=t.replace(Le,"");let s=0;for(;s+e<16;s++){let r=t;if(t=t.replace(H,"&").replace(Y,Ae),t===r)break}if(s+e>=16&&/&#/.test(t))throw new Error("Character references nested too deeply.");return t},O=(n,e="",t="")=>{if(!p(n))return{mediaType:"",mediaTypes:[],data:"",isBase64:!1};let s=n.indexOf(",");if(s===-1)return{mediaType:n,mediaTypes:n.split(";"),data:"",isBase64:!1};let r=n.substring(0,s),o=n.substring(s+1),a=e===""&&t===""?o:o+e+t,c=r.split(";"),i=c.at(-1),l=i!==void 0&&i.length===6&&i.toLowerCase()==="base64";return{mediaType:r,mediaTypes:c,data:a,isBase64:l}},pe=n=>{if(!p(n))throw new TypeError(`Expected String but got ${y(n)}.`);let e,t=n;try{e=atob(n)}catch{t=n.replace(/\s/g,"");try{e=atob(t)}catch{throw new Error(`Invalid base64 data: ${u(n)}`)}}let s;if(ne&&globalThis.Buffer)s=globalThis.Buffer.from(e,"latin1");else{let r=e.length;r>65536?s=new Uint8Array(r):s=Te.subarray(0,r);for(let o=0;o<r;o++)s[o]=e.charCodeAt(o)}try{let r=Se.decode(s);return Ue.test(r)?t:r}catch{return t}},z=n=>{if(ne&&globalThis.Buffer)return globalThis.Buffer.from(n).toString("base64");let e=new Uint8Array(n);if(typeof e.toBase64=="function")return e.toBase64();let t=[];for(let s=0;s<e.length;s+=8192)t.push(String.fromCharCode(...e.subarray(s,s+8192)));return btoa(t.join(""))},ve=async(n,e,t)=>{let s=n.body.getReader(),r=[],o="Operation aborted";if(t?.aborted)throw await s.cancel(o),s.releaseLock(),t.reason;let a=()=>{s.cancel(o).catch(()=>{})};t?.addEventListener("abort",a,{once:!0});try{let c=0;for(;c<=e;){if(t?.aborted)throw await s.cancel(o),t.reason;let{done:m,value:b}=await s.read();if(t?.aborted)throw t.reason;if(m)break;if(c+=b.byteLength,c>e)throw await s.cancel("Size limit exceeded"),new DOMException(`Payload (${c} bytes) exceeds max (${e} bytes).`,"NotReadableError");r.push(b)}let i=new Uint8Array(c),l=0;for(let m of r)i.set(m,l),l+=m.byteLength;return i.buffer}finally{t?.removeEventListener("abort",a),s.releaseLock()}},D=async(n,e,t)=>{let s=16777216;Number.isInteger(e)&&e>0&&(s=e);let r=await fetch(n,{signal:t});if(!r.ok){let l=`Failed to fetch ${u(n)}`;throw Number.isInteger(r.status)&&(r.statusText?l+=`: ${r.status} ${r.statusText}`:l+=`: ${r.status}`),new Error(l)}let o=r.headers.get("content-length");if(o){let i=Number.parseInt(o,10);if(Number.isInteger(i)&&i>s)throw new DOMException(`Payload (${i} bytes) exceeds max (${s} bytes).`,"NotReadableError")}let a=r.headers.get("content-type")||"",c;if(r.body)c=await ve(r,s,t);else{let i=await r.blob();if(i.size>s)throw new DOMException(`Payload (${i.size} bytes) exceeds max (${s} bytes).`,"NotReadableError");c=await i.arrayBuffer()}return{buffer:c,mimeType:a}};var L=class{constructor(e,t=w){this.domPurify=e,this.nest=0,this.recurse=new Set,this.restrictScheme=!1,this.schemeMap=new Map([["blob",!1],["data",!1],["file",!1],["javascript",!1],["vbscript",!1]]),this.#e(t)}#e(e){let{allowRelative:t,debug:s,allow:r,deny:o,only:a,schemes:c}=e;if(this.allowRelative=!!t,this.debug=!!s,this.schemes=c,Array.isArray(a)&&a.length){this.restrictScheme=!0;for(let i of a)this.#s(i)}else{if(Array.isArray(r)&&r.length)for(let i of r)this.#s(i);if(Array.isArray(o)&&o.length)for(let i of o){let l=f(i,!0);l&&this.schemeMap.set(l,!1)}}}#s(e){let t=f(e,!0);return!t||_.test(t)||!A.test(t)||t.includes("+")&&t.split("+").some(r=>R.test(r))?!1:(this.schemeMap.set(t,!0),!0)}enter(e){return this.recurse.has(e)?(this.debug&&h(`Circular Data URL detected and skipped: ${u(e)}`),!1):(this.nest++,this.recurse.add(e),!0)}leave(e){this.nest--,this.recurse.delete(e)}},N=class{#e;constructor(e=w){this.#e=e}#s(e,t){if(t.nest>16)throw new Error("Data URLs nested too deeply.");let s=d(e,null,!0);if(!s){if(t.allowRelative&&!K.test(e)){let o=d(e,M);if(o){let{protocol:a,hostname:c,pathname:i,search:l,hash:m}=o;if(a==="http:"&&c==="dummy.local")return this.#n(`${i}${l}${m}`)}}return null}let r=f(s.protocol,!0);if(t.restrictScheme&&!t.schemeMap.has(r))return null;if(r.includes("+")){let o=r.split("+");if(t.schemeMap.get(r)===!1||o.some(a=>t.schemeMap.get(a)===!1))return null}else if(t.schemeMap.has(r)){if(t.schemeMap.get(r)===!1)return null}else if(!t.schemes.has(r))return null;return r==="data"?this.#t(s,t):this.#n(s.href)}#t(e,t){let{mediaType:s,mediaTypes:r,data:o,isBase64:a}=O(e.pathname,e.search,e.hash),c=o;if(a)try{c=pe(o)}catch(i){return t.debug&&h("Failed to parse base64 data.",i),null}try{let i=le(c).trim(),l=d(i,M);if(!l||ae(l.protocol).some(b=>_.test(b)))return null}catch(i){return t.debug&&h("Failed to parse inner data URL protocol.",i),null}return(!s||X.test(s))&&(c=this.#o(c,t)),c?(a&&c!==o&&r.pop(),`data:${r.join(";")},${c}`):null}#o(e,t){let s="";try{s=decodeURIComponent(e)}catch{s=e}let r=(a,c)=>this.#r(a,c,t),o="";try{t.domPurify.addHook("uponSanitizeAttribute",r),o=t.domPurify.sanitize(s)}finally{t.domPurify.removeHook("uponSanitizeAttribute",r)}if(!o)return null;try{return encodeURI(ce(o))}catch{return null}}#r(e,t,s){if(!t.attrValue||!/^\s*data:/i.test(t.attrValue))return;let r=d(t.attrValue,null,!0);if(!r||r.protocol!=="data:")return;let o=t.attrValue;if(!s.enter(o)){t.attrValue="";return}try{let a=this.#s(o,s);t.attrValue=a||""}finally{s.leave(o)}}#n(e){let t=e.length,s=t,r=k.exec(e);if(r&&(s=r.index),e.indexOf("&")>-1){let a=j.exec(e);if(a){let c=a.index;c<s&&(s=c)}}if(s===t)return e;let o=e.charCodeAt(s-1);return(o===63||o===38)&&s--,e.substring(0,s)}sanitize(e,t=this.#e){if(!e||!p(e))return null;let{deny:s,maxLength:r,only:o,allowRelative:a}=t;if(Number.isInteger(r)&&e.length>r){let l=`URL length ${e.length} exceeds max length ${r}.`;throw new RangeError(l)}if(!(Array.isArray(s)&&s.length>0||Array.isArray(o)&&o.length>0||a)&&/^https?:\/\//.test(e)&&!k.test(e)&&!e.includes("data:")){let l=d(e,null,!0);return l&&t.schemes.has(l.protocol.replace(/:$/,""))?l.href.replace(/%26/g,ie):null}let i=new L(S,t);return this.#s(e,i)}async sanitizeBuffer(e,t,s=this.#e){if(!(e instanceof ArrayBuffer))return null;let r=z(e),a=`data:${t?`${t};base64`:"base64"},${r}`;if(Number.isInteger(s.maxLength)&&a.length>s.maxLength)throw new RangeError(`URL length ${a.length} exceeds max length ${s.maxLength}.`);let c=new L(S,s);if(!c.schemeMap.get("data"))return null;let i=d(a);return i?this.#t(i,c):null}async sanitizeDataURL(e,t=this.#e){if(!e||!p(e))return null;let{maxLength:s}=t;if(Number.isInteger(s)&&e.length>s)throw new RangeError(`URL length ${e.length} exceeds max length ${s}.`);let r=d(e);if(!r)return null;let o=f(r.protocol,!0);if(o!=="data")return null;let a=new L(S,t);return a.schemeMap.get(o)?this.#t(r,a):null}};var me=["aaa","aaas","about","acap","acct","acd","ace","aceap","acedp","aceep","acelp","aceup","acr","adiumxtra","adt","aet","afp","afs","agtp","aim","alter","amss","android","appdata","apt","ar","ari","ark","ars","arv","at","attachment","aw","barion","beshare","bitcoin","bitcoincash","bl","blob","bluetooth","bolo","brid","browserext","cabal","caip","calculator","callto","canactid","cap","cast","casts","chrome","chrome-extension","cid","cm","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cttps","cvs","dab","dat","data","dav","dhttp","diaspora","dict","did","dilithium3","dis","dlna-playcontainer","dlna-playsingle","dnp","dns","dntp","doi","donau","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","esim","ethereum","example","ez","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","gcx","gdsi","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gsos","gtalk","h323","ham","hcap","hcp","hs20","http","https","hxxp","hxxps","hydrazone","hyper","i0","iax","ibi","ibi-","icap","icon","ilstring","im","imap","info","interaction","iotdisco","ipfs","ipn","ipns","ipp","ipps","iqa","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lid","linkid","locus","lorawan","lpa","lvlt","machineProvisioningProgressReporter","magnet","mailto","maps","market","matrix","mdoc","mdoc-openid4vp","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","mqtt","mqtts","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-launchremotedesktop","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-personacard","ms-powerpoint","ms-project","ms-publisher","ms-recall","ms-remotedesktop","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-uup","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-widgetboard","ms-widgets","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mtrust","mumble","mupdate","musik","mvn","mvrp","mvrps","news","nfs","ni","nih","nntp","nostr","notes","npamp","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openid","openpgp4fpr","opns","ord","ordmail","otpauth","palm","paparazzi","payto","pkcs11","pkg","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","rttp","sarif","secondlife","secret-token","seki","service","session","sftp","sgn","shc","shelter","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","sns","soap.beep","soap.beeps","soldat","spacify","spiffe","spotify","ssb","ssh","sss","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","tcxp","teamspeak","teapot","teapots","tel","teliaeid","telnet","tftp","things","thismessage","tii","tip","tn3270","tool","tttps","turn","turns","tv","udp","unreal","upn","urn","ust","ut2004","uuaid","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wasm","wasm-js","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcompute","xcon","xcon-userid","xfire","xftp","xmlrpc.beep","xmlrpc.beeps","xmpp","xrcp","xri","ymsgr","z39.50r","z39.50s","ztdnaid"];var $=class{#e=new Set(me);get(){return[...this.#e]}getScheme(e){if(!p(e))return null;let t=this.parse(e);return t?this.normalize(t.protocol,!0):null}has(e){let t=this.normalize(e,!0);return t?this.#e.has(t):!1}normalize(e,t=!1){return f(e,t)}normalizeSchemes(e){if(Array.isArray(e)){let t=[];for(let s of e){let r=f(s,!0);r&&t.push(r)}return t}return[]}parse(e,t,s=!1){return d(e,t,s)}verifyURI(e,t){if(!p(e))return!1;let s=this.parse(e);return s?this.verifyScheme(s.protocol,t,!0):!1}verifyScheme(e,t,s=!1){let r=this.normalize(e,!0);if(!r)return!1;let o=t||this.#e;if(!r.includes("+"))return R.test(r)?!1:o.has(r);let a=r.split("+");return a.some(i=>R.test(i))?!1:o.has(r)?!0:s&&W.test(r)||a.every(i=>o.has(i))}};var Oe=Object.freeze(["href","origin","protocol","username","password","host","hostname","port","pathname","search","hash"]),I=class extends ${#e;#s;#t;constructor(){super(),this.#e=new Set(super.get()),this.#s={...w,schemes:this.#e},this.#t=new N(this.#s)}#o(e){return!p(e)||_.test(e)||e.includes("+")&&e.split("+").some(s=>R.test(s))?!1:A.test(e)}#r(e,t={}){if(!p(e)||e==="")return{isValid:!1};let s={...this.#s,...t,allow:this.normalizeSchemes(t.allow),deny:this.normalizeSchemes(t.deny),only:this.normalizeSchemes(t.only),schemes:this.#e},r=this.getScheme(e);return r===null&&!s.allowRelative?{isValid:!1}:{options:s,scheme:r}}#n(e,t){let s={input:e,href:null,valid:!1};if(!p(e))return s.reason=`Invalid URL input: ${u(e)}`,s;if(e==="")return s.reason="Invalid URL input: (empty string)",s;let r,o=null;try{r=this.#t.sanitize(e,t),r||(o="Sanitization failed (blocked by allowed schemes or rules).")}catch(a){o=a.message}if(r){let a=d(r);if(s.valid=!0,a){if(f(a.protocol,!0)==="data"){let{mediaTypes:i,data:l,isBase64:m}=O(a.pathname,a.search,a.hash);m&&i.pop(),s.data={mime:i.join(";"),base64:m,data:l}}else s.data=null;for(let i of Oe){let l=a[i];p(l)&&(s[i]=l)}}else s.valid=!1,s.relative=!0,s.href=r,s.reason="Invalid as an absolute URL, but valid as a relative URL."}else s.reason=o;return s}async#i(e,t){try{let{buffer:s,mimeType:r}=await D(e,t.maxBlobSize,t.signal),o=z(s),a=`data:${r?`${r};base64`:"base64"},${o}`,c=this.#n(a,t);return c.input=e,c}catch(s){if(s.name==="AbortError"||t.signal?.aborted)throw s;return t.debug&&h(`Failed to inspect blob URL: ${u(e)}`,s),{input:e,valid:!1,reason:s.message}}finally{t.revokeObjectURL&&URL.revokeObjectURL(e)}}#a(e,t){if(e instanceof TypeError||e.name==="AbortError"||t.signal?.aborted)throw e}get(){return[...this.#e]}has(e){let t=f(e,!0);return t?this.#e.has(t):!1}add(e){if(!p(e))throw new TypeError(`Expected String but got ${y(e)}.`);let t=f(e,!0);if(!this.#o(t))throw new Error(`Invalid scheme: ${e}`);return this.#e.add(t),[...this.#e]}remove(e){if(!p(e))return!1;let t=f(e,!0);return this.#e.delete(t)}reset(){this.#e.clear();for(let e of super.get())this.#e.add(e)}async sanitizeURL(e,t){let{isValid:s,options:r,scheme:o}=this.#r(e,t);if(s===!1)return null;if(o==="blob"){let{allow:a,deny:c,only:i}=r,l=null;try{if(a.includes("blob")&&!c.includes("blob")||i.includes("blob")){let m=null,b="";try{let g=await D(e,r.maxBlobSize,r.signal);m=g.buffer,b=g.mimeType}catch(g){if(g.name==="AbortError"||r.signal?.aborted)throw g;r.debug&&h(`Failed to fetch and convert blob URL: ${u(e)}`,g)}m&&(i.length?i.includes("data")||(r.only=[...i,"data"]):(a.includes("data")||(r.allow=[...a,"data"]),r.deny=c.filter(g=>g!=="data")),l=await this.#t.sanitizeBuffer(m,b,r))}}catch(m){return this.#a(m,r),r.debug&&h(`Failed to sanitize URL: ${u(e)}`,m),null}finally{r.revokeObjectURL&&URL.revokeObjectURL(e)}return l}try{return o==="data"?this.#t.sanitizeDataURL(e,r):this.#t.sanitize(e,r)}catch(a){return this.#a(a,r),r.debug&&h(`Failed to sanitize URL: ${u(e)}`,a),null}}sanitizeURLSync(e,t){let{isValid:s,options:r,scheme:o}=this.#r(e,t);if(s===!1)return null;if(o==="blob")return r.revokeObjectURL&&URL.revokeObjectURL(e),null;try{return this.#t.sanitize(e,r)}catch(a){return this.#a(a,r),r.debug&&h(`Failed to sanitize URL: ${u(e)}`,a),null}}async inspectURL(e,t={}){let{options:s,scheme:r}=this.#r(e,t);return r==="blob"?this.#i(e,s):this.#n(e,s)}isValidURI(e){return super.verifyURI(e,this.#e)}};var x=new I,ut=async(n,e)=>x.sanitizeURL(n,e),ht=(n,e)=>x.sanitizeURLSync(n,e),gt=async(n,e={})=>x.inspectURL(n,e),bt=n=>x.isValidURI(n),Rt=n=>x.isValidURI(n),yt=x;export{I as URLSanitizer,yt as default,gt as inspectURL,Rt as isURISync,bt as isValidURI,ut as sanitizeURL,ht as sanitizeURLSync};
|
|
1
|
+
var M="http://dummy.local",w={allow:Object.freeze([]),deny:Object.freeze([]),only:null,allowRelative:!1,debug:!1,revokeObjectURL:!1,maxBlobSize:16777216,maxLength:65536,schemes:new Set};var y=n=>Object.prototype.toString.call(n).slice(8,-1),p=n=>typeof n=="string"||n instanceof String,h=(n,e)=>{console.warn(`[URLSanitizer Debug] ${n}`,e)};var ue=Object.freeze(["addHook","removeHook","removeAllHooks","setConfig"]),T=[],S=new Proxy({},{get(n,e,t){let s=globalThis.DOMPurify||globalThis.window?.DOMPurify;if(s){if(T.length){for(let{prop:o,args:a}of T)typeof s[o]=="function"&&s[o](...a);T.length=0}let r=s[e];return typeof r=="function"?r.bind(s):r}return(...r)=>{if(ue.includes(e))return T.push({prop:e,args:r}),t;throw new Error("DOMPurify is not available. Ensure DOMPurify is exposed globally (e.g., window.DOMPurify).")}}});var H=/&/gi,j=/&(?=[#a-z0-9])(?![a-z0-9]+=)/i;var F=/#$/,X=/^(?:application\/(?:[\w.-]+\+)?xml|image\/svg\+xml|text\/(?:html|xml))(?:\s*;\s*|$)/i;var V=/\P{ASCII}/u,Y=/&#(x0*[\dA-F]{1,2}|0*\d{1,3});?/gi,q=/(?:%[\dA-F]{2})+/gi,Q=/^((?:[^#%]|%(?!23))*)\?$/,A=/^[a-z][\da-z+.-]*$/,W=/^(?:web\+[a-z]+|ext\+[a-z][\da-z.-]*)$/,R=/^(?:java|vb)script$/i,_=/^(?:(?:java|vb)script|blob)$/i,k=/["'<>]|%(?:22|27|3C|3E)|&(?:apos|lt|gt|quot|#0*(?:34|39|60|62)|#x0*(?:22|27|3C|3E));/i,Z=/^%[\dA-F]{2}$/i,K=/^(?:\/{2,}|\\|[a-z][a-z\d+\-.]*:[^/])/i;var J=[9,10,13,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];var P=new Set(J),B=new Map([[128,8364],[130,8218],[131,402],[132,8222],[133,8230],[134,8224],[135,8225],[136,710],[137,8240],[138,352],[139,8249],[140,338],[142,381],[145,8216],[146,8217],[147,8220],[148,8221],[149,8226],[150,8211],[151,8212],[152,732],[153,8482],[154,353],[155,8250],[156,339],[158,382],[159,376]]),ge=()=>{let n=new Map;for(let e=0;e<256;e++)!P.has(e)&&!B.has(e)&&n.set(e,`\\x${e.toString(16).padStart(2,"0").toUpperCase()}`);return n},G=ge();var[E,Re,ye,Ee,xe,we]=["&","#","<",">",'"',"'"].map(n=>`%${n.charCodeAt(0).toString(16).toUpperCase()}`),_e={[E]:`${E}amp;`,[ye]:`${E}lt;`,[Ee]:`${E}gt;`,[xe]:`${E}quot;`,[we]:`${E}${Re}39;`},Xe=Array.from({length:256},(n,e)=>`%${e.toString(16).padStart(2,"0").toUpperCase()}`),ne=globalThis.process?.versions?.node!==void 0,oe=`[${[...G.values()].join("")}]`,Ue=new RegExp(oe),Le=new RegExp(oe,"g"),Te=new Uint8Array(65536),Ve=new TextEncoder,Se=new TextDecoder("utf-8",{fatal:!0}),f=(n,e=!1)=>{if(!p(n))return null;let t=V.test(n)?n.normalize("NFKC"):n;return e?t.trim().toLowerCase().replace(/:$/,""):t},d=(n,e,t=!1)=>{if(!p(n)||n==="")return null;let s=n,r=e&&p(e)?e:"";if(t&&(s=f(s),r&&(r=f(r))),typeof URL.parse=="function")return r?URL.parse(s,r):URL.parse(s);try{return r?new URL(s,r):new URL(s)}catch{return null}},ae=n=>p(n)?n.replace(/:$/,"").split("+"):[];var ie=n=>{if(!p(n))return n;let e=Z.test(n)?n.toUpperCase():n;return _e[e]??n},u=n=>{let e=p(n)?n:String(n);return e.length>64?`${e.slice(0,64)}...`:e},ce=n=>p(n)?n.replace(F,"").replace(Q,"$1"):n,Ae=(n,e)=>{let t=/^x/i.test(e)?Number.parseInt(e.slice(1),16):Number.parseInt(e,10);if(!Number.isInteger(t)||t<0||t>=256)return n;if(G.has(t))return"";if(P.has(t))return String.fromCharCode(t);let s=B.get(t);return String.fromCodePoint(s)},le=(n,e=0)=>{if(!p(n))throw new TypeError(`Expected String but got ${y(n)}.`);if(!Number.isInteger(e))throw new TypeError(`Expected Number but got ${y(e)}.`);let t;try{t=decodeURIComponent(n)}catch{t=n.replace(q,r=>{try{return decodeURIComponent(r)}catch{return r}})}t=t.replace(Le,"");let s=0;for(;s+e<16;s++){let r=t;if(t=t.replace(H,"&").replace(Y,Ae),t===r)break}if(s+e>=16&&/&#/.test(t))throw new Error("Character references nested too deeply.");return t},O=(n,e="",t="")=>{if(!p(n))return{mediaType:"",mediaTypes:[],data:"",isBase64:!1};let s=n.indexOf(",");if(s===-1)return{mediaType:n,mediaTypes:n.split(";"),data:"",isBase64:!1};let r=n.substring(0,s),o=n.substring(s+1),a=e===""&&t===""?o:o+e+t,c=r.split(";"),i=c.at(-1),l=i!==void 0&&i.length===6&&i.toLowerCase()==="base64";return{mediaType:r,mediaTypes:c,data:a,isBase64:l}},pe=n=>{if(!p(n))throw new TypeError(`Expected String but got ${y(n)}.`);let e,t=n;try{e=atob(n)}catch{t=n.replace(/\s/g,"");try{e=atob(t)}catch{throw new Error(`Invalid base64 data: ${u(n)}`)}}let s;if(ne&&globalThis.Buffer)s=globalThis.Buffer.from(e,"latin1");else{let r=e.length;r>65536?s=new Uint8Array(r):s=Te.subarray(0,r);for(let o=0;o<r;o++)s[o]=e.charCodeAt(o)}try{let r=Se.decode(s);return Ue.test(r)?t:r}catch{return t}},z=n=>{if(ne&&globalThis.Buffer)return globalThis.Buffer.from(n).toString("base64");let e=new Uint8Array(n);if(typeof e.toBase64=="function")return e.toBase64();let t=[];for(let s=0;s<e.length;s+=8192)t.push(String.fromCharCode(...e.subarray(s,s+8192)));return btoa(t.join(""))},ve=async(n,e,t)=>{let s=n.body.getReader(),r=[],o="Operation aborted";if(t?.aborted)throw await s.cancel(o),s.releaseLock(),t.reason;let a=()=>{s.cancel(o).catch(()=>{})};t?.addEventListener("abort",a,{once:!0});try{let c=0;for(;c<=e;){if(t?.aborted)throw await s.cancel(o),t.reason;let{done:m,value:b}=await s.read();if(t?.aborted)throw t.reason;if(m)break;if(c+=b.byteLength,c>e)throw await s.cancel("Size limit exceeded"),new DOMException(`Payload (${c} bytes) exceeds max (${e} bytes).`,"NotReadableError");r.push(b)}let i=new Uint8Array(c),l=0;for(let m of r)i.set(m,l),l+=m.byteLength;return i.buffer}finally{t?.removeEventListener("abort",a),s.releaseLock()}},D=async(n,e,t)=>{let s=16777216;Number.isInteger(e)&&e>0&&(s=e);let r=await fetch(n,{signal:t});if(!r.ok){let l=`Failed to fetch ${u(n)}`;throw Number.isInteger(r.status)&&(r.statusText?l+=`: ${r.status} ${r.statusText}`:l+=`: ${r.status}`),new Error(l)}let o=r.headers.get("content-length");if(o){let i=Number.parseInt(o,10);if(Number.isInteger(i)&&i>s)throw new DOMException(`Payload (${i} bytes) exceeds max (${s} bytes).`,"NotReadableError")}let a=r.headers.get("content-type")||"",c;if(r.body)c=await ve(r,s,t);else{let i=await r.blob();if(i.size>s)throw new DOMException(`Payload (${i.size} bytes) exceeds max (${s} bytes).`,"NotReadableError");c=await i.arrayBuffer()}return{buffer:c,mimeType:a}};var L=class{constructor(e,t=w){this.domPurify=e,this.nest=0,this.recurse=new Set,this.restrictScheme=!1,this.schemeMap=new Map([["blob",!1],["data",!1],["file",!1],["javascript",!1],["vbscript",!1]]),this.#e(t)}#e(e){let{allowRelative:t,debug:s,allow:r,deny:o,only:a,schemes:c}=e;if(this.allowRelative=!!t,this.debug=!!s,this.schemes=c,Array.isArray(a)){this.restrictScheme=!0;for(let i of a)this.#t(i)}else{if(Array.isArray(r)&&r.length)for(let i of r)this.#t(i);if(Array.isArray(o)&&o.length)for(let i of o){let l=f(i,!0);l&&this.schemeMap.set(l,!1)}}}#t(e){let t=f(e,!0);return!t||_.test(t)||!A.test(t)||t.includes("+")&&t.split("+").some(r=>R.test(r))?!1:(this.schemeMap.set(t,!0),!0)}enter(e){return this.recurse.has(e)?(this.debug&&h(`Circular Data URL detected and skipped: ${u(e)}`),!1):(this.nest++,this.recurse.add(e),!0)}leave(e){this.nest--,this.recurse.delete(e)}},N=class{#e;constructor(e=w){this.#e=e}#t(e,t){if(t.nest>16)throw new Error("Data URLs nested too deeply.");let s=d(e,null,!0);if(!s){if(t.allowRelative&&!K.test(e)){let o=d(e,M);if(o){let{protocol:a,hostname:c,pathname:i,search:l,hash:m}=o;if(a==="http:"&&c==="dummy.local")return this.#n(`${i}${l}${m}`)}}return null}let r=f(s.protocol,!0);if(t.restrictScheme&&!t.schemeMap.has(r))return null;if(r.includes("+")){let o=r.split("+");if(t.schemeMap.get(r)===!1||o.some(a=>t.schemeMap.get(a)===!1))return null}else if(t.schemeMap.has(r)){if(t.schemeMap.get(r)===!1)return null}else if(!t.schemes.has(r))return null;return r==="data"?this.#s(s,t):this.#n(s.href)}#s(e,t){let{mediaType:s,mediaTypes:r,data:o,isBase64:a}=O(e.pathname,e.search,e.hash),c=o;if(a)try{c=pe(o)}catch(i){return t.debug&&h("Failed to parse base64 data.",i),null}try{let i=le(c).trim(),l=d(i,M);if(!l||ae(l.protocol).some(b=>_.test(b)))return null}catch(i){return t.debug&&h("Failed to parse inner data URL protocol.",i),null}return(!s||X.test(s))&&(c=this.#o(c,t)),c?(a&&c!==o&&r.pop(),`data:${r.join(";")},${c}`):null}#o(e,t){let s="";try{s=decodeURIComponent(e)}catch{s=e}let r=(a,c)=>this.#r(a,c,t),o="";try{t.domPurify.addHook("uponSanitizeAttribute",r),o=t.domPurify.sanitize(s)}finally{t.domPurify.removeHook("uponSanitizeAttribute",r)}if(!o)return null;try{return encodeURI(ce(o))}catch{return null}}#r(e,t,s){if(!t.attrValue||!/^\s*data:/i.test(t.attrValue))return;let r=d(t.attrValue,null,!0);if(!r||r.protocol!=="data:")return;let o=t.attrValue;if(!s.enter(o)){t.attrValue="";return}try{let a=this.#t(o,s);t.attrValue=a||""}finally{s.leave(o)}}#n(e){let t=e.length,s=t,r=k.exec(e);if(r&&(s=r.index),e.indexOf("&")>-1){let a=j.exec(e);if(a){let c=a.index;c<s&&(s=c)}}if(s===t)return e;let o=e.charCodeAt(s-1);return(o===63||o===38)&&s--,e.substring(0,s)}sanitize(e,t=this.#e){if(!e||!p(e))return null;let{deny:s,maxLength:r,only:o,allowRelative:a}=t;if(Number.isInteger(r)&&e.length>r){let l=`URL length ${e.length} exceeds max length ${r}.`;throw new RangeError(l)}if(!(Array.isArray(s)&&s.length>0||Array.isArray(o)||a)&&/^https?:\/\//.test(e)&&!k.test(e)&&!e.includes("data:")){let l=d(e,null,!0);return l&&t.schemes.has(l.protocol.replace(/:$/,""))?l.href.replace(/%26/g,ie):null}let i=new L(S,t);return this.#t(e,i)}async sanitizeBuffer(e,t,s=this.#e){if(!(e instanceof ArrayBuffer))return null;let r=z(e),a=`data:${t?`${t};base64`:"base64"},${r}`;if(Number.isInteger(s.maxLength)&&a.length>s.maxLength)throw new RangeError(`URL length ${a.length} exceeds max length ${s.maxLength}.`);let c=new L(S,s);if(!c.schemeMap.get("data"))return null;let i=d(a);return i?this.#s(i,c):null}async sanitizeDataURL(e,t=this.#e){if(!e||!p(e))return null;let{maxLength:s}=t;if(Number.isInteger(s)&&e.length>s)throw new RangeError(`URL length ${e.length} exceeds max length ${s}.`);let r=d(e);if(!r)return null;let o=f(r.protocol,!0);if(o!=="data")return null;let a=new L(S,t);return a.schemeMap.get(o)?this.#s(r,a):null}};var me=["aaa","aaas","about","acap","acct","acd","ace","aceap","acedp","aceep","acelp","aceup","acr","adiumxtra","adt","aet","afp","afs","agtp","aim","alter","amss","android","appdata","apt","ar","ari","ark","ars","arv","at","attachment","aw","barion","beshare","bitcoin","bitcoincash","bl","blob","bluetooth","bolo","brid","browserext","cabal","caip","calculator","callto","canactid","cap","cast","casts","chrome","chrome-extension","cid","cm","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cttps","cvs","dab","dat","data","dav","dhttp","diaspora","dict","did","dilithium3","dis","dlna-playcontainer","dlna-playsingle","dnp","dns","dntp","doi","donau","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","esim","ethereum","example","ez","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","gcx","gdsi","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gsos","gtalk","h323","haie","ham","hcap","hcp","hs20","http","https","hxxp","hxxps","hydrazone","hyper","i0","iax","ibi","ibi-","icap","icon","ilstring","im","imap","info","interaction","iotdisco","ipfs","ipn","ipns","ipp","ipps","iqa","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lid","linkid","locus","lorawan","lpa","lvlt","machineProvisioningProgressReporter","magnet","mailto","maps","market","matrix","mdoc","mdoc-openid4vp","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","mqtt","mqtts","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-launchremotedesktop","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-personacard","ms-powerpoint","ms-project","ms-publisher","ms-recall","ms-remotedesktop","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-uup","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-widgetboard","ms-widgets","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mtrust","mumble","mupdate","musik","mvn","mvrp","mvrps","news","nfs","ni","nih","nntp","nostr","notes","npamp","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openid","openpgp4fpr","opns","ord","ordmail","otpauth","palm","paparazzi","payto","pkcs11","pkg","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","rttp","sarif","secondlife","secret-token","seki","service","session","sftp","sgn","shc","shelter","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","sns","soap.beep","soap.beeps","soldat","spacify","spiffe","spotify","ssb","ssh","sss","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","tcxp","teamspeak","teapot","teapots","tel","teliaeid","telnet","tftp","things","thismessage","tii","tip","tn3270","tool","tttps","turn","turns","tv","udp","unreal","upn","urn","ust","ut2004","uuaid","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wasm","wasm-js","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcompute","xcon","xcon-userid","xfire","xftp","xmlrpc.beep","xmlrpc.beeps","xmpp","xrcp","xri","ymsgr","z39.50r","z39.50s","ztdnaid"];var $=class{#e=new Set(me);get(){return[...this.#e]}getScheme(e){if(!p(e))return null;let t=this.parse(e);return t?this.normalize(t.protocol,!0):null}has(e){let t=this.normalize(e,!0);return t?this.#e.has(t):!1}normalize(e,t=!1){return f(e,t)}normalizeSchemes(e){if(Array.isArray(e)){let t=[];for(let s of e){let r=f(s,!0);r&&t.push(r)}return t}return[]}parse(e,t,s=!1){return d(e,t,s)}verifyURI(e,t){if(!p(e))return!1;let s=this.parse(e);return s?this.verifyScheme(s.protocol,t,!0):!1}verifyScheme(e,t,s=!1){let r=this.normalize(e,!0);if(!r)return!1;let o=t||this.#e;if(!r.includes("+"))return R.test(r)?!1:o.has(r);let a=r.split("+");return a.some(i=>R.test(i))?!1:o.has(r)?!0:s&&W.test(r)||a.every(i=>o.has(i))}};var Oe=Object.freeze(["href","origin","protocol","username","password","host","hostname","port","pathname","search","hash"]),I=class extends ${#e;#t;#s;constructor(){super(),this.#e=new Set(super.get()),this.#t={...w,schemes:this.#e},this.#s=new N(this.#t)}#o(e){return!p(e)||_.test(e)||e.includes("+")&&e.split("+").some(s=>R.test(s))?!1:A.test(e)}#r(e,t={}){if(!p(e)||e==="")return{isValid:!1};let s={...this.#t,...t,allow:this.normalizeSchemes(t.allow),deny:this.normalizeSchemes(t.deny),only:Object.hasOwn(t,"only")?this.normalizeSchemes(t.only):this.#t.only,schemes:this.#e},r=this.getScheme(e);return r===null&&!s.allowRelative?{isValid:!1}:{options:s,scheme:r}}#n(e,t){let s={input:e,href:null,valid:!1};if(!p(e))return s.reason=`Invalid URL input: ${u(e)}`,s;if(e==="")return s.reason="Invalid URL input: (empty string)",s;let r,o=null;try{r=this.#s.sanitize(e,t),r||(o="Sanitization failed (blocked by allowed schemes or rules).")}catch(a){o=a.message}if(r){let a=d(r);if(s.valid=!0,a){if(f(a.protocol,!0)==="data"){let{mediaTypes:i,data:l,isBase64:m}=O(a.pathname,a.search,a.hash);m&&i.pop(),s.data={mime:i.join(";"),base64:m,data:l}}else s.data=null;for(let i of Oe){let l=a[i];p(l)&&(s[i]=l)}}else s.valid=!1,s.relative=!0,s.href=r,s.reason="Invalid as an absolute URL, but valid as a relative URL."}else s.reason=o;return s}async#i(e,t){try{let{buffer:s,mimeType:r}=await D(e,t.maxBlobSize,t.signal),o=z(s),a=`data:${r?`${r};base64`:"base64"},${o}`,c=this.#n(a,t);return c.input=e,c}catch(s){if(s.name==="AbortError"||t.signal?.aborted)throw s;return t.debug&&h(`Failed to inspect blob URL: ${u(e)}`,s),{input:e,valid:!1,reason:s.message}}finally{t.revokeObjectURL&&URL.revokeObjectURL(e)}}#a(e,t){if(e instanceof TypeError||e.name==="AbortError"||t.signal?.aborted)throw e}get(){return[...this.#e]}has(e){let t=f(e,!0);return t?this.#e.has(t):!1}add(e){if(!p(e))throw new TypeError(`Expected String but got ${y(e)}.`);let t=f(e,!0);if(!this.#o(t))throw new Error(`Invalid scheme: ${e}`);return this.#e.add(t),[...this.#e]}remove(e){if(!p(e))return!1;let t=f(e,!0);return this.#e.delete(t)}reset(){this.#e.clear();for(let e of super.get())this.#e.add(e)}async sanitizeURL(e,t){let{isValid:s,options:r,scheme:o}=this.#r(e,t);if(s===!1)return null;if(o==="blob"){let{allow:a,deny:c,only:i}=r,l=null;try{if(a.includes("blob")&&!c.includes("blob")||Array.isArray(i)&&i.includes("blob")){let m=null,b="";try{let g=await D(e,r.maxBlobSize,r.signal);m=g.buffer,b=g.mimeType}catch(g){if(g.name==="AbortError"||r.signal?.aborted)throw g;r.debug&&h(`Failed to fetch and convert blob URL: ${u(e)}`,g)}m&&(i?.length?i.includes("data")||(r.only=[...i,"data"]):(a.includes("data")||(r.allow=[...a,"data"]),r.deny=c.filter(g=>g!=="data")),l=await this.#s.sanitizeBuffer(m,b,r))}}catch(m){return this.#a(m,r),r.debug&&h(`Failed to sanitize URL: ${u(e)}`,m),null}finally{r.revokeObjectURL&&URL.revokeObjectURL(e)}return l}try{return o==="data"?this.#s.sanitizeDataURL(e,r):this.#s.sanitize(e,r)}catch(a){return this.#a(a,r),r.debug&&h(`Failed to sanitize URL: ${u(e)}`,a),null}}sanitizeURLSync(e,t){let{isValid:s,options:r,scheme:o}=this.#r(e,t);if(s===!1)return null;if(o==="blob")return r.revokeObjectURL&&URL.revokeObjectURL(e),null;try{return this.#s.sanitize(e,r)}catch(a){return this.#a(a,r),r.debug&&h(`Failed to sanitize URL: ${u(e)}`,a),null}}async inspectURL(e,t={}){let{options:s,scheme:r}=this.#r(e,t);return r==="blob"?this.#i(e,s):this.#n(e,s)}isValidURI(e){return super.verifyURI(e,this.#e)}};var x=new I,ut=async(n,e)=>x.sanitizeURL(n,e),ht=(n,e)=>x.sanitizeURLSync(n,e),gt=async(n,e={})=>x.inspectURL(n,e),bt=n=>x.isValidURI(n),Rt=n=>x.isValidURI(n),yt=x;export{I as URLSanitizer,yt as default,gt as inspectURL,Rt as isURISync,bt as isValidURI,ut as sanitizeURL,ht as sanitizeURLSync};
|
|
2
2
|
/*!
|
|
3
3
|
* URL Sanitizer
|
|
4
4
|
*
|