AdguardTeam / Scriptlets

AdGuard scriptlets library
GNU General Public License v3.0
138 stars 27 forks source link

Modifying XHR response without changes causes a breakage at sante.journaldesfemmes.fr #419

Open piquark6046 opened 3 months ago

piquark6046 commented 3 months ago

https://github.com/AdguardTeam/AdguardFilters/issues/176244

Please test with the following rule:

sante.journaldesfemmes.fr#%#//scriptlet('trusted-replace-xhr-response', ',"aabMessage":true,', ',"aabMessage":true,', '/ws/mediaplayer-data/init')
AdamWr commented 3 months ago

It seems that I was wrong and the information below is only partially true. The problem is that website checks headers.get("content-type") and if it's not application/json then reject request. So, it even doesn't have to be a blob.


Do I understand correctly that video player doesn't work with mentioned rule? If it's not the problem, then please provide more details.

Regarding issue with video player, as far as I understand, the problem is that in this case responseType is a blob, and website expect blob as a response, but trusted-replace-xhr-response returns string.

Converting modifiedContent to a blob (in case if responseType is a blob) should fixes it.

blobContent = new Blob([modifiedContent], {
  type: "application/json"
});

There is a scriptlet converted to JavaScript rule with mentioned changes:

sante.journaldesfemmes.fr#%#!function(e,t){function n(e){if(!0===e.verbose){try{var t=console.log.bind(console),n=console.trace.bind(console),r=e.ruleText||"";if(e.domainName){var a;e.ruleText.includes("#%#//")?a=e.ruleText.indexOf("#%#//"):e.ruleText.includes("##+js")&&(a=e.ruleText.indexOf("##+js"));var o=e.ruleText.slice(a);r="".concat(e.domainName).concat(o)}t("".concat(r," trace start")),n&&n(),t("".concat(r," trace end"))}catch(e){}"function"==typeof window.__debug&&window.__debug(e)}}function r(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=e.name,o=e.verbose;if(n||o){var c=console.log;r?c("".concat(a,": ").concat(t)):c("".concat(a,":"),t)}}function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";if(""===e)return new RegExp(".?");var t,n,r=e.lastIndexOf("/"),a=e.substring(r+1),o=e.substring(0,r+1),c=(n=a,(t=o).startsWith("/")&&t.endsWith("/")&&!t.endsWith("\\/")&&function(e){if(!e)return!1;try{return new RegExp("",e),!0}catch(e){return!1}}(n)?n:"");if(e.startsWith("/")&&e.endsWith("/")||c)return new RegExp((c?o:e).slice(1,-1),c);var s=e.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(s)}function o(e){return e&&"object"==typeof e?function(e){return 0===Object.keys(e).length&&!e.prototype}(e)?"{}":Object.entries(e).map((function(e){var t=e[0],n=e[1],r=n;return n instanceof Object&&(r="{ ".concat(o(n)," }")),"".concat(t,':"').concat(r,'"')})).join(" "):String(e)}function c(e,t,n,r,a){return{method:e,url:t,async:n,user:r,password:a}}var s=t?[].concat(e).concat(t):[e];try{(function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"";if("undefined"!=typeof Proxy)if(""!==t||""===s){var l,u=""===t&&""===s,p=window.XMLHttpRequest.prototype.open,d=window.XMLHttpRequest.prototype.send,f={apply:function(t,s,p){if(l=c.apply(null,p),u){var d="xhr( ".concat(o(l)," )");return r(e,d,!0),n(e),Reflect.apply(t,s,p)}if(function(e,t,n){if(""===t||"*"===t)return!0;var o,c,s,i,l=(" ",":",c=function(e){return["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"].includes(e)},s={},t.split(" ").forEach((function(e){var t=e.indexOf(":"),n=e.slice(0,t);if(c(n)){var r=e.slice(t+1);s[n]=r}else s.url=e})),s);if(i=l,Object.values(i).every((function(e){return function(e){var t,n=function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(e);"/"===e[0]&&"/"===e[e.length-1]&&(n=e.slice(1,-1));try{t=new RegExp(n),t=!0}catch(e){t=!1}return t}(e)}))){var u=function(e){var t={};return Object.keys(e).forEach((function(n){t[n]=a(e[n])})),t}(l);o=Object.keys(u).every((function(e){var t=u[e],r=n[e];return Object.prototype.hasOwnProperty.call(n,e)&&"string"==typeof r&&(null==t?void 0:t.test(r))}))}else r(e,"Invalid parameter: ".concat(t)),o=!1;return o}(e,i,l)&&(s.shouldBePrevented=!0,s.headersReceived=!!s.headersReceived),s.shouldBePrevented&&!s.headersReceived){s.headersReceived=!0,s.collectedHeaders=[];var f={apply:function(e,t,n){return t.collectedHeaders.push(n),Reflect.apply(e,t,n)}};s.setRequestHeader=new Proxy(s.setRequestHeader,f)}return Reflect.apply(t,s,p)}},v={apply:function(r,o,c){if(!o.shouldBePrevented)return Reflect.apply(r,o,c);var i=new XMLHttpRequest;i.addEventListener("readystatechange",(function(){if(4===i.readyState){var r=i.readyState,c=i.response,l=i.responseText,u=i.responseURL,p=i.responseXML,d=i.status,f=i.statusText,v=l||c;if("string"==typeof v){var y="*"===t?/(\n|.)*/:a(t),h=v.replace(y,s);"blob"===o.responseType&&(h=new Blob([h],{type:"application/json"})),Object.defineProperties(o,{readyState:{value:r,writable:!1},responseURL:{value:u,writable:!1},responseXML:{value:p,writable:!1},status:{value:d,writable:!1},statusText:{value:f,writable:!1},response:{value:h,writable:!1},responseText:{value:h,writable:!1}}),setTimeout((function(){var e=new Event("readystatechange");o.dispatchEvent(e);var t=new Event("load");o.dispatchEvent(t);var n=new Event("loadend");o.dispatchEvent(n)}),1),n(e)}}})),p.apply(i,[l.method,l.url]),o.collectedHeaders.forEach((function(e){var t=e[0],n=e[1];i.setRequestHeader(t,n)})),o.collectedHeaders=[];try{d.call(i,c)}catch(e){return Reflect.apply(r,o,c)}}};XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,f),XMLHttpRequest.prototype.send=new Proxy(XMLHttpRequest.prototype.send,v)}else r(e,"Pattern argument should not be empty string.")}).apply(this,s)}catch(e){console.log(e)}}({name:"trusted-replace-xhr-response",engine:"corelibs",version:"1.14.46",verbose:!1},['"aabMessage":true','"aabMessage":false',"/ws/mediaplayer-data/init"]);
piquark6046 commented 3 months ago

