IWBH_01

in-browser client side html5 webproxy environment (sub_env_api.js) (unfinished)

Apr 29th, 2021 (edited)
859
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  
  3. in-browser client side html5 webproxy environment (sub_env_api.js) (unfinished)
  4.  
  5. NOTE: this is a work in progress, it is currently unfinished and not fully or at all functional.
  6.  
  7. This sub-environment api was written by the Transcendentian.
  8. It is open-source, so you may use it, modify it etc.
  9.  
  10. right now it (this script) needs (requires) my main.js (https://docs.google.com/uc?id=0Bxb5iFgmM3V6eTRINGZ0Zm1zMkk) to be already (pre) loaded in order for it to run.
  11.  
  12. The purpose of this api is to load and run webpages and/or resources in a sub-environment of another webpage. Uses include, a proxy page that runs javascript without the website being proxied knowing that it's being proxied, hugely expanded cors capabilities (is disabled in the sub environment) (example: draw a cross-origin image to a canvas and then access ctx.getImageData() );
  13.  
  14.  
  15. */
  16.  
  17. //properly undepricate __proto__:
  18. (function(w){var O=w.Object,Op=O?O.prototype:!1,po="__proto__",dGS=["__define","etter__"],eP="etPrototypeOf";
  19. if(!(po in w)){
  20. Op[dGS.join("G")](po,function(){return O["g"+eP](this);});
  21. Op[dGS.join("S")](po,function(v){O["g"+eP](this,v);});
  22. }}(self));
  23.  
  24. //if(typeof self.phpact!="function")TJA.require("https://docs.google.com/uc?id=0Bxb5iFgmM3V6azZVQmpTb295bGM"); //include 2php.js
  25.  
  26. //String.prototype.iindexOf=function(s){return this.toLowerCase().indexOf(s.toLowerCase());};//non-case-sensative indexOf
  27.  
  28. var rp=function(s,f,r){return s.split(f).join(r);},//replace
  29.  
  30. /* PHP code:
  31. https://pastebin.com/raw/TQ0Jt7pK
  32.  
  33. no longer using php code, using https://raw-http-api.thetranscendent.repl.co/ instead
  34. */
  35.  
  36.  p2_="code_g2.php",
  37. prsHdrs=function(hs){var ho={},h,ci;
  38.   hs=hs.split("\r\n");
  39.   while(hs.length){h=hs.pop();if((ci=h.indexOf(": "))+1)ho[h.substr(0,ci).toLowerCase()]=h.substr(ci+2);}
  40.   return ho;
  41. },
  42. allcookies=[],
  43. HttpReq=function(meh,url,callback,ehdrs,bdy){
  44.  var cb2=function(r){var bgn=TJA.unArrBuf(r.slice(0,20)),rsp={"ERRS":[],"headers":{},"sc":0};
  45.   if(bgn.substr(0,4)=="HL: "){var LL=bgn.indexOf("\r\n"),HL=bgn.substring(4,LL)*1;if(HL){
  46.    var RHL=HL+2+LL,HS=TJA.unArrBuf(r.slice(LL+2,RHL)),
  47.    fl,CU,rul=[],rdr=HS.split("\r\n\r\n"); rdr.pop();
  48.    
  49.    rsp.body=r.slice(RHL);
  50.    if(rdr.length){HS=rdr[rdr.length-1];
  51.     rdr.slice(1).forEach(function(rd){var lns=rd.split("\r\n"),fl=lns[0].split(" ");CU=fl[1];rul.push(fl[1]);lns.shift();
  52.      lns.forEach(function(rl){if(rl.length>12&&rl.substr(0,12).toLowerCase()=="set-cookie: "){
  53.        //save cookies
  54.        var buf=rl.substr(12),fe=buf.indexOf("="),si=buf.indexOf(";"),dt,buft,ph,tc={"name":buf.substr(0,fe),"value":buf.substring(fe+1,si)};buf=buf.substr(si+1);
  55.        dt=TJA.gurl(buft=buf.toLowerCase(), "expires=", ";");
  56.        tc.exp=dt.length?(new Date(dt)).getTime():"sess";
  57.        if((!dt.length)||(new Date()).getTime()<tc.exp){
  58.         tc.domain=TJA.gurl(buft, "domain=", ";");
  59.         if(!tc.domain.length) tc.domain=TJA.gurl(fl[1], "://", "/");
  60.         tc.path=(ph=TJA.gurl(buf, "path=", ";")).length?ph:fl[1].substr(fl[1].indexOf("/",9));
  61.         allcookies.push(tc);
  62.        }
  63.      }});
  64.     });
  65.     rsp.redirects=rul;
  66.    }
  67.  
  68.    rsp.currentUrl=CU||url;
  69.    rsp.headers=prsHdrs(HS);
  70.    rsp.sc=HS.split("\r\n")[1].split(" ")[1];
  71.   }else rsp.body=r.slice(LL+2);}
  72.   callback.call(this,rsp);},
  73.  
  74.  u2=phpact.bu+"/"+p2_+"/"+url,hdr=[["x-nope","cookie,referer,origin,x-real-ip"]];
  75.  
  76.  if(typeof ehdrs=="object")for(var H in ehdrs)hdr.push(["X-A-"+H,ehdrs[H]]);
  77.  TJA.XHR(meh,u2,cb2,hdr,bdy).onerror=function(){var st=this.status;
  78.   if(st===0||st>390){
  79.    //phpact('$tmp=fopen("'+p2_+'","w");fwrite($tmp,file_get_contents("https://pastebin.com/raw/TQ0Jt7pK"));fclose($tmp);echo "Did.";', function(r){if((r=TJA.unArrBuf(r))=="Did.")TJA.XHR(meh,u2,cb2,hdr,bdy);else alert("Error: "+r);});
  80.    //no phpact, using repl now, use start the repl
  81.   }
  82.  };
  83. };
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90. //   BEGIN AWESOME:
  91.  
  92. var blobs={},haz_url=[], //The blobs object includes fetched files as blobs, with the 'real' url as the property name. use blobs[url].burl to get a blob url of a cached file; haz_url is an Array of Element constructors that need href or src, each item has format {"n":constructor_funct(){}.name,"m":"href"||"src"}
  93.  
  94. Omap=new WeakMap(); //match iframes to their 'real' origins, url-fetching HTML elements to their real urls
  95.  
  96. /*note: this section is part of the "engine" code,
  97. it will only run one time when the proxy system is loading
  98. then the virtual proxied pages that are running in the proxy system will all rely on
  99. functions and properties that are defined in the "engine"
  100. */
  101.  
  102. /* use new Proxy() insteand of fantasmic
  103. fantasmic=function(O,p,rgf,rsf,o2){ //O==object, p=property, rgf=replace get function, rsf=replace set function;
  104. var od=Object.getOwnPropertyDescriptor(O,p),y,G=od.get,S=od.set;
  105. if(y=typeof rgf=="function")od.get=function(){rgf.call(this,G);};
  106. if(y=typeof rsf=="function")od.set=function(v){rsf.call(this,S,v);};
  107. if(y)Object.defineProperty(o2||O,p,od);
  108. //please note, rgf & rsf accept an extra argument, the first, the old function they replace, and in rsf the set-to value is the 2nd argument instead of the first like a regular getter
  109. return od;},
  110. fillN=function(to,so,not){not=not||{}; //put fill'n in some objects (use to make passthrus)
  111.     //forget it, use new Proxy()
  112. },
  113. siMLp=function Simple_ML_parser(s){
  114.     //forget it, use nullIframe
  115. },
  116. siMLs=function Simple_ML_stringify(ML){//forget it, use nullIframe
  117. }; */
  118.  
  119. //need src (get/set)ter: HTMLVideoElement,HTMLTrackElement,HTMLSourceElement,HTMLScriptElement,HTMLMediaElement,HTMLInputElement,Image,HTMLImageElement,HTMLIFrameElement,HTMLFrameElement,HTMLEmbedElement,Audio,HTMLAudioElement,webkitSpeechGrammar
  120. //need href /\ : URL,StyleSheet,SVGUseElement,SVGTextPathElement,SVGScriptElement,SVGRadialGradientElement,SVGPatternElement,SVGLinearGradientElement,SVGImageElement,SVGGradientElement,SVGFilterElement,SVGFEImageElement,SVGAElement,HTMLLinkElement,HTMLBaseElement,HTMLAreaElement,HTMLAnchorElement,CSSStyleSheet,CSSImportRule,SVGMPathElement
  121.  
  122.  
  123. /*note: the .href and .src and form.action properties always returns the "effective" url in javascript even if full URL is not set
  124. ex: anchor1.href="/aa";
  125. anchor1.href will now return "https://www.example.com/aa"
  126.  
  127.  
  128. HTMLBaseElement can fix this for all except form.action
  129.  
  130.  
  131.  
  132.  
  133. //awesome works:
  134. self.a1=["a","b","c"];
  135. var [do1,v2,v3]=a1;
  136.  
  137. do1
  138. "a"
  139. v2
  140. "b"
  141. v3
  142. "c"
  143.  
  144. */
  145.  
  146. var ref_ifr=document.createElement("iframe"); //use this as a reference for a browsers window's normal state
  147. document.body.appendChild(ref_ifr);ref_ifr.style.display="none";
  148. (function(){ //main iframe (use to get initial window properties)
  149.     var ins=new WeakSet(),cw=ref_ifr.contentWindow,ifrp=Object.getOwnPropertyNames(cw);
  150.   for(let v of ifrp){var V=cw[v],Vp,m;if(typeof V=="function"&&(Vp=V.prototype)&&v!="HTMLAnchorElement"&&((m="src" in Vp)||"href" in Vp)){m=m?"src":"href";
  151.        var pd=Object.getOwnPropertyDescriptor(Vp,m);
  152.        if(pd&&(!ins.has(pd))){pd.n=v;pd.m=m;haz_url.push(pd);ins.add(pd);}
  153.      }else if(v.substr(0,2)=="on"){}
  154.   }
  155. })();
  156.  
  157. //don't 4get HTMLFormElement.action
  158.  
  159.  
  160.  
  161. //note: a global, real-top-level function that takes the sub_env window's "self" object & 'fake' url as an arguments and outputs any array of: [alt_self,new_ndp]
  162. //will include at beggining of all sub-page <head> s:
  163. var sph_bgn=function(SELF,_url){ //include document.sub_env=sph_bgn(self,"url to show in js"); contents at beggining of <head> of fetched html, because of document.location, the document object must be replaced with a passthru (Proxy) copy, so simply don't include sub_env in the passthru
  164. //
  165.  
  166. var alt_self={"document":{"__proto__":SELF.document.__proto__},"top":{/*top it off*/}, /* << to name a few; wait.. make this a pass thru 2 the real stuff, filtering out only location/url related stuff. Don't 4get to filter src, href, and therefore (get/set)Attribute.  make document.origin && self.origin (get/set)ers*/
  167.     "location":{"__proto__":Location,"ancestorOrigins":{"__proto__":DOMStringList,"length":0},"assign":function(v){location2.s(SELF.location.assign,v);}}
  168. },
  169.  
  170. new_ndp=function(so){ //new non-deleteable-properties; source-object; (replaces 'var' declaration); like Object.assign(self,{}) except better
  171.   for(var p in so){Object.defineProperty(alt_self,p,{value:so[p],writable:!0,enumerable:!0});}
  172. };
  173.  
  174.     //note: may use random names for those 2 vars in altered sub_env code /\ /\
  175.  
  176.  if("sessionStorage" in SELF){//sessionStorage is full url including ? querry but not #hash; localStorage is origin only including protocol
  177.   Object.assign(alt_self.location)
  178.  }
  179.  
  180.  var wait_=function(f){if(typeof f=="function")while(f())!0;},
  181.  
  182.  KNOT=("location,document,origin,self,window,top").split(","),
  183.  vaaAaar=function(P){if(KNOT.indexOf(P)<0&&(!(P in SELF)))Object.defineProperty(SELF,P,{"get":function(){return alt_self[P];},"set":function(v){alt_self[P]=v;}});
  184.  },
  185.  
  186.  
  187.  /*NOTE: use new URL(path,base);   https://developer.mozilla.org/en-US/docs/Web/API/URL   to create a base object to help make the new fake location object;   have no way for scripts running in sub env to run location="http://example.com", only self.location="http://example.com" will work because of the way get/setters are defined
  188.  
  189. maybe use something like
  190. const location={};
  191. try{ loction="a" }catch(e){ var stk=e.stack.substr(e.stack.indexOf(" at ")+4).split(":"); [functionname,line,character]
  192. //find and manually assign location
  193. }
  194.  
  195.  
  196.  Object.keys(URL.prototype)
  197. (14) ["href", "origin", "protocol", "username", "password", "host", "hostname", "port", "pathname", "search",
  198. "searchParams",
  199. "hash",
  200. "toJSON",
  201. "toString"]
  202. Object.keys(location)
  203. (14) [
  204. "replace", "assign",
  205. "href",
  206. "ancestorOrigins",
  207. "origin", "protocol", "host", "hostname", "port", "pathname", "search", "hash", "reload", "toString"]
  208.  
  209.  
  210.  
  211.  
  212.  don't 4get:
  213.  location.toString=function(){ return "proxied location"; };
  214.  
  215.  so that location+"" will produce expected output
  216.  */
  217.  
  218.  
  219.  
  220.  location2={"s":function(oLs,url){ /*use a general location change function for this & for link click*/ },"g":function(oLg){ /*location get function for document.location*/ return alt_self.location;}},
  221.  Elp=SELF.Element.prototype,
  222.  EvTp=SELF.EventTarget.prototype,
  223.  oldie={aEvntLst:Elp.addEventListener,rEvntLst:Elp.removeEventListener,/*gEvntLsts:SELF.getEventListeners,*/pstMsg:SELF.postMessage,
  224.  inrHTML:Object.getOwnPropertyDescriptor(Elp,"innerHTML"),
  225.  sAtr:Elp.setAttribute,gAtr:Elp.getAttribute},
  226.  
  227.  ClkE_=function(e){var tar=e.target||e.srcElement; if(tar.nodeName=="A"){e.preventDefault();
  228.      //do link stuff (make main page fetch link resource); I can use this so that I don't have to change Anchor Element "href"s
  229.  }};
  230.  
  231.   SELF.addEventListener("click",ClkE_,!1); //catch link-click in event bubble phase
  232.  
  233. //fourtunately oldie.gEvntLsts returns a regular Object with each event type that has listener(s) as a regular Array, of regular Objects like: {listener:func, useCapture: false, passive: false, once: false, type: "message"}
  234. // no no no , we don't do getEventListeners because it's not a 'real' function, it is a dev-tools api only
  235.  
  236.  
  237. (EvTp.addEventListener=function(e,f,c){if(e=="message"){
  238.     //do something with e.source (the source window) to get fake origin?
  239.     var F_=function(E){/* call f with element as 'this' */},use_=Omap.get(f);F_.real=f;if(!use_)Omap.set(f,use_={'elms':(new WeakMap()),'n':0}); if(!use_.elms.has(this)){use_.elms.set(this,F_);use_.elms.n++;}
  240.     oldie.aEvntLst.call(this,e,F_,c); //woah, a 2 diminsional WeakMap [Listener].elms[TargetElement]
  241. }else oldie.aEvntLst.apply(this,arguments);}).toString=SELF.toString.bind(oldie.aEvntLst);
  242. (EvTp.removeEventListener=function(e,f,c){if(e=="message"){
  243.     //remove my hidden function
  244.     var elms=Omap.get(f).elms,hf; if(elms){
  245.     oldie.rEvntLst.call(this,e,hf=elms.get(this),c);
  246.     if(hf){elms.n--; //count instances of a function on different elements and remove the function key in Omap when there are no Listeners Listening
  247.     elms.delete(this); if(elms.n<1)Omap.delete(f); } }
  248. }else oldie.rEvntLst.apply(this,arguments);
  249. }).toString=SELF.toString.bind(oldie.rEvntLst);
  250. /*(SELF.getEventListeners=function(){Lrs=oldie.gEvntLsts.apply(this,arguments);
  251.     if(Lrs.message)Lrs.message.forEach(function(v,i,a){a[i]=v.real;});
  252.     if(Lrs.click)Lrs.click=Lrs.click.clean(ClkE_); //clean is from main.js
  253. return Lrs;}).toString=SELF.toString.bind(oldie.gEvntLsts);*/
  254.  
  255.  
  256.  //this function \/ helps 'declare' global variables (need because of self.newvarname=1;)  << I don't think this works
  257.  var DkLrI=setInterval(function DkLr(){
  258.   for(var p in alt_self)vaaAaar(p);
  259.  },0);
  260.  
  261.  
  262. Object.defineProperty(alt_self.document,fantasmic(self,"location",location2.g,location2.s,alt_self));
  263.  
  264.  
  265.  var atrd=function(A,T){var a=["src","href"],M;return ((M=a.indexOf(A.toLowerCase()))+1)&&T.nodeName!="A"?a[M]:!1;},
  266.  g_hs=function(rgf,at){ /*do get href/src*/ },
  267.  s_hs=function(rsf,url,at){ /*do set href/src*/ }; //'at' means is attribute, element is 'this'
  268.  (Elp.setAttribute=function(a,v){var m;if(m=atrd(a,this)){
  269.      s_hs.call(this,oldie.sAtr,v,m);
  270.  }else oldie.sAtr.call(this,a,v);}).toString=SELF.toString.bind(oldie.sAtr);
  271.  (Elp.getAttribute=function(a){var m,r;if(m=atrd(a,this)){
  272.      r=g_hs.call(this,oldie.gAtr,m);
  273.  }else r=oldie.gAtr.call(this,a,v);return r;}).toString=SELF.toString.bind(oldie.gAtr);
  274.  
  275.  haz_url.forEach(function(O){
  276.      fantasmic(SELF[O.n],O.m,g_hs,s_hs);
  277.  });
  278.  
  279.         //also fix href/src & extra end & beggining line (scripts only) in innerHTML outerHTML  (use Elp which is Element.prototype)   childNodes & document.all clean extra script element out;    don't 4get XMLHttpRequest;    Use WeakMap. (get set has delete)() to set objects as keys (this will come in handy for storing inaccesable value data associated to an object & property) : var name Omap
  280.  
  281.         /* 'target' Element property needs to be checked by functions that work with <A> and <FORM> elements
  282. _blank  Opens the linked document in a new window
  283. _self   Opens the linked document in the same frame as it was clicked (this is default)
  284. _parent Opens the linked document in the parent frameset
  285. _top    Opens the linked document in the full body of the window
  286. framename   Opens the linked document in a named iframe
  287. */
  288.  
  289.  
  290. return [alt_self,new_ndp];
  291. },
  292.  
  293.  
  294. rel_pth=function(r,p){
  295.   var iOf="indexOf",S="substr",bgn=function(a,s){return a[iOf](s)===0;},rci=r[iOf]("://"),ptc=r[S](0,rci),afptc=r[S](rci+3),host=afptc[S](0,afptc[iOf]("/")),domn=ptc+"://"+host,qi=r[iOf]("?");
  296.   if(bgn(p,"http://")||bgn(p,"https://")||bgn(p,"data:")||bgn("about:")) return p;
  297.   if(bgn(p,"?")) return ((qi+1)?r[S](0,qi):r)+p;
  298.   if(p[0]=="/") return domn+p;
  299.   if(bgn(p,"://")) return ptc+p;
  300.   if(r[r.length-1]!="/") r=r[S](0,r.lastIndexOf("/")+1);
  301.   while(bgn(p,"../")){if(r[r.length-1]=="/")r=r[S](0,r.length-1);p=p[S](3);if(r.length>(domn.length+3))r=r[S](0,r.lastIndexOf("/")+1);}
  302.   return r+p;
  303. };
  304.  
  305.  
  306. //use anonymous function for context (will need to fix 'global var' declarations so they attach to the new global object):
  307. // ^ ^ do that by replacing string of var declarations with JSON, ex: var a=21,be="bee",c=['hi']; translates to: new_ndp(self,{a:21,be:"bee",c:['hi']});
  308.  
  309.  
  310. var trapper_func=
  311. (function(){const self=alt_self,document=self.document; var window=self,location=self.location; //finish this line
  312.   //insert fetched webpage <script> code here  ( use these 2 lines \/  /\ as wrapper @ beggining & and of <script> )
  313. })();
  314.  
  315.  
  316. //note: beware of: iframe.contentWindow & contentDocument & window.open() & document. open, write, close () & document.referrer & new Worker() & XMLHttpRequest; For include, just use the <script> wrapper inside included scripts to.
  317. //don't forget to fake "blocked cross origin frame" errors
  318.  
  319. //This turning out to be a really awesome sub-environment API
  320.  
  321. /*
  322. definer func = trapper func
  323. one instance of the "document, self, location" proxies (new Proxy) for every fake "window/tab" instance
  324. access within the definer (sets the proxy objects to replace the real objects) inside the definer annoymouse function
  325. (the function used to loophole redefining those built-in objects)
  326. by using throw-away object properties that get deleted on the next line
  327. for vars that get defined by snared code (what's running on/in the proxy that is being tricked by the proxy) inside my definer function
  328. to be accessible on the "self" object proxy, use another annoymouse function inside the definer function with eval inside it and
  329. the object proxy can access all the eval-in-definer instances
  330. don't forget to put "var arguments=undefined;" at beggining of definer function
  331.  
  332. */
  333.  
  334.  
  335. (function(){
  336. //use this to parse html and extract proxy modifications from .innerHTML or .outerHTML
  337.  
  338. //note better idea: use iframe sandbox=noscripts as the proxied page iframe and run scripts exteranally in my script proxy engine, accessing the DOM of the proxied page from outside it's iframe, then no inner/outer HTML modifications are nesisary
  339.  
  340. var nullIframe=document.createElement("iframe");
  341. document.body.appendChild(nullIframe);
  342. var HtmlParse=nullIframe.contentDocument;
  343. nullIframe.remove();
  344.  
  345. var real=Object.getOwnPropertyDescriptors(Element.prototype),
  346. rplProp=["src","href","origin"];
  347.  
  348. Elp.__defineGetter__("innerHTML",function(){
  349.     var Huse=(this.nodeName=="HTML")?HtmlParse.documentElement:HtmlParse.body;
  350.     Huse.innerHTML=real.innerHTML.get.call(this);
  351.     for(let elm of Huse.all){
  352.         if(elm.nodeName=="SCRIPT"){ let iH=elm.innerHTML;
  353.             if(iH.length>3)elm.innerHTML=iH.substring(iH.indexOf("\n")+1,iH.lastIndexOf("\n")); //take out 1st and last lines because they contain my proxy code
  354.         }else if(elm.nodeName=="FORM"){
  355.             elm.action=rl2prxy.URL(elm.action); //replace real url with the url I want the proxied code to think it's running at
  356.         }
  357.     }
  358.     return Huse.innerHTML;
  359. });
  360.  
  361. })();
  362.  
  363.  
RAW Paste Data