diff --git a/package.json b/package.json index 79f3bd1..0ec3be6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "type": "module", "scripts": { - "build": "deno build.ts --tagName 1.75.1b1 > ubo.js", + "build": "deno build.ts --tagName 1.75.1b11 > ubo.js", "test": "node --test" }, "author": { diff --git a/ubo.js b/ubo.js index fd9ad99..64d919c 100644 --- a/ubo.js +++ b/ubo.js @@ -238,6 +238,14 @@ fn: 'trustedJsonEditFetchResponse', }; +scriptlets['trusted-edit-inbound-element.js'] = { +aliases: [], + +requiresTrust: true, +fn: 'trustedEditInboundElement', +}; + + scriptlets['json-edit-fetch-request.js'] = { aliases: [], @@ -3192,6 +3200,55 @@ function jsonEditFetchRequestFn(trusted, jsonq = '', ...varargs) { proxyApplyFn('fetch', proxyHandler); proxyApplyFn('Request', proxyHandler); } +async function editInboundElementFn( + trusted = false, + propChain = '', + argPosRaw = '', + selector = '', + jsonq = '' +) { + if ( propChain === '' ) { return; } + if ( selector === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}edit-inbound-element`, + propChain, argPosRaw, selector, jsonq + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const argPos = parseInt(argPosRaw, 10); + const getElem = context => { + if ( argPosRaw === 'this' ) { return context.thisArg; } + const { callArgs } = context; + if ( Array.isArray(callArgs) === false ) { return; } + if ( isNaN(argPos) ) { return; } + if ( argPos >= 0 ) { + if ( callArgs.length <= argPos ) { return; } + return callArgs[argPos]; + } + if ( callArgs.length < -argPos ) { return; } + return callArgs[callArgs.length + argPos]; + }; + const editElem = elem => { + if ( elem instanceof Element === false ) { return; } + if ( elem.matches(selector) === false ) { return; } + elem = jsonp.apply(elem); + if ( elem === undefined ) { return; } + safe.uboLog(logPrefix, 'Edited'); + }; + proxyApplyFn(propChain, function(context) { + const elem = getElem(context); + if ( elem !== undefined ) { + editElem(elem); + } + return context.reflect(); + }); +} +function trustedEditInboundElement(...args) { + editInboundElementFn(true, ...args); +} function jsonEditFetchRequest(jsonq = '', ...args) { jsonEditFetchRequestFn(false, jsonq, ...args); } @@ -6940,7 +6997,7 @@ function trustedOverrideElementMethod( return validateConstantFn(true, disposition, extraArgs); }); } -const table = { abortCurrentScript, setAttr, trustedSetAttr, removeAttr, trustedCreateHTML, hrefSanitizer, proxyApplyConfig, editOutboundObject, trustedEditOutboundObject, jsonEdit, trustedJsonEdit, editInboundObject, trustedEditInboundObject, editThisObject, trustedEditThisObject, editObjectOnGetter, trustedEditObjectOnGetter, editObjectOnSetter, trustedEditObjectOnSetter, editElementObject, trustedEditElementObject, jsonEditXhrResponse, trustedJsonEditXhrResponse, jsonEditXhrRequest, trustedJsonEditXhrRequest, jsonEditFetchResponse, trustedJsonEditFetchResponse, jsonEditFetchRequest, trustedJsonEditFetchRequest, jsonlEditXhrResponse, trustedJsonlEditXhrResponse, jsonlEditFetchResponse, trustedJsonlEditFetchResponse, abortOnStackTrace, trustedPruneInboundObject, trustedPruneOutboundObject, jsonPrune, jsonPruneFetchResponse, jsonPruneXhrResponse, evaldataPrune, noEvalIf, preventAddEventListener, preventBab, preventClipboardWrite, preventDialog, preventFetch, trustedPreventFetch, freezeElementProperty, preventInnerHTML, preventNavigation, preventSetTimeout, preventSetInterval, preventRequestAnimationFrame, setConstant, trustedSetConstant, trustedReplaceArgument, spoofCSS, preventXhr, trustedPreventXhr, mpegdashPrune, setCookie, setCookieReload, trustedSetCookie, trustedSetCookieReload, removeCookie, setLocalStorageItem, setSessionStorageItem, trustedSetLocalStorageItem, trustedSetSessionStorageItem, abortOnPropertyRead, abortOnPropertyWrite, adjustSetInterval, adjustSetTimeout, preventRefresh, removeClass, webrtcIf, noWindowOpenIf, closeWindow, windowNameDefuser, overlayBuster, alertBuster, noWebrtc, disableNewtabLinks, xmlPrune, m3uPrune, callNothrow, removeNodeText, preventCanvas, multiup, breakOnCall, replaceNodeText, trustedReplaceFetchResponse, trustedReplaceXhrResponse, trustedClickElement, trustedReplaceOutboundText, trustedSuppressNativeMethod, trustedPreventDomBypass, trustedOverrideElementMethod }; +const table = { abortCurrentScript, setAttr, trustedSetAttr, removeAttr, trustedCreateHTML, hrefSanitizer, proxyApplyConfig, editOutboundObject, trustedEditOutboundObject, jsonEdit, trustedJsonEdit, editInboundObject, trustedEditInboundObject, editThisObject, trustedEditThisObject, editObjectOnGetter, trustedEditObjectOnGetter, editObjectOnSetter, trustedEditObjectOnSetter, editElementObject, trustedEditElementObject, jsonEditXhrResponse, trustedJsonEditXhrResponse, jsonEditXhrRequest, trustedJsonEditXhrRequest, jsonEditFetchResponse, trustedJsonEditFetchResponse, trustedEditInboundElement, jsonEditFetchRequest, trustedJsonEditFetchRequest, jsonlEditXhrResponse, trustedJsonlEditXhrResponse, jsonlEditFetchResponse, trustedJsonlEditFetchResponse, abortOnStackTrace, trustedPruneInboundObject, trustedPruneOutboundObject, jsonPrune, jsonPruneFetchResponse, jsonPruneXhrResponse, evaldataPrune, noEvalIf, preventAddEventListener, preventBab, preventClipboardWrite, preventDialog, preventFetch, trustedPreventFetch, freezeElementProperty, preventInnerHTML, preventNavigation, preventSetTimeout, preventSetInterval, preventRequestAnimationFrame, setConstant, trustedSetConstant, trustedReplaceArgument, spoofCSS, preventXhr, trustedPreventXhr, mpegdashPrune, setCookie, setCookieReload, trustedSetCookie, trustedSetCookieReload, removeCookie, setLocalStorageItem, setSessionStorageItem, trustedSetLocalStorageItem, trustedSetSessionStorageItem, abortOnPropertyRead, abortOnPropertyWrite, adjustSetInterval, adjustSetTimeout, preventRefresh, removeClass, webrtcIf, noWindowOpenIf, closeWindow, windowNameDefuser, overlayBuster, alertBuster, noWebrtc, disableNewtabLinks, xmlPrune, m3uPrune, callNothrow, removeNodeText, preventCanvas, multiup, breakOnCall, replaceNodeText, trustedReplaceFetchResponse, trustedReplaceXhrResponse, trustedClickElement, trustedReplaceOutboundText, trustedSuppressNativeMethod, trustedPreventDomBypass, trustedOverrideElementMethod }; for (const [name, ...args] of calls) { try { table[name](...args); } catch {} }