Do I understand correctly that video player doesn't work with mentioned rule? If it's not the problem, then please provide more details.

Yes. That's correct. Thanks.

Regarding issue with video player, as far as I understand, the problem is that in this case responseType is a blob, and website expect blob as a response, but trusted-replace-xhr-response returns string.

Then, Can we resolve the issue with extra parameter selecting a return type? Also, I think that we should improve json-prune-xhr-response scriptlet too if necessary.

CC: @gorhill

AdamWr commented 3 months ago

Then, Can we resolve the issue with extra parameter selecting a return type?

I think that we can check responseType and do it automatically without additional parameters.

Also, I think that we should improve json-prune-xhr-response scriptlet too if necessary.

As I recall, in json-prune-xhr-response it's done this way, but type is not set (sante.journaldesfemmes.fr is checking it, so in this case it's needed to set it), so it might be necessary to fix it.


By the way, if I'm not wrong, as an alternative solution for https://github.com/AdguardTeam/AdguardFilters/issues/176244, this rule can be used:

sante.journaldesfemmes.fr#%#//scriptlet('set-constant', 'integrityObserver.corrupted', '0')
piquark6046 commented 3 months ago

By the way, if I'm not wrong, as an alternative solution for https://github.com/AdguardTeam/AdguardFilters/issues/176244, this rule can be used:

Thanks. Committed.