From d07b07cd4584f46692daf5dc3e3312a4fe4661dd Mon Sep 17 00:00:00 2001 From: liukang <644012909@qq.com> Date: Mon, 10 Feb 2025 13:49:57 +0800 Subject: [PATCH] move --- .idea/.gitignore | 8 ++ .../inspectionProfiles/profiles_settings.xml | 6 ++ .idea/misc.xml | 7 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ .idea/weverse.iml | 10 +++ config.json | 3 + config.py | 5 ++ dao.py | 35 ++++++++ db.py | 60 +++++++++++++ main.py | 54 +++++++++++ proxy.py | 16 ++++ screenshot.png | Bin 0 -> 73591 bytes stealth.min.js | 7 ++ w_token.py | 85 ++++++++++++++++++ 15 files changed, 310 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/weverse.iml create mode 100644 config.json create mode 100644 config.py create mode 100644 dao.py create mode 100644 db.py create mode 100644 main.py create mode 100644 proxy.py create mode 100644 screenshot.png create mode 100644 stealth.min.js create mode 100644 w_token.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..c90bb13 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..56a022d --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/weverse.iml b/.idea/weverse.iml new file mode 100644 index 0000000..74d515a --- /dev/null +++ b/.idea/weverse.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..27c13cf --- /dev/null +++ b/config.json @@ -0,0 +1,3 @@ +{ + "executable_path": "C:/Program Files/Google/Chrome/Application/chromedriver.exe" +} \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..6c7cdcb --- /dev/null +++ b/config.py @@ -0,0 +1,5 @@ +DB_HOST = 'www.tixly.top' +DB_PORT = 13333 +DB_USER = 'root' +DB_PASSWORD = 'Yy5203344.' +DB_NAME = 'weverse' diff --git a/dao.py b/dao.py new file mode 100644 index 0000000..a074a99 --- /dev/null +++ b/dao.py @@ -0,0 +1,35 @@ +import db + +# 数据库连接 +try: + db_conn = db.DatabaseConnection() +except Exception as e: + print("数据库连接失败!") +finally: + pass + + +# 根据num查询演出 +def get_apply(num): + query = "SELECT * FROM perform WHERE num = %s limit 1" + result = db_conn.execute_query(query, num) + return result + + +# 根据演出id查询参与用户 +def get_apply_user(pid): + query = "SELECT a.id, u.weverse_email,u.country_code, u.phone_num, u.weverse_password, u.birthday, u.wechat_num FROM apply a left join sys_user u on a.user_id=u.user_id WHERE a.perform_id = %s and a.status = '1' and a.token is null" + result = db_conn.execute_query(query, pid) + return result + + +# 根据申请id更新token和状态 +def update_token(aid, token): + query = "UPDATE apply SET token = %s , status = '2' WHERE id = %s" + db_conn.execute_commit(query, (token, aid)) + + # apply = get_apply(1) + # if apply: + # user = get_apply_user(apply[0][0]) + # print(user) + diff --git a/db.py b/db.py new file mode 100644 index 0000000..db2cbdb --- /dev/null +++ b/db.py @@ -0,0 +1,60 @@ +import pymysql +import config +import atexit + + +class DatabaseConnection: + _instance = None + _connection = None + + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(DatabaseConnection, cls).__new__(cls, *args, **kwargs) + # 在这里初始化连接(注意:这里应该使用更安全的配置管理方式) + cls._connection = pymysql.connect( + host=config.DB_HOST, + user=config.DB_USER, + port=config.DB_PORT, + password=config.DB_PASSWORD, + database=config.DB_NAME + ) + return cls._instance + + def get_connection(self): + return self._connection + + @classmethod + def close_connection(cls): + if cls._connection: + cls._connection.close() + cls._connection = None + + @classmethod + def execute_query(cls, query, params=None): + """执行查询并返回结果""" + try: + with cls._connection.cursor() as cursor: + cursor.execute(query, params) + result = cursor.fetchall() + return result + except pymysql.MySQLError as e: + print(f"Error: {e}") + finally: + pass + + @classmethod + def execute_commit(cls, query, params=None): + """执行查询并返回结果""" + try: + with cls._connection.cursor() as cursor: + cursor.execute(query, params) + cls._connection.commit() + except pymysql.MySQLError as e: + print(f"Error: {e}") + cls._connection.rollback() + finally: + pass + + +# 注册关闭连接的函数,以便在脚本退出时自动调用 +atexit.register(DatabaseConnection.close_connection) diff --git a/main.py b/main.py new file mode 100644 index 0000000..7fa5737 --- /dev/null +++ b/main.py @@ -0,0 +1,54 @@ +import dao +import sys +import proxy +import w_token +from concurrent.futures import ThreadPoolExecutor, as_completed + + +def task(aid, username, password): + # proxy_host = proxy.get_proxy() + # t = w_token.get_token(username, password, proxy_host[0], proxy_host[1]) + t = w_token.get_token(username, password, None, None) + return [aid, username, t] + + +def main(): + print("输入演出num") + num = input() + r = dao.get_apply(num) + if not r: + print("演出不存在") + sys.exit() + print("演出信息确认:") + print(r[0][2], r[0][3]) + t = input("是否确认?(Y/N):") + if t == "N" or t == "n": + sys.exit() + print("请确认人员名单:") + u = dao.get_apply_user(r[0][0]) + if not u: + print("人员不存在") + sys.exit() + print("weverse账号 区号 手机号") + for row in u: + print(row[1] + " " + row[2] + " " + row[3]) + t = input("是否确认?(Y/N):") + if t == "N" or t == "n": + sys.exit() + + with ThreadPoolExecutor(max_workers=5) as executor: + # 提交多个任务给线程池 + futures = [executor.submit(task, row[0], row[1], row[4]) for row in u] + + # 等待所有任务完成并获取结果 + for future in as_completed(futures): + result = future.result() + if not result[2]: + print("applyId:【%s】,username:【%s】获取失败" % (result[0], result[1])) + continue + dao.update_token(result[0], result[2]) + print("applyId:【%s】,username:【%s】获取成功!!!" % (result[0], result[1])) + + +if __name__ == "__main__": + main() diff --git a/proxy.py b/proxy.py new file mode 100644 index 0000000..25ef9c3 --- /dev/null +++ b/proxy.py @@ -0,0 +1,16 @@ +import requests + + +# 获取代理 +def get_proxy(): + headers = { + "User-Agent": 'Mozilla/5.0' + } + # proxy_url可通过多米HTTP代理网站购买后生成代理api链接,每次请求api链接都是新的ip + proxy_url = 'http://need1.dmdaili.com:7771/dmgetip.asp?apikey=e2c93cc3&pwd=7e7b4dc0c932350a36142d3ed2cdb878&getnum=1&httptype=1&geshi=1&fenge=1&fengefu=&operate=2&setcity=all&provin=jiangsu' + aaa = requests.get(proxy_url, headers=headers).text + # matches = re.findall(r'(\d+\.\d+\.\d+\.\d+):(\d+)', aaa) + # result = [{'host': match[0], 'port': match[1]} for match in matches] + # return result + proxy_host = aaa.splitlines()[0] + return proxy_host.split(":") diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..105e57e8dd88abe9a55b9c70166dd62872af6acc GIT binary patch literal 73591 zcmd?RS6EZszAwzHuUG)F(LoeNdJ~Z*Lt%vCa+tA1^DMLXEoX9B(P4#MG}%bBy!TvG(1vPPLz~q^hQp7n3o4d zqotp5%F3PpBEuc^G{ck&Cv0;`;1L4RDZ8JgCiH{uTsTN|^x3(P=G%=ItglVQ1WyZ$ zD*jNZUk|x?!zff^>Bw5O7+JgGkq|mz)MP>xnEqK+UIrvBJ~}b6zP_HYcG){_r+60k zHwnp)z?Y}iV%uC)B(Dwm`1qD@Z=HH~DgsReK7JFSDP(7dBYr7d3qo-=dmk<&BO}yW zcc_^p9>uB6ZER;>Jo{~2lyhOzGB;Uck;w-mb#t+R%7>M?&<~ytYEL|^EEvd)J$-*y zWfFh;gXZphz6*2xMzOxG_52TJpTmzEsvpS4hF$BwfOmGi4X~iY-l80nr9Az%h+Q#x zrihh!Gt<3~e=lxR&2Ua0;0|)ame+QF#ogoYXz=6Q6^YuCLIe zU6cigCI)WShaS`^b(r}Lb;Z(8>(CTzoF|+&xr`K?Z>4(Mp|Op%K~3*z#u^#s9R|=a zsYPbKH)nlqB-?Q{Cj90sBAzEVaWO?`aeyoi{0vTa;s^t2m*upoJY*`e377e$<*Iv^ z0qTWktkGK(lUyH;Mi}03l1ZkYh%8kaHj+AqGJN1A+>gXJ@^l-5@5)eGZ>joVRGKsp zFxIMcgR`UGI}z>F_{Q?EzKfr{KBuo$@$&B-gMw7xTQ$V=`qdtax+4W%``Nh!0q8k3&q#w{8N9Wv(nOdqmh<0xJJ{qF&W9T~7qmgzxeqDw)>YUn5CW0f!b z#0G!49$*lb0dt=%|7vO^+;%=3D>5_%@-;qI$1rTTiu0?*5mZ@-?4`nDf=k77h3 zd|qGFb@kV>`*U&knXp3FRm4lk)9!M|K#Se>1cYwz<0H=&y`LeV8$%}#xL`f{QNd>~ zoiaYMLOzqwHX%Fh22h`6D22cAJ&us5H&w6hR90;%$p5%~A`;I@uGZtW4K2Ph^&C55 zKa|JW#Kfa(b@Sk!fbVe4W(n_Q-|+9n!pSPqEr##(D-JG#B+Xae}WuDMzP_&k=JKM3_*E|0x^q+sP;S{T`oJ)w>`g;UPBt zOt#)bc;Rkg+sHRBJ*T46g|LFCK*B0R;^%&VKHWb>Rd*d7c4Mkl9D}$WuR0r!Xgg^4 zyVcWKPe5OcR&ZGsvFGaWBWKnr=uWOQKsH7!6u!H@X>O)$fY5>`B3ri$3bJVM9;(e* zLtRtTQCu0TSr_t!?A#x$6=XpVEihES<}jpZ_nTNtUDy9qMmp86EPqv>EihP+7Uijd zt<2=HF&_{UXw|bXgaYI1bioUwY@nRGYCY4I9QHnT_g+^BrvURdU8?Xx*J>c>Bc_K* zV00sIwj(6=+ZRn7<;;$y9bEO3IGb*lXQ5~xc_+h;dC%}uV*hW5BXcNyx@w!pGY_Kn zzDIigVxAjM@etU5C>{NM(;KfD@(iBH=($m243Q8 zsqd$cQgLxtNQz(y2??&0xG1~<@kEjzH23C-ubJe><2(O@ql2!cn(>JV$ef~|`xK%0 z0P8Sc&QE^siEkP^^%+dWyM=84wWzkQt*xy(=vBof;&*;_MK)tBGA6$jkB*L>qygXk zX753({zZbGpg*ZPXroVl!0fO|e2SYJ=+}QulBxdl%%`0f{#@gKa#S=Ris{ynPpmJG z+!mAP=+igH$iZP6CoCRqJH*SAY&ass=7&k@WPApi$qWSC49)rR?jvsb`Y*>Q%BK?Rj@aWqUZJ7s!W=jL4d zSMF5B>r@rC(e%%%sE#`KLUZ(;w$qloG#S$iR<-RPwrDDPx@PU5f<+FOV;k5+XloI? zd<#svPHV$8<|Di=3by-}Cdt5BKXc^BbMkZq91L-l>L&L8j|4B3PO6f{ z&+Mb_GyExlg~6@AtWQKRX5Q~gzcE$1t^E?rBUZRcx!R~Ehu`)ojvCdV@ZM)1$l9W9 zW7L+bw`JaPsgN?5S!s1O`0{ozOE@>hY+D}|@J64ooeeTnzqk`D3Bfg;wkX&bSO<>| zHsQT=$tnHmTW4&-XFrKUM^_z_s89sg!!7?9$M0K(1xwt;M?7RhC7BsfFz1vJL{12( zg4@zJhBZgu=izVKukRMj=oZ=$5o>02?8JK<2-fD<7YlhHgfqs*oD9EC{*g ztV+hQ>ek5^t~0Eex;OHrYTFP8f6?7>Ob}|&Cp1|t#Q6&%-Z;llRor?#PJTP!Mehx+ z?K&RVr<$RgpGlcmh~3FOB)KbG0-%25^v5iET2v<@9@wU%;Nu%U4XH7i)+u zpX{sM_6ds~ypu94*J85VaLtjlUOO_M(Y@@u{@`dZ8+NQjQgQX*NUl&dfbcMV$%=5^Lb(8dw zpD;Y2wPDIyXIHq-Ny+$`vWNa7j2%h8o;%dFs87!|)|B@MS{+KGLgzlk$%odjue(!w z(^W^)l0`Mq%vvE^Z+}sDNnGnm3xZ)hM9jcdP8-`_4$mKqC~0^Ls$RQcoPN;F>uF1T z)E^H2Sdpd5>Q7Ei@Ob=s>PR+y($d?{VY3_Ny-hLmH-TR=u$<&9w!<|@{9KW>wFO?y zK|Aw@H6ECVM=0i-PG@z{_J$J-bL+_M0*xz@@0W`F0PzkakK4o#oljV8#&Xgus%J$! zcW+aLo&6;_Fa>&#qNO(Oh-*-G6;FxF7`qN?M}eU*iG929o%p zQ?Aq(dHbvNP=>h?Pv!mzw0A?9$a9{Lv7B8FQJ3!;b}PU{aCLosn^;3KrB7d6AUXC0 z@61p0fo+q#Ya6$Lb=Obn$LWU)etgpZJo7J6nm^b0pB-UR&Wg#w(z^l+E6%L;DQy)Z zO(B_tMmzfy0eIBnkr(rqM4%(H6xU}+M{NLTbHpMRW}j^7yMrN?QW9T~6RhjoP?t&T zSb08k#nX1k4#+G8{R~*_YU~dsXnl~6+PB22w^_H(uFV{pvfNh=`?)a`U&=WUfY!zC zaMaqcLTo73$mxv76+^|9JhhDb=#BX$h)=muJf7%`UHWOE)k@w`X29L)K8?~ga(P*T z;xN|LTBj1c1kbd%*s|NzYGZl9G`L6moO+m3-c_x!jy~6qVzEK zVa{KGwznU@mqQnh?!;KD{G+n0XwEy_(+r1_dCJD8)a>H-Q!qo(* zAAdh3)DKm?8cTeu6XU5OqDIRYXWI`+H#uetE z1uQ9aIO{j%rY*Qf;$DvU&UAU0y^XLpxM}BK6~>OPtmMSCilUyMJk3st(Z}RoK3Z=B ze7^)b;FM;tF!;MjCBfT)*rAh=n-M8sCudRW!n{UE0fAt#JOqd!@aP4EBeO34wuf(Qh>j|;lKhjp2M75Phs5ZNH65rHM zVqP}zQ?^pJItg61hk09jgE|K>R$k$iUDfWZw=U*c)v(+HvD3+NPP9ThkDC%VX;QVn z1HfB#aN0-Yt@NkZ=Qq@J5?NWoCG7T!vNF7joKwspx_?uToWvWOd>)IJ**cnECuaf5 z2$L8f3+S>eCI%_TQxYqQA85jBiCW*^Qvc?}Fo#Pa0HlO6(uy@Z#Edly9VOdCt6w$l zpqdX%9DmPr*%6DpmQk$M;X7X0ww_jA3%m<_llge`6<&9(+MV0jYzMqZM%Olv@K~=J zu!C@QY2V0j)tO0uB>-_zaz*YoH=N9l%!?BV}bdWDz&eJlBZPzk?ZR50ANs$&#{dJKm z68=4RQhy#%(`<^#=Xpfs7W>#oeRH2OPh-Y*dYR!Uj%4LjiU%W|l@2}Kmb~AT)5A0S z(@jSMbiuf^z@1%N+{kxrK9qw1X186?{fcv661{l{bd%JlrxS9`;Owyz4*psBDsxrD z(&%I!W)&XBr-YTgk%=q^$B-T%NkH?O0G&5uiGALLL&Fn^|OHi551HE{P_-QV8_=m^@~ z9+H)=Yj7O!-*h$LaQTAjP9AHu|NwOcv#);EAr zCK4z=baTz1bK@%X0n$?~Ta$e<)cqxAWnhmbP!=>w6DIfyFC{Mr0d%G6Mp1eq0~;@0 zGS9W-ohA82pX-i0Z>Ds79|l||aG@m{BNter0(-NeweLsmb*ZTz5eevapk8Yrg*nE{ zMkniJ+!j`fs%}(y;GHp=PDn_cFvQ$JGy&wf?@fH3AIV6xeNRth1EFH%%qKy#l$>)X zGbBYqmMgO7lbmU@MB`>69sqg?_YiS;O?JkHe$C5||J_&i_eyt*9ffDd`$TdFVMYmg z0RU0~Jdx#1rHS4Jx}79>W>%>Hb$}EVyZ;A<#a*e^r3iaOZfI(&NychTw(d`^1k|*5 z-domvy+>RVW9fN0^RtzeKd4Ybm6^JM9=M_)=d_1PE25 zNMd*uz{7#TLLQ2; zRsfy)4r;z&7`7(Webf{kxcXpI7l5)1Z7QFg`J0_8fTDPhY4B*jy{oGV(0i-6)|hmC z-Fmgxy5c=|A8>oSOyvJzHfWE(&h!T3`4dqLEZ*(j4LkUwx6rVG?px*u!U?85Vog;tZ>S27#f(IA^703D%w{jLJY*Dkc=IZ+L>?lCrxv8Yw3}S? zGqVQfB0BXupEJwqIVGV#e>m)11|+o)U%WvD_Z;hwZ8CFR1gI}Y3_#9wdic=rpU!sQBHS7=!l zVTxnPG=_}PXYSfRKaRuJ{6w0YYXL$;W*HP-T13?Q{U+vaI>DN|`;Tt8N4B<}yopmE zxn{}#iF(XxB9gk{X_zwrti&BJ!dRKgjTmfnBOc%5{Sc-nfz+B3ao?)ApcwnrcMk06 zl~-qQTB1E@nN?V$#x<6^x|N;$YEg3TD*F>8j>;QuWf;)syt>Xs^M`GFYjsi`(^FA1 zcA!FG=7`3sy$>S_XghcC_IZsmL%Bik#@gjFN}tI{Y5Jj!IykFCb@IA5x`^ZV8+?6b zR2UX~J0Zj~md0(5v`TWvx$(<0x18gP=pyQN$V>4Ku-CAn_v5N6#frfQwD96^K_%Gvr=7*Q*(@7Y5Y)p*{1hfRbyOgh-#B3 z^6O6RzL+PzJlg5?+&s0xtWmPZYwE)xVdsm3)o%Ju@Jr;LvN&;rMf{^Jwm3OB9z)gb zv!j#?ps@RJ3MJAfF83*H*pQx6tY3S$E`^3q5$D{G99&s-qaH>A6SMYmaJ*D}GFWaEYUs(FVP3@?Ih)76OR}hVPNDp~!jRS@sz%XpbaZfVvNOupyE7;)0B=wT z?Y09@{0@5!kK4K!?ML?)gQ-g|M}^?-4Bk6R#FrbACYIG7QSL<(s4e$Oe_2vuU02r< zzGQA$y=F>Ee1dVs023Y5v%G~Mt01770)%ryyh2n;ov@tel!!HfLNKa_&0l@rp1VO5 zk2>BYpr0P<*f$Uu8ObdE-@PmA` zr}$GE#E44gt!kH^bfX=D{Adg=xg*AD-5KZdlxtn&tX&)02VL4KuZscdoRbLKrRrIk z-%u&gDM*nVN*#55v|@emm$l)t&604Om?C}@U-JhTl33Wj?WEehPI=K-B80NL`bs^N zlDQlZe`}Z}&osCnY1aPBe>kmQT(mQ>2#~yHi25&%3VMP7`i&Q~JXcHBbtVBpM5zKz zaHLro%+#yI4%GQ*oJTU5YGhbww57{bN7>l;wEGfcK2`%b%)YCo}6bG&2c?v|LY&{w*P!mK_4y$|cF zerWV_iN@&b1~W0G)RsG2bSHNqYyFbV17Y;BN5Mb~BHfsRh-+SId$C=_AzF z>nZv;o4;W+4%z8A3H&#VqV`zuWXh73mrFojGT8FL{#}@aqEslsT9o6wY1p%i?-gGH z9aI%83q|0&#vip~yu_;I*V;=9v6dyrHv+T87>BwxA8%{NT%%BOU7&Su$=clou`PKH zl;jAz52U{{EdNzC1Awl*RAsvm1tqQ=6_W*exw|&F(npAV%;x?Kf)%&^+-$MX*Zl0+ zpGyC{VBvN!ae6X=^BF}1TUkH6aT3U9=kD8e%y&8k+*n*qVkGJ14w*M^+LfGnJ;#lO zn{to=zDmI@@%bhWrhNV&OMQL*RqS>mGAd=UDxMKATUaQ>EBgBFXS224gkxITnUib6 zS@+SivB#;pzLy1sc_6=zJ6a5fF$&CWCG*Z>H3{fm9NUo4eI`5m*`G7oA_|*FJifc7 z`U#^;*ll12{~(n+wLV;0Hz4uD;?cWEhy(_vr2rY+qc^Wn^xVz;!ev8gERG+)cDnR{ z7h6q)6#j{(KruHaSjBZ&Td4c~ul|t*u&Zz(?NLjxV$xXL!=+D)&JGWNJFsNATJ-m) zT{U*wY3Oh_qgy)6QCwBQFJ+QzB68c6IH=&q)p|%82p*r{ld)>OnfeZUqb&Qu^g?O5 z(|Oqjk(N1i9D>1k__5B$PN$)($?~y#(%3B3BPZ~#O_ildOQDe@GjX)t*%I|xkoCRw z+T7<`L_>IdT0=%}BRlmad)V$k(*JGF&FF<)}@v?Keb_h;Ra0`)tW9~DqW3Q zw&s>CK`h@4oS+rL`ezoD{~z3;^-b|u)x@jKHq3eTLPdh_$Xch?IBTQN%uo2e}qvRRU(z{_FqcKV2NjrpPz1CmpKL9|w|gxXMc8g?QQr{e@QPWVf24MCj@s);O-yccn*LInk(;a z2_YZ)`aX4~C60a)L>C0*c`j_AS_RbMQV0hui69N`vugFNpLE_pwPOA4#z5>rY#E^5 zE} zha}LTqRR)yMI;*m|2p%3VjchM+}{N$ZOiO{3J%RF&QH(#{4mJj$uRK6XSLn&S^xO} zVb2K~LiUP;1T_dK49u*RxegjebFQC(?9wP3!HWX#InxHJj1AK$+kxMu#*hnC=612^ zIw)yNsApMR?Q&4t4SPLx_9iB007NnXpt!f)p8F#B%+tHuxI6DbNhi&a9e@me`MBIy zrc8eQG=1aF-@@9c;7`6-e>NaBV4ci!U6l5tiHL}f`N1~~;};V%8-SqGxV~fZaghuc zmK<@?(oF5RY)E`_zx9&iod05;`|(H`P;`Ghs;XiHztG=?+n0O;Pe)3ZWh3Sm;?_** zo3*Mz6w%RX1x#SW0F|7$14;sUmIER)XTFi87XV~vyp=q6FR<##k#WXxQImOg#IT@p zx4^Iu+zUd^Stg~cv8`8{9w4jLJdLFpkvgy9(-ck4{YgKiazQS)cssFic6!hGer~t4 z;sgvo7E>ra)7MV^ll#KqRU>i9zq%D=zoNJ2iacs`p5Esv<-z%J5J>U_BxR*lM1PKI z)aWq72bABe2!S2sU2=--Al3Xy9AbX&){VQc3$oKMu=+%y<9rf9=#b;A=@gphw~5yP z^v#E;+7^1Y3&PsI1|nLML!idlDwx4bPjTve0Xm2|qGVCpb-!IU`qUK_4=RXsXFFtAF+sf!zPXo>pB z>oaL8+esa_jXag+l$|J_wG4r_H2hNvxs8FC&s}M{GBniws#>U%f;DcfurS0F8~Y7W z^GzVu0>s9a@0zwozNl~R@Y29k(izb9ITR;fPa+yYN5ToY*m=;loQ7~h&Bx)*{lHuK z+j#j#whkaLv#&2BJp%r&k_Sj(gQ75QdX^(KJy2&D&KB{dbJ*)^q^v10FN}T9rp?B) z@igaEo1ur)K=KCB1_0jbSVRzCHhyIrVUbhi$WH?9`9z z^-o@E-HJHAW8GPPWM@Je2jR3}M(gc!82QY%s=m|A#HbDk8V|2!+#)CTsrNUP1u16M zOE_O0+37%7^y>9E-WMFN0P~yAV6_Cw6LGP`LZ`ZNDz*4+6RQ-fx}o-FfR95`7k6Pn zksbCsIhM02weq6(2KX~Ir50-S1y?B`Fo3S2wKNXHHL4?F0;Ny*7k_4_s?c{|PDCU&3gYh@*N6 z?y}Uf_EV$xHKB-e0L%}F+9!2NMXBS9#>Y*)zur20Tg4_^RQB9uYNM(5nW-ni?3`oCZZS@MUt78*)ky}!x^z2_Le z;7}IV*N1g`nVFzs{6H-4bbjJZ3cZBy+&A=hBUc`Ly$BO0klFC9|7ziI)~zJydP}T< zAkU8u0A5t7{TsaCISs4icE`c0WTAcWplg@VX+ctLRA;K4j_Ygs>7$v(v1owQS?V+B_go{$ z8p!`7Yt#d>Mzwzh5JZbNW7jNq8^hVOULfC}m-3!W&rDTO;OdF*${|ES7fLVd;Wu(N zI^SN6r8W+_cO+`CftM}FalL{3RPriK2Z-l|)cQ1z*8QL|#4_hhFBPsp75n+{TNTD< z^>R^zHW173In+1UtrCr%n3y<4IwuQ08klPK_2q;*AKx;PUG%BXBC%7?ip0Jkrk0+r zrDY4E)&3$G+}+wLS-YEt__}MwE79H;ya(y+ zCkp!H1zLDcDhfk!c)-;#->Rn`He_YvVG;lK_%nEvZ1FN>=WglCFTj?E$j>P@l&{ z9*>r*+-m}DwkU&+P|p{QCz~;xl-h_*;R><;G6HA={Ria}z9f53yj+VG{at)4bd`w8 zUzbKXn|Lvie^usc=>n|;ieR7xI$L;&?JPpB7gPZ=Fs*~t1=xoR9U+oavU`!`LXHIi zaPCK=P>~Ru6U<-(y0&9=$gS^k1uPp77V+~u3IzZhH=)hmHnsu+Xw);j;lK3!Yh-9R zOWOvWv=k|cVCMjM!UG16?0h}b=x8)Mq!p+U!HzM;G+C=c^6nI81~LpQ31xyfNQY0g zJ=!a?Rk6!#SOOZR?~l( z>gVmsm*?s5vRJW+!%=E?=1@O)6TMkKPkrO@U?o7cfzM+`Q5r=5_nb7`@VkBya3M^S zWg32+FYbk2))a=p+wE$(a>R?Xu*d6qKsypTeNbbkS=n2qJ?VorLj;~qhOPKQ%^;ng zE!q}bq-=Qh6Wx(M=@)3Hse#$Kl3Geag0tmd>%jz%FW~Zj- z0kO+}JBC>)DVfdAKVTj;;-!l}li_{@jufOUXZ}sI%R_Ge0C~6~pF}m@w2uMSb2)~t zi+~k9`xv22PN(lV$|JeJgdG>uSsu1)L8cT}mghRzFih*qBJWcX0u(^OuH`vgTpp53 zuD%z@RFMS-;!vYnT~FGLJ8a)jQQ4xBQhvow$l(vO*3G56lQ7_A~<#m)yr z=7f=-3{?66wW6MX#j2mMvu8u`6Bx2W%D16|Fa}At39Yi+)EckT`!k;?g!i*Fl+&El z>A!TjrJJARfq_hg<(TWc!eR$wDl`#SxTg_wxS7{*5h}*kfhFI`3odE7-G=0 z7A&DXis8^!(MDgIbNgbg#k7-Dst`p`0AHvQ6~KDdP7C4+U5~yZCAuS><>r@e%nG*Gu`pe6@R&m@dEy~ez@_@aX{9M}wiC*yKt%R{&RlJ80 zmeA#(rg}`@X>#jHq3?*lkvc%2XRbfjw(q0X9>NGn(16)Os{bf{f6c-72UUqH7)fp2 zkuz@xD!k^prt+%6yhC1!WR^ruMg%6I;(f421Pa{JRdR6RQWt=oB~1XV3%;`ZOOn|# z5FjRJx>xQVknRFbVUXt>)7QV*)Cz~%)R2jpWnBcQPx#NTe{8vPE%Z?}ax)vFpFfO) zBFvIA?B&DO=IJqUop0gMW%n79JdHoqn0+L;f%q2y(5nX0u=Asg%KF>;{HFn)n22VW zRv4vKDymqV>g)}8)q>_*&qc7m;;r`Fal7pG*sB!oLu2@Bt-u zY+fNSbUq5K4Hu#jn(Q?EhRBhVWXQK#{Pf58({0FHweI;mCyb>uSSerToH7(=2}~So zKZ|E-I@BCQI`7NNubWWAtd*1+dc;TeeA_1S2Yono70wF$;0D10REzUY$R${SM=Kfh z)$B;X1wMX5N>JkPND%l92Q zk!H3e8{*7C-0gf#Tj<)0V&-Y~112;e7)@U_fEIq>U;^B~J?hQfx$n*j=i%5v6z_Gq ztBfsU^)H44xv6OGqV^FLV?*y_9T2Wm?k2IDwljjnoA^!45b-WM?{?UK0=$6i*1~$h zedc-NSNGJtbjsuCm-iSX4}_8!?lRcGE*$+_({RuR#MEZbSSn%b8nxW$Tbra z1@7>iv>M-fT#g5WW4uNtyW5eOMYK)i9ZR|<9))?>zW7}0YS+*4{f!bc^EK*?=Kc;G zD5wjB{^9mvqelu5d*MO1EH89^couJrDFAc{AT6}PSrv2za?Bch_w6mcOn_00G&WW0VX$HkJ24h!bHuaurx?B&dLBTcJ_uUh9RcN?BJZ&xR<& zbl(y+*l^!K;ZRf8t82|RGmo%OfO$SSyDNgAqFJltf(0iE@|~83ff%Z)JjZU=c-ikJ z&I+MJSESIT9K`q4KRzGM=%W8dXS1FQQ^?U5RO*Ix(inx1$mKCN9BmsMjJWVSz0%}M zfWZwU%+W>|5X1aqi#BezXghehz)P;Xh}y8G)w~$YP)Hcb@wh$|C;GC+Ep@eeYH}vN z0m0;b1 zYhKA%c&c_(zyYU+XVKfa;+XNu#ZIB>R(UeEGgTzxT<=Q#p-dDrzqoftPsTI(5!(*K z*WF;=S~23-dE5lt2ndsO1(nfh?kcWW%4Zctr00b(yjUYYEvSC8zcZO}J8n*}N&!GOPgQ&UlzR7Y z#JMgFO@$b;TB?(`bqZ%Z^uPx2FJ)541k12Lldh7gdLz;)hhq{%=e08+m>t|=MKAwb2CTRPtSZ&MmT_c?0 z*CEvzz$3J{Xo+&Wy&IVHtva{#)l0m`=Z4DK7Ie|u9A zAkxKIvSZV%0NvL8tp2};Xwt>X{l|Fz(?glD>-7=zEtm-Oe8p8Iq%o}l*apxK=3GO4 zB$9QuS2JZ~QsKO%MEKp4+;X9lf|%F%F$dsY1R=M(xD1Hr`IMlrld7wv#4SUdS)Y5c zh>aJGgPIG7Mp2EHK~^ME&;PAWm}dC$HemcSNX{9d4`_igsnWU+4AqWMcCIm5OqAJj zxhM~+wdfz~iMd>&+uGVmYzo-6a-Ct-6_^2~h2gPewU6s-Wcbp~yp*s!e)2Zqe^<## zYgv4_PebPc_Oq_zBTtI6wtzVO#%A7I-sDRkzT zNSXo~<88DPux%OmOvV;{CDU&^Vs3Nzy#^%%IIdp5&PoQ>oMDUgy(5|jj%jDUAr1ND zemhB?!}-eus6xM#W>%SgT}zUg4cDuuE-(rZmS<4!82ARTmsa-P$0;DxeZ!SV zL-G8C*?JRlzvO6jz`N-!eA*xv*qL$jbn9_wDd$+zBmR6saYxlA&PIT1{QVD_CVx6f zmpasJw%7m*q*tFD64G^i++4_oX^sG>4ZrsatY?8sxSuO9dz@y5w`!KSID-#|iOdv# zA7H&TLVG3B`Pr-St2YXZf%KSD;dr@)rvV^eDiAhIjp*UD#Cm~v>Q%<;GvDJzG)KS% z&Z06^a;Tp*Zqnp}WR0A|u;%88R(EwG(ne4L^mS+fGyF_xYx-w_XacXjhh?qPZ`j_~ zeU7>D_}taPBqg89T%@+sfKT-1c|J$t96f#p42>+CrU`~=IcsEIv^#Et$gTy zS)au$g0``+_EodgWAo)Gm65IvkP`-=9pF42S~^tMg0u^dh+d{-M>) z7s=hk%e9xK(vmkaK34SlxP+Ho#sDj8?X8ktpOoS70vXKYeS=-YaN>ls4FuM?uY&Bb ze`Epv#%lovD`F>_`Q@_2Nn7!U!8_y^S<`^Lq>1~~*HZmb9$+1Acid*adQmt1wMpMr ztUTkfVHV_yr*7<#42{}jr^Wl0vQ_~(VX|j4T4fuyYv5>^Wgs)ID3FS2iSIGX(&-o) zhL*Lzg`KE(gDuW`ly)SS2v3{K0#4F`rsHOH+;b)^3s^>x@084ZQsKpR41-&3mSDkt z%tK)SQtI5-n^ZTldR#Hh0m+!X2Bf|tuwe(516KCiY22bujv@jroD!(VPR+IisUcNh zWBe9fd}{3m6N+6h00{{2`fV%1K8Tr*ZX3jA)~=nnhDG?^?*T7n&+Ea;qW~?W zPR<}pSOSw$&wi1^P4dR|KWSKWs}~?9#nhf(d)Fn_zQ1?%PaYOX#GS1J(Ff-5RG%4i zgE@UZqm=D|!pCF5MOaRp*RY<1{T?y57?hK>ir3YEhZjuw8dk2pt|Wbx)C35Mw2-aH zLuUg|^$2)M_??9lLw&c!J9FHa_%^tS9P=nPt7(4SXuokDnFKYrj>+9KAXAMv6HZ6?4S{JjAyi|Lo)r z@$sRTXub?h0ULB7^ZSk?EI@R9=we`S*%(eDQ_0ai-#{@I-&3h@@lkJofr!VBTMxuMys6MP1nTr z+)hE8TQtV6r`oCoOW-1>+vgTdbq~GqS^aL9=(vj?P%6W-RwB9ei*Jk?-~{800skXQ5J(#= zbzlEaY1z^yB>-h*xJEcbojCO#2jEP~k-xZjHk_wE*LZ31@L2BYTw)FbF%A}MKFroMk}%!Ef=}=J_CCa3;DBygUd*} z5RVb~@X&rIB$SlRWK+h2YjYcZYqZ!qx(6O`(>j$_ZgINz==6QU>8a)VT75?T_Gu(K zG9&8JG{yJ?#RsuV)gJ!fp*gJu-qJT}h!I7#?Bt`uRr_bC3FDCtci{>>AgkhD^H`xG zCM<8Dfgx!qbSob|#?4uBL4Z``JV#7Mu)pw~IoyfkYueXO>EJUQKXL5%StQ(@@16ZZp4buAIZTz?TiD7U%E~31{OG$e zs?wi7Yo@(9-mK^mpBq?H6?)I8W{F!CED4(_ds)lNwXGMveC|ZNBTRjz1A1J7QWwbH zTRsx2;UQCcQ4F7$uKjVcj%YiD(c~({aCUTuNwEGbeS1bwpXw)Y%{#4eS?PIXbAY$q z>OA_?ifv0oD+(&S3jJU_(Ofp=H+m2)hC$=jeAhy37RRgL-wY{v49lUlzK-x>GECFU zW2GBGYg-6P1il-UiM}6J)}(G^NKLtlX-#82CV9vq5iD*4axDLK2iv~ zHcu~E_=T0uHgp4-BCl5AFS0;;Vn=+ltT7Nxu-|k-J~n-sWXyo^3_4(a(V{3|TjYN0 zaU&=$Jz=hb{jth5XZH!t>Q;e(EX0x#bKySs>397&lUrV`Z`=h6vKM8>jZ7^CIpm#( z3JwOWJzE}0XA3h~Dm?T+ZK@{64L*GCn3Orzwp=^wVyE)?b#%4>p<&{Jz2k$J44?6S zw=iCuZsxqmNG-k#dXV!F;1cSOe~bI_ycRa{&7t`n&8Xh?H|(KT-31y|BOztyvgz{v zGxA&+!#h&lxM2oPLRDF5wC<>ZN6zUH-or@Pr|bx=;s7?91dD|+s&9`IpMJoPNj0~ARvuSA@KK9LqF$zL_V0_#9-@HvN9C`h zSw1%Uf;euvnP5{XP}gXV!d&&H#_zmjmY(064j<--4!^!`8px+u@0diBcxkJ^0fH8l;wl$6s!*h@>Xq3k5l}~qr`$m=C7#m`nthu zQZ#k)%|5$TJ?~@fE#&NEx21a?Y9`WOuzp0&uCKOT?wzL1ZIm<@7nl!x?kTCUuymN~ zbyN;Iz}j0%f_-ss4EtgR6f-pmp9%(^%SIdM2cb!D#h;QyRr=4mxNkQ z=o7C8%K(edpQ}z2^zui#rVF3!uou$|%iQ-3QEiABc%<4EKTxYN2z2i>&R#xM^2PTb zoeDRJ_`1?9$~j$@Q~okIube7gt)Eek=MkOEl|9ic>z)itgtqR|fGg9kOg|hN-OXT5FPutW`kD@|1u*)o$w!vmah;4a_0ou~kLs$nJui4qdVAw~p zvPolfS{~C|>_>-<9MoO(Mr7KS(nIPjiae}Kv9&0N9t*WwSy`6Emc7MBIoDMHe|(Z} z!=d+zDlJPdoQJiVyrgm4?ki!bLN>!x4>-gF_4~{ zzl40IT1Gj16^FwKTC`V|n4ahTadP%QZ%oop;Rnh((txehFsCX5Ly3<#f=K~Gm2^nth5;ri1G-8_TU>)zVn0jR_uC&5(mPfX7HpV75{Kl0W!^qC1?9EpqL^TH<> zPS#G|UEN=_I=Wy^BjTVqVWd6rdv^)~GH6fDE07S{-FH~!1UX%3BF3c_9CM{8Cn|8- zjv)eKtIlrkw^0}ny#znM+i^Ekg4g(!_5|%I2I6C|*I`=m!o5tzd^L}u7cuZv(#t%E zI1CpYo2w>|=&>GJjoannLDJtPCr5DGk+Xxy9;gMb{h2!qvFhVAa{D@+aOEjmUf758 zhcdqnk>He^+#TPsQ+d>hK^d7jRnezm(#t^a(=emtK@-Jt4sqs*LalfaHo5V zy`4&C!KHY?_2$o4=(t&uv02g_{H<56_qcU?a>Yke>sBcI>PnDRX?C^qw1-q1KE%71 zY$&~BeYqrFRXjYF%pmDKI*A`v`g+SH%&lqk)3RG_aSgYmjcrdlJ*EN+kIOLvc?>mt zORipDCU)kx%gfX~>g~77cIq}54Nt;+gL7nKiKxy8PvFgZursGUGL$A}&s#u4Y zBXjwH^tO=WTpxr+tYj~m231BKz zJ$e_X*St&l&M+>H_uYLx&RBD~)W1C>3=2MkctlNSao2Q96@Iz9C^V6;KsF+?g(2@0 zCQxh&U6xjIZy1~(kh>y_Ru%*Lj&?z{`|aDi6N9cz3B>Z}N7Fw4VZCO5Ao7jr>P0Ti zpiC|4xj;(hY2nr5ijfI?#Y84;>vQd}ia`fl^{SaD@&J!qje0}SduA~ zwPxQ>rl+k)sLo<)Fv%Bh%hTc%b5H-~c^{e(BpJV9X_m~%Rj$55zHEAVS3i1xlRd8^ zmGghG_m*L8Hc`KCol!d^*?Diw_AUlbN|^*3A6Yf34A=eV{4(vd`mWHp7JwCLzJo zAHN%!(Ym{QD__-0a`&l0@S`5^1*&2HA;ugIUEt;ygjGsBj^?ko`_%EJVUA%DJ~_{t zrc;lBOB3#88GqUcEPxKKA6R00o_oK2F({i)fWISz?3EGd!*Hv>L+wU}$R{3bR zo<9T9RVQMFDEuKfPL^d;!cP>FDCpVUC)$%#)w_E3zJ-I`=+iU>X1ld!@%*srypCJ< z-XV6s-o7Wh==fMyJ05IZPulj2$m^-`hcrl@HEkPY28p9E{q}aObJ5;(zAC2}di-!I zre=aM`S4Tcc)H`V8Nph#@SF1Is`t{OxqK#yn=)N}YHORG{2nV^ZVKX?BSrBo-zSU` zf5Ms1xYAnSg{wA9`G>^;uU5eY1ZJR5Y@|g3J z_gBjx&7L9-6`8+!m6fqXch~eQez38OnU3>GK0rLCetN)jV$~pIylaSlv5{2jYp7fp zjWru5SGQ#mC3WFs7#3YNO0Y(NpST+7_IO9!WU#j3EmS5+X6|7$g?FXl$KvdkR|%nc z5B`dJGU@{h=xF%%L6l0LDD%|$DDu}*@mbeP#|*dGtV}$FK7PNt4T8C(Fuu!;G6$DG zJ%!AE%jP6me{q|0?xpsj)#^ps+g?ZMx-pyA8XbEY`RyP3MR~gQxDSrgRN0SAbOw;Q z%C_rguB*4VguM>WL(pkgJ#}0RY+x>Jpn7tO$(eoor=3ST-Q+?W-MfU}2{P^-k!wO` z-G3c-c0^^Kd)*CryxjmBynWkEK$%+DDG#OB8DfHiMBMho(jOOGY>N_I_i{p=B~l)3 zLAt{wokwINN17L)P28GIg`p=^3pH+?TYTE2tOsuwYmt7xzcg`{diX;%-*z`T{w~TN zSEMPMW67tO*||@fy;f-zxwklBkUm;L)i?jjAr+f^Lsf5ACUOLVCEr_k5qfZH*_=Y- zs3Rd^$iy2lCF;_rRxeRg<@~xZQxCRG2iopT(t^}^|DAhgVpS;9+r|@zy58eSy$YZf z?gpkCbmPMGjr)%Y453|UvCmEmdq0;i3y6J#QON#mv3#9DUx8tdKK$~{%x&oaECt_Z zLd))*+cVR<-9HDyN*WJBs%TQa@UQe?wK#Rj|L5~bC!Z?x6!(b>`wQ*U-_JmZ__K~tu4hq;n&2;F!yZapMCv#`q)eJS8_)&Fp zgw{1azeiWuE<~D7v@#do^U7_72oC#Nzkg^n#RQ5LtQzwB4)3jU^fGv<((+5u%&d9H zZ-SJdM%y5XfzEWYa^NDN?)KWFcqQL173Wt<4TO&m-ZE`17Hmg)uMZ-mR|>;9%qYFO zqcfLiLf#HWLL)@#OUB!WeTO420(*p6zYFjS$TLfI(^O^hEH_quyVxJoN+eIBQqLwX zBE_$(lVKTmc@tNaTbZCj-?joaa=V%u@Q3`Q-rBETKvQ7^N~wa?RgO?Im6K?AL^xEK zO!$|X1CDK%upauL@a$7mh4}exC%k5Lzb3GW(wdr+c(vx1)i8o^XP72gR0%;X=(~bA zI(u`P&HxP*q~T?KDdC8h9KlFO*Ppvc-A6|8jKg-~9Hi>td=%*WHiX8{S-H2ZWKCqn zIM2aQW}38|K>=9Ha(8DUN@Dw6qW?P6%#)Xs>L5k$PM%nWc14VW2jt^i{sQ zr5j(E1bIRNWeQ^<9TzP4`6T#J5==7A#MUBAedz>_I%w`d$+1oRlZKL~$J@9zkxXx( zOJR}khIh-2MM&aL>XZmv<$*7_*O@57S*#-`CG+wN>$xbl^~wf)!~<+rzcDRjso!aO zJPl%lP|(-B)u|2Wl>%5jhV5!>*#le50kzt7fK1})2ym>>;|Ed3r+7^??0n1Ad0+G? zs{a#O`LC$-n}mRYW>MO1@^OZr=DleCo`$e{T<+K&)f_wG!w7ofBV}2lmcrdJVVW5j zij%T)5>%8(d^9Vx|7Nqnpx3!WL3%h~;oM{)1vMDoHSz$Pk3}#e%lLg@$G)QjZd~v{ z&bc5^{U+?FbcUqzg2YGp_ifgA7AqCl6Z+fbmcD8ts)j8pYQT<#O#eocaU{Gq=DCDqeLv$!0R;dRQg$ ztEzy8Q>lySb=T=5L{d=ZlCncnHuTxZCsRtRQN0M-UK2%17g+G96}|J-=HB_}5S z1mNttFB_DaCDXUxQAnrQO-^OuDK92}iw<-+Qi{@qsjw=-s9FdUq=S6KUF8QfE&)cU z{JdleYK2wJ$&XxxIcJW--~$u;2<3 zxTqOfYm;wCyF^j;7;5YiYcc6S_31&tVfM%jAAdRiz?CD3BsdUU_l%{fu6fZcthb)O zf_H+>5I zZjmja9{(_H+?|j>pAvluXEa$<29Y?LTOC7vT@Yj_8>M&mR3Ic?r^}9w1ZK%?@bx)c zrKJHpkIu+say?|fo7AeJO()oi{AYo!-7359M_O9Bjr=#k^TpRW({8+@UIdbj9r{;J zbzI>LeGQGOkk(%=o&6Ma&%1NjbV7B~$iN^Yc}}gLdBk(fKt3dc1iie1DKFyZ59OSY z;Om;~|CPWAm4`*f?Mj3nnJzco!f&iMkJs#9Hv;fQYjoTK&>&tBn2E8H*L!!OxgoS2 z09n>#hUEthyiR$p%Q!BU*R832)*Y2o^OP|v&A+UxCu-2t48f_(qb4B-DbKwGqe8Y? zhFKb4?I2K*cB1&Tt$qt7%fxRc?E8hX*UsH{)N`uqPOF;4umWx=me3_|Yj%+;u5xwG zYO&Y(a{nqZ=myrzON~l75$9*i|bjmU+ zuOe6T%o>ubf3y5WheG(?Ec#nDaw=MA%CP}YdOiK4X0q(+FN38o0!;w`;6prO_kMp> zX}wF`c5qoDkz|leS&daG=@cDvOFEpGA;9Z#d=?}2UGnVSF#k@0qVyhXnXob*yJ~P1 znb0mRFdfFCbLgd$W}<(w^)NrDR7K#m`xt!8J|6?Blfj5>ppz6+RT`U7tpE4b7a>2S z;M9T~6@sHpR5hfNnqXKIoCoCDGau4_FB);PG@axgKh(^e7`L-XGRfA}NU3_21k5CW zYE`AayD|oH+deN$P_YV)A_b#705&YwDlD+npTgWomQ^W_&$G0UA}zU=v24BUyE~yk z#d^M{Wivi0_M^i&cNsG?egoX2D$L2mZnQ5@@)2Pil}(;ta;O&G8EH{ztG!j!YhjQA zvKR~fqNxkm5M9%lDgZ_mY#H~4JOckISFF#Uy3ZoKkCU5yyF0L)EU8-wn0qZcns;?f zLZokL#u8L_jx^}J+Q|Pb593*?By}D!?(QP;*>6>hWCnEfKNSw6=_jLcuz#;I^|HR28WWv;4EL(7H?hc|5kW_$82*L8#s1%0HGN%L`MqG)n1K;a?1^( zH#qSfOzleLN1Pk$E#k~T#+A0_Xbwz1uFsz3OJspj)gHfMY6q8lqTm>jeh@#r#b~eB zIwz2*o=lO=%ncqP7vx%*765=cN>=%zR)d(r$7)x^RN%C*{-36b_uZY%v16K@;k4*J zEe3`g-FJ}DtQ9H#C5dEgjojMI{=jyUAX6*S)=jOSArIbvoF+_{p+R6Q`>caxyA_oj z3oHR2CHIS3^5bobjDG9A%2ynBly)hy*lQ?6!c})~kzTD}F92P+7~Z&QO84KIF7<=R zznZ^C;nN+CJd;$3&3Z(y!d*e?dOY?64D^6bn33{{PdB-+8bkl;TSd~ytj3l>^UY(r z&v1>_v1}uc>5YbO&P7Vg9xiz7|Ecr{(?6EUl5~r!SF9XN+{wk*>rxLEJ$F6|t+4k| zNRHMm%8i(eCKAtC0f0B7BYQ@~7+`nm`FbOCb=a0eWy(Ud2!J`l)qEx)7qxs#yfu$hzg$s416cKWr&cr`3La(Z* zmiA{h_GD&x0RxYzZF7@QfPKSXr;eka?h}BcEiFD9{H)d27@c1{t(aontppPXb=d=m z(n+wjj!`kaCzoCxNSoz-(U&>dLrD^EdX#bfLBJ{i2rH%u$s{aU}!{*;g{rWIHs zKW1n5HC}p2gt-grlyf~Cg7uSTKA8iUiz0e5%2pMo6e=jCzUhK}Y|a z+}7n!8q5C=xoz=K{megFfPWe8zYOhX%W(f?xc@TTe;Mw-4EJA#`!B=& z|1ZO(=80(^01cO9r(Xew8(&ZL9Q!m(!_|qzUw#(1sg}eYR~Rvo=OoJF#w+3yS8a)X ziWsH74w$+DpUqy%g1N9eU1=0!)0W)9*%noAFSSQyb{)3Z@UHT4 z(jW)fhQQ&+sV0_N?6h6;27j+AMBvH;EQ?#)B;<%+7l5l0isObqxUZq^uPNvM1a<5F zkD#vmJuUd6#?DaqbKxQT^w*a%I^f@|8gj3x6^G@yH1oX>p3H(o5x9wIoUNlm_i}6Z z0b9@)KoO=7t%fVwU(#^`0RJ|+;t#IAl?YbFrD|3hjL-U%J!O(#RXeN^e_i5n8hj)L z_S(?QPScvHxe6d-qweqfDhCQYRx{!Q<4j7}hu94Z{ngl7>u`-UYHIdL|AVqjHL0k0 z(HdWZkF|U3dkxnm{<;l*vTSK60}Fc`^F%Ea0chbyiyPmoB%BqhcyVMn0m{&k-JkaO z_`1>GK~hEcA@vs8@I^7;&(>9=6h02=)yR9%X6c7&vIkrj_{~kP%NtxIrrAZvKa-q# z`aoizO=Gru<1Xp!kywlht2Te%#zWVI3LPm_C261;u?N6V&RgwX0gsny$n-P+rEFG( z{1JDE#~;~N)8^0^8@R_YYn2UKF3apqA*YjZ<>X{_Pkb*?l+ku=uIs#_eCuxQ8=ol6 z_f7gf=u65~FPh8Wxk3H1Tb{Uzlv@Omop1c72MypO0M*rK1)}fTnB@Wx>_{gFB=lG#csR+vsqg-FuF8=jdhk^nwo;;5B(BR1v} zikH&Ices<$VEy+LWOTUr+ zmsk4pT+%FZm5FZTS52@ldb0eXADA`Fa#?kSn<&_0^-C{IOi}NbAzDNOQRQZ-lLA{9 z^+!9O*9co1S!x^pnSjiLftRq}ENA-?M+K@`@mzkmO#o@ri>m^`K%O)E)(M5+42i4> z1os5aCPCcXD`ap?i|`|P)!0uTLWfXoKa5kyUYYV_wP_{u>L%#mQlCUU7v{8*Rg0lj zw3Gc!Vj7qDFn=>(L8RpSknfcXC-x3ITW_b1mYmA?AJ}LM@LD~5etOAH&U`?SIXim$ zVIn$I)$aQ%cgM0M;@LB`vwJX=jrAI?-ttRDrw(H;^m!=g?&*}$w=1KPeI)Xg(@8GJ zfM(P(`MI#FHmjya71+k_U2hhnw!C^3S7r$08a5sQo-XU0NAVbs!s>PFCvS}5!%lwN zRyRmZ^QjYKNjW@I$G_W@cMOGgbDlD_8+UN&)UY0np}5$UqPVQ26ktWb2w|(}oC@w& z)o?3ENn-uMjBbEv5^tGH+AJ|C;mAZn8@Jaa7ociy*kHGc%3En~vdCd0j4ch=7!TE3 zvNe(&r*H%;%S}vzMbPu~GI5hQ5=Qi1vN6`O_vF<-yTqBr^v1p(%q=>kXyhM$$Rybo zs(~a{aB;jw_Rf@mB!|aKPGbGmiVaM9H5vywT<8oqW3n%Wnt^=()0fos9G_E%m+PGD zLj7}-N7YwApFDMvlA~ly(Eubn3@-lp82P5`#1!zH1nY<9#8(I+rL!djb^2QzlQJL1 zXO9_`$ZCc&v1)M238wmt>Hlf!5irc`hHGN&>=G-Nd>{ackA96`wp|qxs6<1n8fzqT zbg240{!IR<9?gPD1bC2+)bmk)8o?klcKK5>79-C8_uhHai2j`9C zSk-01$0|Jx#%%SOJl_8ykh*}jG{B0f&*U!{9Jyi}IQy$3kig6GO9rEyDppKh(j<Ja&TmZX6DQ*UC#)_0Uo}7=@N1^cn#Og-D`jcB>bn+ zr7P&jS&c@5?W=Iyl1!gyCj=W)#G>H(2~c0SSDSXNNRDD>(b#Z1pqzf9wr>%RLsUmP zD7~I-UZS6ZYG*5ocaqAQkYvRM=17vEFDSdi>3zCU2N9DTc70&hw%|XoGvJcg4jT+u z;%7KP6FgUUDAlEtNC@<)P5Q>LlYH#t?{Wb0U#5xWK?9V^kT5Xth!zeHu~SJ8#fqlC zEE8PX)haG=cBARy0!xS8b8Q9@2AI6FH7#IbslWj9HG`LcRkCO@ z7mzx=;$rF_|F1={{~PgabI2^WsOW`b_?_CPSB|?IH}>s=3kqf^i6l=4{$y|r{|)%@ z^gvfic&(c2oDw$-?aS6lw23}j4FkTvD>bma;-Ihe-5Yuy`g#4WqGPpV?rpl)&Onl@ z+w_=?{<-n!zp8JqSEc{k-@PQAsk#3ZQK(*gc)tl&wKht9y@8wI_-D!ZuP(&vqAq{e zR0ya&+x9oRx)Ovhy217azatM%oh#2jl;foE=Gc|M>^9K9n`ywPKJ~G*B=l*GYaC78 zhlQ(WzRx$395fP7_8=Mh0j`MyV6n^I&$N7wgR;;8RqYZl>T= zZu#K|pf|NthBlUqU+t{+`2d%ePne?+Z2n}bO&p|3^Lz8`MA~tEW<{gI8}(HXf;beZ zvxx`{rJTNq8Ik;c)2C|0wEz7%Udq{VF_S2ie?_UEtG&@jg8fp-${e0b6jg8Pud6w| z@yJ<-*A$Q?`!PWz<}p!@vqdgBrTc(X!vHIhjl-@JH>8j-YLwt2ie_YM2A<-kCi0=K$H|;lnGJ)Ct;d9lp?g<$wBygL3+Qgaq_l zWo3sS;|f|-SU`ZP8E+@q6@%Ec^HbT$r8^3HfDPzRA0?G8e4ZIau|KB?H&__YE#CKT z`_=|;Na|S#!p8_J={yD@8Uu&C_oxUqM;eWvgWEdc{)s?CtK zm@ujri-BeL#qR;-!!*X-b>w>QZ9KYAZ~76x5AiQryTxhbkDr$-#>GuBxqdz<`-Cp) zICYO5K`F%*;NOL1{k`09W;X~A(g1;y&E!2~28~Xf-mB+VfjkJM(80}v<@T|Ji=-b5cbtOwZ zD9}A^3k3=)VxHxmA549Naog6`n0h9a%ru5-n|W@Q5!j%C(HrSe1jPU{$ExNNymLM| z3D;C~s_&H9%`RNgrNt!-{K`-WlK_ITS*vba0bX-xb(SsUBve*BJjk-72d%QvoJ+OB9jYFG9NgJM)o8LzW7<1~ za>jg{`$EbgX8Z8sXkK^M_jC#~oy2zg^phFbvoQf`Wwo>rFzQlF%d0^1Y;*l{ge~Pk zVYRIaP91g3k((TR%wtQPiTugAmDgscu63-U*N?^ZS9N>Ov0XaTo=uW7-By-O60wHN zs?>|<>COJ-ZZ+XFE0OXW$0^0>Q&30xUy15O`$nU}pYvC-oVlGMFuAn?%<46n&)mIZ z*IxztZARVX%vTkm8Wd%-)SJVsQ-vq)o#C9eWAuMe!IQ*ADXJt$(NHf@L6;iXgwN$8 z92z*z99_;jn#!P4rQ6H|PrwX?p|z7LzfrllA89-einZtBiLENEQb7JTkMN>B zlh3#fs5wvAeg1Y;)M_qa(CqxUEtjo#R4J2rQCA|>Ibn(I5)|0u+#wi#oL+9OH&dqk zR59!KJ=upMQzb9Qhu-ALOR3)t?1)@z8WlG-c>Nt34h|mlfqTjPc7*sY{mnmEZ#Og; zuvr{vR#0sd2ho&Ys(+~VIpviSF5gl0Suc3kE%EnP*3+tezy31Qx=g)wo>Jz;lY)_j z@5?mFCdEmf-pct2r<`mnTR@I-7vK8*n@4HFrx-~e<*OCR8v@9mFKu9fVjrh(?b{#j z0mnFf-|EzNpa+foPMDrBuOpaAJ4j&dsm$8!j`A!8i=k%Q+0+iA-qaJi&KGE<)8CJGrz<)e8vYrz$@jFia;kNsyC{>p!?hX$}>ym-B$wy`md9{6?a9x>z zXa$)y*vD+sF~2snPnBUG9zPo>qa-$2dJ`(JoUfmO&=Ghxrcyk*M-X*ntXK%s6NyyA zlyhrlnZ8Yy+q-J89&Mg@M4AaO-INdgDxL|wvAzi6l^Sn4o=Y&JXeN##btR(a^L3m& zhymxsco0fozS(}C*>am+lq}7uVbRUb_Qb?!rEPo$-8zM*)brSR`Qse_65Z#yj})`Q zm={54J?Zm1JRLUm#$9h~@3#$)tnLAP;C3_`#~7 zALeJLY>U{I&jD@b+(4E#Tk4&=``XV;Dyz?%O;79^{AR?rZDuv1+>VMx`yW65emJ1~ z@fP|^!kImW0uh5a4D6Wxja`ipIbPe3_k+%Q7Y^=xqog}(O|=lM{&tUJlL)^vRcE#N zH4>#$w`34K@Q)Tixa4czo8LJV6^5#qA-R`%W)f(mP$m5c7_n=V-L45CYn0*nkZ z*x~3hA~(lTH<_k`l}%b_&Gs)9VT~r8gS!!}W#%3I(op31`hrEXMTegRiaP#v>f=;8 z;>@LpDV5|s1D#)fo>qlDxV?`GhJwdJ0;lz|;@07%T~lgP-He29ok`0CuSN|LP8{ze^=DrmTONeRkEbSQ_U`x#f!K=bwKHxLG%>*q=JuJVBet}ES4!rag@-mL4Nmu&9s_ng9qGnb3=6Bj!H$f{Dp+EXC2>XIZ5+j3>8rQ*-sq-Gc6{B8ghEB%wuQ0?^8C6r9kFz@ zeWLd#sIT!N}-y+eILfiP$hz5yKVNq1bXK5|2^LB6l<@~m&f*kPa7TOBx;6a)v3q1y6E zZA&u4xfnvM#e6*2)qFarpuLWq{_QWcsR^a)n~iGkFPSBC%y&4qY9y{2=i%p)Gp{>7ca`!t>o3j@2ulfi92!nf6wfH3o z%NmGR*DBEeX=E;v&nBxv6vNiO$d4Owvy#GZxDP<$nn&M(&}9sNzRTD`nOSbg3t?M- zGd!xtGrnX+c8;*y2%aj@xApHm4C@OHRyl-pRl7-vfS}q$?K{_D#$R>y0I5vYHgaDo$a$q*QlsnSf#nb^&>7!9Oq#QaL8aDZ@wj4qt$hn#5x12J2 zCpDCt`EQCyWpr>us!XM&VlVY>*of0YK$WJGl-|!(xhS{AwW(Y?gCsyclzoz~YK)=p9(FD;r*vdPh!!h*en zX;u&_@@RsbR=>HqVX~H%~ zj6hBV^Xy6X@KMH$@#xqg+{QrG^NS6nm$&*-wl-1uwRZ-VecsJGKz2u&7nFr^efhrRvX{CUD&|4Eh=I>_CyWLSCe< z4~*>;LF1he^bxWu=USBb0he2ORySYVTlNWQv~tlUN`^>S4P~^C2yvq;EaZGQ zmOXIP2jh$HvyT=Ojltu4A82UDf=U9bRS5B8lGq9Cr&KqppT}|gL&KG=kk_!84xp)EH?Q?nOYDmd9f+H9{{wbDqa(p+`AP_lt{ekD%)>#EV=EMj z#438v`Ky3HMn#X{j*_rvxr}baZctJ(_zl%7jUlEez60=*+~;r{vab} zum)XeB@c!wp$vj0F;qifcx-bU8@4H?^Y+J~##KGv5%QG!g!reu&R%0vW!>>F(?P}y zxiQxD#Lq@8Z1jsU!!jirBBtW+g+9xcPgC7~29Y?$sgr+;Q#=2IwVBrT4J5D22o@z{ z8E^dBKjQ(FYYEbj1==*s+q=%c6|U z*MmBRrC#_}cLX~Vx3YH|xOIcmFqpP z|G^Kh3q=z0Hyp|&<=wd9ALeYLHT#1n9GoPZN=}j9V<(5^Vk3T<%BlL6p}L8@VCok> z#bOZ#W)X2K!6H52T>ki0OZTO5|7DY+!^sxOdLpM7*b!O}KW7*9dZR@Z7@BUZZ55{^ zcDTHx9;02ar)}k6(s=NnJJ%=n#!$%ygxY9ldcOJ1fjnC87LV)o40w= zU#f)Cgc4FvP~<2kyIQup2A@y`E3TpS#~v{B7#2+Y%!NSRUskM)@3J2I0x;?q>AD#*OpQ!NI{<`Frp*mM|@07uN^bP=O*_v#>Jg_02c0|H2hU-sX!T^7N()W-Ix7 zqPa#q;{tfjk8{=Ug`J1~sfKi4+&7)x=y^3zeW5nHAoAn&?=Ad&LS8g~n)V2e-le;) z@~=wJve*=0kBD05Z52hllRg$`)=0{NZ<7|3Gh)MW>u2z-LMgrH{X3Cp`Gu)9HN5tf z^kmIu@l}-es36?$^Ak4%$ACuVYkB@n+T~kHcNjQ-w z&dwVgC9nt`i?DJ*Fz@IA@O}cY4MT zNFbtSS0wq{FThWA7H(UOY2B<|x1deWW+w9UT@!xiPc00Nk$YmOcoMIC!C4YptJJlY z>lskgwxwJ4w}x(qa6eO=2*me?ike5o%qBvnh+02_-ipcj`OB;7-^1Z2?Q;aCRXhIV z%yQSk6v!l3OoPP98uC?H^C#Wwo4Fo|wB@?5Djy)e6)5^wwrwSyrBSHtp{rjMXjl<- zLZd;7y9rYbbznme@0eMYMGY3x?9dr84IZ;^Tg)_tuL}aOuK?#W^Nza687?y=qnrDS zYbrVAIV+qjYLiCwcjCvYgJtrnbz-J(aZjmJL+?-ejLsPrMbwXU*uK21^&@Z`%pBo%RUjgaV{B+cnVTE)a+YXs!$4c;H&YUK%kn#kBu zXCEIzyj&inTv8!TSvdL?#r*`q^f!wZ}f+3YKH5%__vC)zB2N!lZq+6 z^z`&MQn`fXfN#3KUa`OKKkb_@&B_|pAXMR zK7alk!%y(~#g)wloM7>4mzDa;*oKEpy_(u9kAS1!w;L|b&ih9Mhu0CVH~yyDcbNqx z|FAbr;<2Hay##M5DxrRvw{9pk`i?Bmi;nRP|7_Rw76oRGJ^inX4|m@U2m1Vpw2;C2 zCqvHv?$x>bEa=@!r)EdEw0%a}u=3HhJ4`0*;Ez`0|ET~OGc19KnO7RQ(-+=n7nYRb zjRr#pDO=%31=SqR;u^^JeVOMp7>KxGTF>EOf3C>R6uMejd9L=V#b#7%1GMLC7vHDn zy<>KqY~HSrs=>_~-?X&vfdJh0^|U)|2XW7KrWn#@E1UZd!!bcJJT|2Fz=qR^eul zppNNT{_T^gn*nu}ivu{SkIFT74Pz_}v_YVdpXe{sV9;{+oM`v(^K3LrFR?~GCRIZoC7B5vl%>rt}ma^-0jDo}$CUn+xwVWW zmR2aSwim8)&HNqe6T+w4Ljl=+?b?{XmzXZdY*+98{j<--`GjFStB2QKd$aROKhkYG zg=rj8ys>ij<6>ZZ*;v_oXNwXCOi9z|>fBa(yx=7&>gco7W!MWX5_L0dFWH`{-u?x; zXagQe^ZAeDqrOA}zf!*0$}=n{;KPN?Y21!KOJi^AKGl>=3;C>972Pa>@@BnIOE~po zU`H|?*(4~`PuDB9xpqXj)cMs3otF3H#d$C6LX6vByA9x@3q4Itea|d7aW?w1+s_7l zAfd)PNl_odSsTpHifrP^*8f|#BrBQc=v7>hUGJu*cm-H-G8*zs`N0&?E0Gu8bDlLETN z#erm4&BEL70$DHIgF$$qiN9;YPH&6%lkav_2LyxB9%F$lp?A8N@fz7CMHAxS({|HF zVIE(2tyUV>XPUI8Ac}FRF%;d|WtiGC=(lJVx8OilD4k8>dyie3uyQp!Qf&rJZ0qFF z>h)S&nmx_$1HVFcTSMd72x618Tbv}o`n(R!DT4B1y=sVrv{U;Xfk{qT&1F|5%H1Jb z^7EmcO!D_1%he>FVqAH#j8T2n2QkzJZ>e`uA1<*;gSj<>>4Yb?`&B_^S+Cm@UD+pQ^lVLi29(1pNQM_k#tcQKQg1^9J^2m49coV&yz^%2)4Q4=`-Nl?G%UPS$4Ljl_}a? zZ#SCnD^6fL&!ePm1MW99XGfhUkyjfgAiufxTjWfViQAa}>wo(xA2MZDJhEfw`ISk{+bl@KK<)89YX1RmMLot2n zA6dM7^(@Gqj`_%0iTQwYF<9*vYP|OLv%dS+ zy_ISoEH+YoPNNR8C?8=r7ht?viD4Z*o+&$;h&R*0$!ve#NA9!5pUA7XA2!E3J}q!Q z8b-5L1YL3-?=)XM8xAZOH|r9uUcPvC98&xG*LnQ%0*}lL2GX57BBbS)w>Zk(+H$%- z`~FUUOyegbA%O(*8lKIKOh%ND4zIJlHM@rh^)vwOnt6DdN+&lkK_eo^&4M?4xbugE zu2Imq8+p@wk$X#+WQ?YR7b>rB z;S|rnYwL^g?p^lt`4xUnKV<}hpuy*?S%0?`^~BC_Z(Ewem(@umii3Xgxp=h! zsF@4MTe3BYkb3OtlcUgIK-D$grL_`lK*Acw!q;a#3zlwYey;IyUyr>!1g#u+Ak)**_&Vz-8__Pq8UF+qY+kKP7 z5&fOsKBuUx84?{F>be8Rh2x%1Ldy}3vAE;nS7w`Vq@c=$sw#X0 ztZ6e4gr?7N41E-K=2#E$$yi`ji6QN#_>y$FC%n)A3<5pRwt<~(vw`XXo~K0-B1n-y z6FYFHQ|Re36@Cfpnr(QR3+1mAviEqz1$ZG5tM2WKp ziu$%3pF;f5$!u5{W>8`anA0Ga?`?|k>eoO$5yvU7Q^S%;&)Hr=U*l=s?A4cv)VLR= zcCiftf}B$%iEs_hrpVE{@+BVps1H2YN|8m{b9?npC$^JuOoWF46$Ps=CzFV`c=jTR zDm%RrIu9MN+rtp#uo`sjXBZ4AEmDZsnc!abi}4A+918E$qy}AtT|Q=ziIOpJad9am z^K6cUKU|UAw>lX;^_?k6*}_lBTUNc!Tl0BER59ie_`Rm4-);-c9tCsfRbV1v7b;5zC6dP3HorBfjpQQj}OkiG-8LoG5bP zy1^DkFZdHKuyfz z8`K^H!S*k(R&qEYSw7-QMEm!>LlURTH_~#x24GnaaZ=zoNnQSBy91hM@I^ywZ$1qb z^>&0IqJKXY+iK|8&JNO6o=z0Dy%pv~v?J{7=m)?JJo~-_p@YppMS8co%U&xjQPL=J`FA(JUWJ9e@6zwTckl1_VdF z`^#eU(W)}C>?&7_7aMy;pesDJ+8?(bW*dpCp$$yICi@s=&8LeZ)em}`Y7^*8F(w8~ z4p}-qCI>5?rK-e04nF;eQKO?NYPS1Q5hH@u1a*F?`mkpVB+%U{6nQVeW!yuEBsuK# z3fJMqHMJuYx~!03aMW`pl3ae5ktH|A>b9;9+rbl^#qVgUy^K1O03bi#-#26>UaBwr zp1iH(Bo;_Q^_jX*o$#La_A8^KQ6HoA^4?)9H4t8NYc~DS!2cgP1xSsXU)OiHTL%31*L zROdsg@3Ls%kB&y4Ris67&=pijE8zfM4#x${PuUF?8)wBIil;j)%KF|`$WweQk$`VA zbEb7{L@O6p$p4sLz?wAyA;b6`+>zn5wiEho8x`%J2M=!E)2|ykufo19k8arSScXXr z!|j)`Bj~1Le@~n;p{o>j&MzI#N&&!B^Eyw)xiL_2e$LCct-GNQLu5=efOKL=gmX}> z4@?tte)13}q1awsQBHMOwa&T@4~x2qN^k>cN=i{e!LkYP;jfn?`V1}i4y!9vC4h99 zH#?z2B?U$&mabh3z5zzA_arE)UUkKc-qHwNvbY!X-*hO|A!m7g)tQzlDYdQu;@#Gr zqPC2N-)1(A6w*dOQX-j5 zI|qRwv}uPBx45qD&wH{CPw*9xO~I+pr=^~nCYv!dGascmopGxb^T?|f&=C{K;s$(~ zXdD}*L1>i@o@N2TL|)Kn3=wIooSaKo#>j_hLTt|;m0>zRJQ;1?{`!RO1RF%M%$S^a zegMp!3sg8o)q?Uiwmb|Cr+cQ`t1L3PEn6&3(|n;K1~l2ojVL$}fP!(~hNh0)^x6!l z{*s-Q^Pa1D_;jQd&ms&P0l7M!+)$eMcF0EJ`5~^LMyBj1X`7|X|Df)@!k?>6Bpeg_01&_?3$f=PrDfd-GW$q**qma!o@$}qc&EI60QA{! z%o4-9nNx3=e>1t*n3K;kFCf%$cySVzA9}rSYiC=tT3gAjBQ)$2unYvB(GrWRUR=$O zwzdvE7XJ80@_{~5rMM5GQc^edw(;*q?LA_GYj*gncyQDWEs-nu@n;p+*gTgd^snyq+Ih%2g#9HC1z60^ zaeYbn)Hx}r>*#%0pm2$Gujki7_;m5tiD(Sxq+C&l`t9RSBToUkt2@5D>QI&1$H5?<(k98J5*6@+3G?4z1L z&DAv%&VH3fmuJ~vRvBeOw(L%GZ&$7h0s=|q10KcdMV|1a72{ zV$w4q0EcHnbOvC2W}p?>(+y&f0aNf^^5y+!2?$7LT9K_9+-9#BMrDS-j?a0pOUWiP zob}nLynj8=Pu#i=^lvpKr^lkX>I3O5Cdcsie-ZC>z^+&&;N}#9i%K~e?TRVCJDB|- zuHoYFnc0{#E=M1Iu`{0uUOam`|Eolyz5eC=qH6xyOtsz`tZ864yh1a8BxHZcST_AC0}R{H%1R3LcV{ zT{CFJGpdeHGmm#5RdzT$`}F?OukHsnV6zp6XSWM_rvGV#cqUMDti^~&&q|-iqgq>` z>{8W)5P;Fw(Q%c2be-5$jJGWcOM{K;7Z$O{E@*#_Pe^htb`Y z(kP5L>XR?#n<4LJ73!$jF_RcwXCZ&4G}J=X=!Bjs-R_n|;0gDJrsf1$TRaYXnCW0z zTz<0cLxDwSl-szY4G@>W8%PL00qYVH1R!7d=iApRm_H4SC)zAX2Ib{9${z_$b(DBp zc@VX%Lzn1Qr!63nX5ZV=3I=S*77t+!v(3@vVAB_8bBcf1*JCRer<~Lm@9F$i2wm@H z&=$}~;|!cUXRd0~>#Nxq&c*@K=SZb#a(Z+5LISl?zHF|LiNSfU5*B9=$|8M+vqjWh_;?}L?@6ikg zzwTo>!;2Cy#0_QF^EqWInn569zd{TQ7Gpg7#W8d%K?dB4t{u1Kx8h^}B`Hb&aAIJ{ z)Kr{zTjh30wwss~{-unutEh-x zeSa+gpBn!<$nd}WflnoX!~o68(I>(csPMAzG;`3LkG5Bnufg!Ss6il81l^14{Y#4pjJ&KxhhYH%gJQFr5E48;;yrYuQ3`6QVLpb6$r6L zt6IYDJF`cxPp=@S=MuX4c|6f%>x9S2eux^Na}d5w&EtwKeWufYuo{ct&T6Kc5znwr z9!jsUK{pF(_P0%$PLJ=oI_u%gpcUr)wEM>((d=rPwk$0D&wbpA14VYcP~ah|C6oSnbsj3kYbQ?*8NO*#)2=EWrC8MubP2%gR_i+FivU zxzSkH>4F(tKeD=Da=;5Z?DZ@fJ_&TmnE!aYFX4WO;-h4!2{ix>+-!ITcR||nQR_?L zQ@K1iRb`Y(3xvl_A)c1qwpSa2Aja;LYkoE(;`yy)r<$rpYQd>6W1C(LtP4d@bke}v z9MGLa1Zie7P{eoWy>GIXqar{)$8FKksN7n<6MzaJ>wOQg1KjFejJZF<9TgT^k#x;T zF>YIPI{Uu259U6R7;P@&*$aqeHEVmOZ&(z6xQH&oaE#-c0?YI{{-Tep-rs`O<#L23v#N*zTfBzy! ziBucRt^l&`au1ca+Yfty-$Z)nT0C7*rC6%9ojt12o;NPdgFq!!LON3T(q^)kG;y%X z=P8Z}S90BCGf#NiRfPG^ZFPlxQ5w9)a|&LabWqgIc6j?9OTo>^t&TTq@w|u&f(`Gu z7QJjC*LVuboPE-fLd7 z(`Yp*!C^YzUjg%3=<$ayUIC4RAdUZ^;LlC+2yKYM-${V->S^bKTA8}Lq1SMzV*okAt=DYw^IDU}2-Hpk}v zk&Yasm<{*lIDN*rZ93YIrX*RL;BVQuIyXgpXI(<3f{dIHUi{%X-!V0F-xglg%}Ito zy&%3`dqwu?Q1v7dlnQMf+Q5_{;hE{uKGlFc2yCWLtC@YDybiX&F2S*Os z*tKXvIB|2@SI+E0Z2+F~$wKqDvF3AYYqNQ^q4$^371cIR#sJ}DayHy+5qBD1$wDD;E zlyaU&)StY9pPc?29bP-+=8K(6@oI`R?(8arB`+%4KA%hFw&Rpm97C^pct4JIgikj2 zO_Bw7aEhCZ6dkRp+NrmU(?sspEJa47`AJ8yDo(W6dUnd0oyLpsCvSWSy)X_FJvoGf z8l2Es7bmYMB0lL0@mobGz_j-pE%~ae$UacsJZn2htJ;3sqIBK_UKdDvI;^NBO1k+? zM6T1@eHa@MA1ZSG=992yY-%+<+Ce-mz?XUXhp%IsSbkvFBp|9Pkdwc2h-^2mBsn;z zQ0E(2Nc}k1s)Z+|?o>OKz6G&q?%{R#x!o4CH6qwpR80mH2OA1z65$lF;+5SEyI|Ut z5>TKeUtys~Vk~yEB=eRwcPMjC-eClByesoHywRJ?#~CCBntdQM)s&v$Mm{$vYt>_| zthn_cB2w`R&qrrO5{UY2ez9pFbdD5XBo^SLCJ$nzl*q}Kq-%}F;?$cL#8fx2i4X1e zx2S$0cF1Ga#nX6fb8bvw#NfS|`(TzJwAleZQ$UmQ+t6gCkmf%-?J$qR@CLBCsn3F- zAt08Z(aD$J=032d_>aW{8O9Sk4aNo7t)U8}uNw^r+faCKHdfvs;WE-CxhY?$3NNnq zSL2F?q7bv|MWPuv4nN$&DuOT$pZ7ih7H0-CC*oSd|%0^XolJ#X*0wH z1)ub-w<*eZL=_-s%ehs_sF+A zV6nu?d)*hMyh8Z9Y+OvJ&0KOiI;ub&6QNkHM^zM1$h;>M>6TUS^Df{%701h*7)K^s^77En*ku@jwhvI70UJAS0FtBT9D#@v@o7~g z_s$||DQPma6)L^bj|C}o$kI66pw%vY0>a$wPp?)zHS7-t;sw0R*S8K37T-1zo?x*s zH$5m*{^7_GAGC|#%+yi%77;Y>DOdiCxQb>!8`2DfZXmClmdj0pNg)n*8spqRH99Kg zL~pNdZ-ltw_R1Sff&a6g?ObnU$gqSRtmBQgHRH9ds@g{tZGhTyVco<9T@Wgu)v*!`oOip1yj* z^=>^P*eKrdq&Kwkboiqf4;7R|ftlnzQRbF)z4c)9jC{;#3_a$+I{6|OKVmsvIObEA z5FbrPjcac1G9+2L*r^Ccj%Hc#toPTFu?3#b6j@4d9U^{@cKQIl31@-LM3RL+dd!|E zX^aC)Z>zB;_&y#49=pKV_s7*j1NSami5mDa51S|oTv1`Okmj{q`RTe(UvnCJJ$LQn z-Mw7Jz4rKn@H5fhAG4na&Ox}@k?Q_HMTA>=3A0x);D}kCIjSg1OzPhFaG&K3{D-85 zc?#!wr_lTO>*pcO^WZ_(q~N*uWeD-S5&@SOP{Sut@_`BpO0+tY?tlM!xWc| zw8?*J_qt{ON|jRHKz_bQPnFuvO;1-=0o<=%L`(r@)8wz5sY_aaZMAcW^Y8zFoGA_x zb4Ig6L63ak_`$U6q3Ano(OUsuj(%+YwL5!&)3bgzie}tJJbrTaO}1m8X1+_6sSf$}ubVpV9&APL>PVG=5d}eK^g>K8aFU|a z>B82doI5W0%y3J6FgGB{e0+@%rEqE>G{a(YKFXdJ4te|ln}`o;=>@qTSwzi(=Q*Pf z>~OxdM0Kjvls9YbWxV|;wM&ZFdR%|v(&OFnm`TqEGV{DKqF3^}-;Oz)uN4)cD?jD# z4GF~$e=&JK!$hN!+m^Fg%StPQVgX43V9}uGjvMBTetdmMBlm{73Cwf#jhCzqJE-|g zewD;o0zD-p7=|^tGS#sz#j^*HPhBV8(R+nwjNN&y>7@xUNMGQ%vER#1m8OD|E_2Y^wO{UuLaYUd`W6OHj%m+cE8r8QS-%E=0dzb+P zntix%e5fj-`Mf}A&&ANH`wbcPUt@mvUOhnS8v>~pa1EVMdNx7VDWlJ>2(wcN-ncEE z{C?HA9D2m_o1Wxm91l<08O^e1PD1*|`nPOEfgo2v*y%HLcxU=SEva?#pr93}Ax?Ex z*(5#7+g>vNS~lv8%di-ed{HYTFcgfQFq_fwD9&~)l7CD*iZ*YS2lH5%ovkP~@Jeg;+#--KZPQ6#Ve$f$~4Y%D;jqUPFA4B8D0J#NkyPQ#S_k)#? zi|DDM{-KNm9(8iOl#pLx)1f5W|B}IDShVt_rsM`n3el9tXoeOTHF$pZ4G_^kth{f+ zGkp2-OGW{7K5@%}9-xPI$Vb%ZQbzCd-Nw%iBZnIXd3fk*3iyg9R9nO!dflPh!;Bmk z-23BHYemx>p`%`bo&|7A9Q?3N?2Dwt8|0&8k(giAzg_$?k06?(F3sMb>CEipd>q;> zR%#E+KMLXrWUhWLPf8oIZ^!;!^~>bBp)Dc@3Q7TxatxL*+sRe*eekk z;f){N{TV7xr8n>8sH!;k)nT1JKKbpOQu2_hv+1+C5&uX!H4725Gk1k zXvrP@+xYpbtjp=;83)q;fFZUwNX%}krM3G()0z%%`#(wA>C}&|oZIKD%n`1bxO?r( zmk%#!0V-pc-*r0UrBldjb=h=cfqk<7bD)G|qX6tzvB4Lf!bAWP8MU)Esj1P zjSUC0a0ato3yVdk%({ZEMZeo!HJJZ3L{Fyu3#|T~s8V&}t9C8W9JX_>;%7uRh1Gz3 zw|}WJ{4*=Y_*mZPLXpq>;wVp3%X5y&4=ak}y&B-x`?L-N!?hFtC2uA57@%VqT9M}t z`XPS7=j|aLf`&!Df->T?X|4xm+nr^fzhL-z9B|V+a^A~uaUx|0S#5M`<&LGfujkEk z;uXI|$%4?|Mt=vGzle4_kQp|Xc2y%nf1&$>xZS&jWAnO4p?w>O>l(W0xqRK{^0|TV z1B0m@o*)>XxhdHH^uC;)MAyWw8oUPr2@KphwKuR5(1CsEzN&i7gr_BO@ciu9?@0gC zQ{XSxfUtN^GAFJ)ZzyVX2f;9_5>=e;tO}eVq=Z zL|}$1qD|zhxU~B9W^I1+;%5OXWg6&$NZw)$5E)RW+Nuq-{>%^5ZDd}s=9fRT*G1Kz zRD5`Pru?Nr(lNVmyf{T({NoJC>E*-R{;Tg4`BW39KxN);X4thY{@V2BTtg9!^B5p1 z0*Hk$PG!Q4EQdM%6$_x%Wo@{hh$ocqbS4@|yyHh7 zwlB?=Q(!IL$@x}m!tIqEjekXd0)n`fd{$A$BiXYNsQQ!vry|OqwY*K)A$Znm->W`x zVxaex%!2fJs_EB$Ehf(=2z>`EERRy)$otI?Kc}b9^gg0&{`i>RoB4(g)V|Uq9DYt5V#zd)js*6p%vvpC^h5Tt2#XcJPVnyyg01U;(#Wf17wtyP=8{ zBJ8i6Q3Mve(8nj*?@c-4k@*Dl`*9xtuDTGrV23pu639@Kc$6D}0(V{i4jgoyffxGt zwllE`=I~fCp*7LZvnyGro_G!^(*WXT()rN)JSZJMu%~%kYq}i^=&$q4q+)PxlZSZ# zZ^Pe1PAV73kTfsiP_3+bEjw;-m!2V+bSit;V=en|*BM(N1xK$Xzkb?^J{NiItqT!6 zWFGs}>o3C-Uynrku$8;bNQtvTqd#6fOI~M6dAW7s&D(snD?e|MFVD%={oPd0B$xob zIO(Kvl726+qa2W!#d}3Y+C(|zXkz(IL#6w|&2f$GE=&0?eE5a^pbQVKS-sB0FjuQp z(?5X)gme~hoxYS{(2EK>-TXR0strmoYr$t;E8-yX(*BI6dm6T4`YzcQuE{|iXG3j_ zFMHWJ9x%FcWnML_^%UetZb5NbU{Ql5U@En9bne-~l{Xrm0zWD;6oDEksIb(gn5Jst_n@Dz0E zZB{-y&6n&uUG+*!0Cc6;$MESgbLeg*F6^sA8CD>6vx~PD+(wf&_RKQR+ z4r|J5|IUv2NJreuYqn)Bca)XCmD=@aFa3By&n5nq`|&22+H-4;zNZ=-$RG)B266|t zUDwJ6%-jCK-5>qy#Nq#rdf#uSf5-6$q`?%+($dDCL>xMIa$h9?Qc|Y36Wz3c5U?we zhooHgD+K)3-&r(15M0L9)@$c~1#~bxn|Or#uhK{75?0l0KxgUhuWGztYx;Lm!GBcW z|5UN~|IhaV(lUJ+Aj09A%f2>Fi$?mZY>GwN$7#h2k+qL1c}_bdul{_uOhB%&GQaCE z3#XA&I+a?!myF8sO@6}jP0^M>Bem<85^tl-;NU0bdb{7N+m_gTF{k!h^O7-CdZ4Id zQ+_E0Hg}EJ&2r`*lS;>FS)qKzGrwoj%_{{al)ITSevTKP|?7b$l|XPaAqD6)n<~O>%t~92~o~Vei1* z@h!o5Y0^tYS%h_v^lEthwMX4gRMF5P)_W6lfw4?;zh2Mc(-n+NWcvrX9^toKXd**i zH|!3Kb!;k`TV)9ER>eg9+H3W=h%3t7{h86EC>bM}gyZxi{-^=;^RU=FvfTUgw4DvW zv<#4`Igy&-v|4LB1i^bh8UWyfC68+=&}zS+pLt50+qb6R7Vq+H7zS_@T<3*8%9a@R zY|(c}=@XYCyOWFp#knp^sI4(3q_GU#vXVNG6_S7l|2CdWs53ww9Wm{g(NJ6R`pFeP2yDudMpX zZQw|4)53t~(#W+Kerv+;5|eYP==<~Pw$+>3n6X+l2gJ9ueoy_)E5IRK;HSb^rS`kh zT^*iI`D2h;lhA%+Zu;f24nr{=o6YV)6lT4+Y53eAM)GEDZVh0tF z!qYvP;NFKai#7!gZ(D@frz}-ZRG&+fcJWj53h!c;mE1vkV){eX1{a@{utJ>v($=n1Cz^3d5|K&Dp1CSKBcw7Z;U?$vdeSTEd zM#|oc4=J;{fHHv&E*=VkR!+syG zgp`Ej2p|o*9Tz-8)gWZ zsZ-Hr{shOEbcF`t9r-%_x%V@vNj&tcZ5IdRM{!>Ajk0EcRlr{6u(VOLN2J?Q5pmcQ z->*K9`fPcL#N3xEs=Pq_qt#=WpoERZMeTPCbUN2tYs=H^4ApgvnELr)?`FdZe=gf@^G)KFrP{= zW-9j^;;=I`-00qGup6H76_&j;>heKR_kiOaceF0-CLH1sJ0Z*lGP%rgm{Djl(7NjK zH~++ z=uMT-H?pB?Mmgl&Tzxpy08bd7oWzn+Wjs2v^*xsNFoa~E^>)dzU1|k&wugnNbIW%} zQJ$8;9d@0{g56z(_+0z*jocOjgxxh7gO^D68$tYt2g%H&?%M4Jiy%fM5ekBnrV+K z3+V0q*wm^&pX#?tg38lwTwLD*(Z zM$$SQkb84p>;mvzHXM8!_)8OB_k!$>3=rdX&@@7Lf#1gCr!%XzNZNb}Zg(_DVQYC* zcxa)P6letB3)Rs9ADCx^P~H0v*ajZF0= z3LG(7>0*)FTV&ME?3wE-NWrckmWk{2>Z!1DFD=w6P;prn9pWU;kGfEhN}UVx-&r2r zBjt|mZqCK%qyRVVApJJkbW*i5C82Xo)YW`9%r?Y&2>c z4*rw+nMIB^QHv&L)fm;T=8vC;ug583*&)6&8AjDNKlD#7(_9WM4TE5m(L!XT|C}cG zi2)dVWdTIhkc{-g?rPYtW-Eua4qg5fQgsv)vxzHZe+>k*tbT z^4s0;DyUhrCDZos*&NwE>E~ZaRK7A=Sp>;(I(knWWFx4VFWjQL+dC5O9|!bta8e*k zQxdoD3U*Os83w&BwLYtJpLuY1iCoo{-lMPMUzjODTiJv!Q@6HaXt!=k%)86TQ>FrX zkk}+L2b|VFx1l0xogz6_!~W8HAp^3rr8&(xN)76Hf6V;bu4>h<8aok^skpi* z#uR7$kz5P?IfZd&5ZUaAJc6q+t^aw9>)WU{9TcDO8F5_N=!hgLY8S{pAqXI;8@8h{ zgUi{AUy24G@X3wuQLA#$npL1&{SZhEiA-*U$Uk4X6#ev-IyZc`$nu-wDqD7bfZ+4v zMzZ@oj?Fts*dAvY({_X{age#MY>BaqhX34M%%rWbDBzK+zGFMHa~s4z4B>l2lJE^b znL8U+%f4f5nLS>^++*H*qzY|C_Q+_T1>Z4D#r6){GES#8Z!NWn>OyW}MDBzx!!{36 zrt<5~$h~n$q4NM1V}_4{sQCzUif84LI)vuBa;5I6^t!*|&iIblRS0Dl?jxVHI2}bmBw0{4@ZD9W)o^_F-ow!}Ckl@S2)^Ikj2z9r zTgLf&C}Z@y2J28-5DS(d0H^BLk}`~_iy5HZMv(t3obr|W6I-QINwMG->%2_4~X-v}^*Z12(krkEoY))@;hTPZub@3?EW zyJ@TQn%TWNRAQR}lO4%-w}&Am|rIY}E`c%zk%%ME;G`g}U{?B8f=(ow()QaWS@jLjao!V9PA2=Wkdq zMKj`PhyjHioNtdjbx{-QzaUBQeLcpQ3SW{1DTvFVr1p!-R3tY*Mkytnk? z%Wx7UvnR-ZqXkZB7@+PXf#5(0C6a4zjsV%AVQFgxihIxbhe$tY+asY6nqSQ&+RtOD zT(B7yb2vpTWESV!&+$caFm4|Q3iSzX)1qFfP``0oY75ht6WniQV$6S;f|NSRML7i^-1Wv_RK3&b^(QZeSUUJF|o zRx}^pD`MoPbh1rz+6c~ajBPi5dqu5h(@~(*?@+s}A~%nuy)j%-ht^V!3b0f~`Z}}` z$tAak%0@-1v%*c);RHe z`yqH=Sc8GhxBzTBG_lV-UVJIV4!mVhzx4ZKx#HWYI&!p>wsoedeV0SJ@qfPI-~8VH zD<4Nbfx9UbnCue?&YjbuM%omqfxIC4gTCm@JDC67lpekG^Ur!T{aK~{a1o)uM%>;% z(D()K$^GW~|K!K-1v)$wkT}A+kTLyfzWfOc#dnl;O6-mSkCOs7{W0#gGJYTuiEnId zMtSJ(|Iw9yHN99pTIg5r_O+iRRDngf%IUjbeDO%wkJS7xL!!>nMMTqmf0U?3et#EA z*x#z-nc2***Z+Ow6edX-m2~WF8dW3BJJyv;;_1WY=g%4AAb;7RmCo3VRiOGFM*S5i zMS7_ZcFy7Y4yD?E)j_mb`$Ro;XC_V4d&k0jC)iE=arzQtq|vAC>R8d# z!!^8R^z4JDrWS+dzVB>d=Ns;pFU0&%{AR)PsQp22R5ain+QXO0!`xn%tU@m`yfS|k zjGqg~dxz>5U&kfxSB!Iq3m0c9q43BRE9;({;CN1`+~5bsyKAu>m4%Dap)bUfg z^tmb(Hf$0^4>oy`ev0tN3)NdX3P)2ntLx+*!%)l&7MCZ$myuBn&VyhwjaULBB=Xm) zq&~p))tPU}u{>+rtWp@Te zi(4r>31-Jz-eV`=nIwgD=4a!6U6pNUqBZU=)OD$6Jr9>w5mXO~Z|(`-Hu3aIPwnW_ zg_M6_Kt_jlvrSCb>Iop>k9fEdO zgB0##soCMm1Lj=vG-@(HMQp9hF-WQ=FQiJ%KP=H)6CRUY@N`@fn|QF@{aK2WQKAj; zk#&)m$<%HfD&*i<3qt(6{Q$&~2o55Q32ZEi$M7<(j9YP5d0mpSTF;D{vB^B@MJ|zvK65qHAz0KlgPc2zm4E#3b0?xXnW3xFtK2RNJ;-5BiHuvc|)6}aKZ@J)?wNQn8PU@=tu7)$s4HrcdCh7*$xks^Ly4v^9$xKHbUq0%nE?^<)Rub$|Pd7p#Y| zMC6RxBDT(6#ORZ^Tk4NB&G(P$^82nz^P!_E6^5lXB)dI0yd5&PJS%k}f&{+p-6J|p zD6|YJuEgsQgZ-l*|D3LX40X9b`Om#FZ+;vArL~0Ib(CGy!w5v5_1oN-!(n;-ICD!j-OaxF2A)id97qOe)f3v%=~-c zGC!7g!(5c%q8jzYq@M!iQH)9d<>%Zd&Z?Y~u@Xc$K|5MN-_U*XZq-Kd0tv-yxA7S~ z$Havt?X&`>G~Ns9pzf|VRz7!{Y)YS<=2(JU)zf0RhHP!E8W^~m zV2cKYFI`LSjoSE_U@BxqE`6?SdF+2su|#1_4)bgOjnrC1r|1Pru02#x+X)*G4GsJ53 zexKI#(FHdThA%gR-2(kC9fX|<6{mj6- zy9)Z~nV0<-CQWv(OPFY!Et+r-?E8~efu{~2# zioPJ+{7F{NBK|m3W!(L~UDSy2qmpRb<;#<6?&;=VQP5sCQ`dO5@%g6})iNkok1Ms7 z4236MP`(oDc*djC#L*P)GYRH2nwmf7Rc|`W!C-1JI&r10 zaAmV;YIEx1x2a$<-{_ydf1z8PfN{Drvx~KZiCychkBJA%>|EVWs39Xl1W5~9HlkWZB(ub(>|>J~`=Vb0T-| z@FnqzjkT0o@K)ma)izR;_qx!tbcNk;nSrMm+manCE!$?!tOr}8Jo!sU-7tw-Lm=DHfZI<}uies_bFT+4*px;Y{}8 zaTm=-hcgISl|H z=hZl~6qA&UjuRiQz65hlZwgHzg(7pU_Hqxtm=1OeNBAC0+S+rP=yJQ3sZwo8LQm^y z+hr*2^j}FGRauvST7XUYLT|0=4}5rIk~zK5H-N$R%#?5RKMjejEt&GhYgTtB;`ya! zUDXvwC3z(0FI4!YYrmO+KKU~&H@#69!pU&|N=KP+8>~D@l8~lbzO+EKbFL?H5zSbXe&R1)>))H7x8tl-mibf4Lo60s+d;`{DX;2qI^0|y>d!I{wGKQDIG0J1s z_fU_gp)X6)mO9!6I?l^=i0!x%XsWQTf;Oe{3B9(cC1L%%>qBF*!W~;_%+fQwpmTi} zi^a<6bhwCdWvtb%Z!=OA+om50rEhxP0GFeHQbC z;hX^6O982)pez?_Y9)&9zb$F~nB1C?;>*P5cs$-}wq3YG?q7kQ{(~$#^gV|QSB$=b zy<748SG{Yf57D4$87GvIYasW)nm7zwaaUaalizj01#?LHlT=_0Ma4Ya#JviK3@L|K zTC^Fhb{@HQh0CY6J3}Z>Q!fC;FlV-+vJPl6~$)RdqE- za)K257qzYb9`t^il{BLBaEA+z{>Pvf2-wq(UxneLTKyQT50DPWy|v=Nhxohlt+Zbm!z#P=(fKc zx`jp`5$6z$RJco-b#d!+Px>nT7T57%4!YXe{B!nSK;iN~Lt*=GDBNSN%HEW?+umNg z%cU#g*FHj-_W4h&JLM3!@Bu8P43t<=F;&_`T)3p&i(8dDou#G$N#tsdRjh7opJTFSx7wJe*k^%3GVr8DFimrP@x`>?eS z*SvIbiWBOtcb3aa>$ju$kUR>OOVPp@agzyuQO(o=OsQc0pwp`W5wDGWOv8PGn%QJL zw6~>mH~jcZ7mwb`X#jVxxQN{OpY6UZ|Jd0Gk);KRwSMi@rDy3_!w$_2%8AqnGr-^% zv|av_A-9Mb7HJ{cab_$bUTR~uuKV9XVWCO%JH`tx8{h65{8-C?#i^lcfraT((3~b4 zT34sV^DGI5O_(=`5v}m082f9wzX6K64_sy&WAy<}(5YG@kE~OsV(OI9alA2tf4b|R z^^9b9><~6fxE}>xMuQhEto(x0#L8U)G_|2Oc#y+wgO+^SG~PT`99hiJ^b_Rck}eU@>8ZI+7MTdXXj+j zJ@fkwh+_XSASwZLiswwc;xa#A^Iu}~8VlvKcds#=kU+~Y{9MUXrXMW&i(DA)Rsaj7 z##Uwja%Zoy5srB$F}`4(@mX-}mu{8U_=gdgd-54WKViOW=h=jy|D`NHW*652)TsIc zoonXLViRqR$f(Ph_MWadU-ykWj5*#Lq)s{YWq-4O_Gzak$JK2sQvjcqGPud%X99*X zW8|;+7pVXZHBem5L2^e$Y!@Fs{LEt!bqp}C=t#&IO>BzZ!e>-ZS1F-3Bcb?kjI4w; zRxVcahS{?Z04M?-rTTXLI2Bnj)x)=-@NjSNzB4!e0^m;{E^%Kbg+7#+O~Q50*q2JV zD-_8(5xULw{}a2g9uml~d6(|ux);OPG<_RdXB6OzxqFdL4oKFZZiGa`oK&GP_O$oO zQ7PwM4#IpTk5N-4@93Q|hKTl>hG^G=Ig@qWOH!XL96d#Y)=IG!^AO2zQ;mrxQxOVT zcg5!Sq<&E2vXhF*?)3y7Dc%<2C^VboK0qF`Eg5n0X}hsn-{(G5X)vji5C}NHuu-B} z&;R87YL0Tn^u)vjj(yEA%Q6DL9}SN?-#8qE^$M$o_b0bM3FqJZ4@|`u@}~$nr~F{8 zFvS*C^Tf;_Q`n;w1u@l4*Cy-nYsbUOW0{bGrj(?|Yqv>&?U*Ia*}}RQIK-y|M)9PEPF_l7T7q|^^4?WUTuc-bYB^C4MD z{H>tg;Q5L8uz~9$UT?k%kfd;xuySuZqt>_*8!Hjqc17y8wrp0kLse%z*Sp-UMeifR zGioq>$@$wrSEHPDrJ{1vM^XcKW2Rj^^57l}i_ua8diGeQhU(Jg&ziLhS89Ls=8hF% zdDuc@A0kafreoP|J{@c25-kduaT@(nS*~%`&XUI6`(UBe53^l0;59T7KYBsfg*TB8 zw_rXL*S{!Hr-YE*Ud6Jabq6Y^IXpyf!FiP}z?|aFlzE09LM|vLV@iQw9Q?{f_Hxs# zyG+yN2%TKKVte=xSU}&1CM5CyoU{D%GvF*=;~iC`5tCdjTkbva(lsIShf95c z#jA4Re_>4K_K2iaa2g8gt=*m^N^tC!-}o92TFSlUy0>JBIwE}^lGq&XqfuUxwY=W` zupluOjc>!PnSK;oOw6?cF2CQ3==5!2aMYrr0E4ndatxUZDe1Iw6%LRZymPJku*g6b zc#F6>^@pi=u5+B1kfce$&lA;D_tKpiS6~RZNc*~RxO|uz40AAX?oK??5_iKWHL)YA zM$bO}sE(R%z#7Yv2O82K-fp&x(UK_*iq)~U#xFR;elHn8G9^3W`T%e-1vlMyJE45f zN)mm)I{D9^pmL>NWHhQYK@OUd?5zAb$#>Y==5kK zzkY&W;CM1Y^es{ej~LJx;RiUQyf6RcTA#G%EX;9abrfWk)zt-%z#{fRq@>b&pFtuwP4FI5kEoy zUKe6?H*b!d&zO>Hrj-WofTD(90Do#F$!T7*0UQZymT!f*mnYc+PBwBGTPN`Oe{`~6 ztOCcp)#ZH+dOuQa_W0#E*f~(=%wgV9=gG;lcRVK7E|v~Vrx7!A0b_Goi1C7b>)bh` zMdws~4Q$l*k@K*L_^Wz@AD{}FNx5AUFLvsQ?n%fsrcA2|?xQw1x2!?m=1Mty7NT&0 zgH#`%JgrhGGqi+?$OUt*B3K#ToFY^S{HfXAJZz9LqW&?-36l>~yEt#7Ga?~Prwyya zg6hI2)i5pqS>oyuCOaX#apJ}F`wA&@R~0X3tH%mfg&D3sx>3qr1zR4_Hvti;f_~oS zgwv}vZP$8&?OP#Fqqf)0y*HFv)gy6t_K8E>Oeb}aU!+1WZCbD`K~^1bYKjF|=8vN< zOxuVw_2udIXw*ew1VrwhL`J(Voca8GVC*Kp`B0!wL*N|#QNrUId2cHaIfFGE>?RQ- z4mhqe?ImBrw^t%4M$)cgB4~OYfu}Mn#xb%P^eNNOt%{l!dsaT1nqx zgQM*$9%6Ba8INHj;%kSdUE44zj4kg1p{Z;SjYC(*_2K)4HI@WGS#)fJc2mJ;bwc%uLcJH61BAgE`}lD*gxAft@>MJcX{9=Ev_E2})6 zk+S2SS`#!?rB&?hV3J*}2`+!q*4z9GNE44-yC|PP`=ExJyTj&t7d25rIA8jngQSJe zI!Lk=Lt|COZ=)hyeb27x#5eU7QTq;jc>vIhL*yI_t7)PvXNmj3Bx9{!;&5&qy#{(g4xus+uTC z2obJ*9dc&GBz&S)5y3WKE2}=IR^`kKT{=C+EIIEmU88~=`#JYR+^DI{bu)sY@WMhT z&LX5DcY&I{^cMPMIP3_&08e|IEwuRBx6mUgt#iEY@jb)Lxo56s&K-Ql^beD>1q4O+U9IMbSzxM%+PIXHmIGU0ZEcS`o^OnZ z9z)-MSF2^18Ku+y$Hi&9ThrT~rW1Nu{vx0isv8wn)j6~oU?iDZDaCgZtXa_@6h6&8&KGnMLdH9u-%)|8~cT=RW;Qv}CZ5 z{6#=o*e2HQjm`|@{9GPyad{S~7$)#9aPj~{#l2)E3tMMO?!#gt>4c~Y8T06)T9X5x zb4>0*24>tpK_p;+suxCjhl=Ao=@QM)_$4d3foWIPak}L4!Gimj4hWc|^!NW(|MR>^ zkfBR)l%WjZ>kJlbzy&}}8xW!2&0xCPT*mZ(Puh9GPl3sUUR>u7^<=^GxKmU6rIk&3 zhtj{-3Fte(%Rfqcg|9~^X3WMgbuagBTu9+gEZY}mt4kw2W`i#5U2VK%Q@WQytbp7B z?t0;|XeDRFR*@5Ft`$PPwIjl*c)?^pIiz)ym0%*UdHSMd*SCB_`lS~fba@MX^v%-d zbIn5egvw_hY_<$UwVt!k%b${*1QVWlV4)p+ zs?9^c;<_mVbuq^rtX7lbD3XO1CAGY^q(634*}y8;c!Rap4c+l4!Fb;IklGV2P}&n3%r9fff+pXaC9_OPIwM2u7&qfdi+M<(PCf zFXlgciwOR#g)31Asx)FWow1)9JqUF5Go~=Y|7z^Zj<~WkYlM{C)4bA_t2WGS-q9dy&eL;`H{7d^36b7 z-54uU15aBrR{NuxdGye%yHZFXJP za}`0hl!*_pg{gZ39+#!SYXK6X)YpanRre^lGkjwA=NNDjeM!w=xV?#-SbQn2W7_ zSB@N|lFDh9bf1Vu;Sd~H`zWuIY;zv<;M@Q2HVY!^B$RMQtb;)n-Do`pMX`XrUae* zu>iZ1%A3_4A#_<(gf4<5?S2tlM6H|Ey+I}LlcVh;4d1|G;o6`JkKK0Ey6+I58udtW zxTODp9_Y{TKRkOU-|(91;uVIqx_$_CVr)4&;jtF}$!%MI^^I5`*3x|X3m>C$>g<59 zGvqfl=Y7$Tw9Yasx?>hcM^IEd3n!T5PJqd#`0r`EN_^&dX z5MGt>LZ_<~@u9>;w=vW7NB9dJNgEAu`DOLa&>)nSY3K#dkc30#&ae|Q@ zO#YqY8Au#4#r08mGHZaXsC9RMVFe(Mq?nWFJjovC5=d9oRe{XRe!&n-@FIkU8Mrk0 zpP(31jtxe;RADkgM0gljhqmbppCB!NwO;uTX6PQ^cJTXua3lW>C0dgG7j~sY9XuCS z#|vG+BXB0r(!ok6UfD6F-$9Rj+x1~w0PF-yFMKHrmq_IypId&_u6cv}ks6@c|MO{; zq0Un3U-+2bjeQ7}8ZrsY)$e61Il=Po_t~XP)b{;O^8s_amBRMQq7=1J;w%r$^o?)s z_1ce0%7nrLm^&U(k$-clhbWlP7xJ@mkRna0ErD7|-#gv1IZJ9tdOq&qz3=hfBo$Hv zjcw+mh=n8vm*52KD`#QFeT;!~da3-DXQbdGi=ucIxdaLKSlRly#F;%S#0Nv%j!M6& z6aDc8y+gkUnES|=fA4J|VO!K(& zq>~uwhN^_YXl*!9xb2gpnpeuFl=ZZBpR+D0Uyz7CyTssQB4nS8j!hm9Tu(obVR>Yx zFBw*=*?cH|^lkHrg(T8K#7M*)A+M+TZs~V0{n`haDJPqcrsO2+`A%*=x0wix6HFTR z-3(R#R$W=>(>QJ9XZHJ2^3M2rg2!;^q;DVF^EA_aDNS(Id=iKZzEiO7Cit zH@;cxl)dovMIMG(7QS3V6q3p}JxXR@Rg}1PJMx@HovmuivW9=!ZG=m%x5gVgD4TdDtFB}?^A*oro$L+wNnTrcpQewH z6t-*V$oZJuqmd9&TrVi7pW1%zr>$9Ae5Hn?yU|<~-&k`@QAXuWQ3OJ#)sS7dWG($R ziOAjW5+qZzK7X$FlQ-T325Tv@WpBI-J_t zufD!5arxVoN!G%3f%V~+Dq1JLVkjT+FuY-JBe0pZW@M)gevxD?CR^d*}{($c8m+aN}_Qd=S8Qi{mZ{j2Mq#ttxL#lfZ#;S!j&KkUb6?0@RPHg(> z$%x0dX@hP_ucu$^RFH9dV9rx2CtBXL>2w{jvq#+VxM{1QNK{xBJBD%W4!lpRbQxAB zzYPiihC6Q!&=Te%DBoYxTyk5U4zqTj2$MFwp41X(O@bj zCNjqHn>tH>j9_qWU)m1OeLyA$R_z_s&9TO1GtrgjusYdYE$-P3n^I z=JsVLlSj$zcxNFq9zZMKT)36 z`=Alzzwg0Wed%w3(xf1-V@_d)`JRAd4#@RRbl&r{-~pe+-aP#!VtwCo+IY8HrbcDu zChAbuh;IC?gx+D7<$T_(_N}Sv5fSP29ctKk^ZKFpm6etC3Cr@GC6Pgvd~Bm7L#=X& zZ4}1npbNs{$qxgC4Q;Y{9@GvfJbrJu^oCT)KQ+4i{*}9~F07mZ6cQrE98osQG0%O( z&QBRVo@VW^2o%O&d&NtEpLj@1i103~SH5R{V75}6VOjX1V&zSgciCIDQElx*{-pHjvySU^!Y9=<2BXf$ry=5^H zF5q~V#D153spg#SJI~3RQb9sXBCjEPwKRmBMASd3K)3U24pNj(Fh4=*6OKq7JDx@F zX0^NZywLKc;IS_i#66c)Rl*2dW>~4?*aoAsU_Rvw ztz#Se0aB$CAk#x6p1d^Kt#y#|uqb44lu^PXC0Ef^yPd6)Q(~qEP=Z$gCIRQu$8t3ap5x~a0fOwwCF)b z*3SJE;{sC2j|L!m>|Fe;zd;@^Z0Reqe|AAF#KAKUXN&_*H0)}>a+7mP7XY??{W<1P zg%H_~Sm(Bbe1tk{2ohSKelh4-B%B=5E)K0#H71)Xn{Sv)dI%gBc7>NxojDpBYbN>`R`KqVvwR z!n1~>px}%afz}STF|_7^P~We z>W>0>gVx4CD%2a!?O4PWWxrSLMeaL^>(l~1_YZp2!EpZO!>DAtHzNaBSGTmFRYq{> z>Z02uqG$5PC-N>t!0)be&~lb*{Eg#=zxU;xq+w?RS50djynNHRECCve{R{Ms033r$ ze-7QZycLQfp)H6##a@8~ZF1KvFQ*iI`~!jSSFPL)b37Dn!A58SPN^c}J%-LJk9>hO zP!^8axK8A#6n(y+X%11wRDRKUYf+QiewIc0G>*jGAnTyVp3p}!gF$>*=K?Z%(dPL9 zKYBx)^knWz=lO%HurkeLY?$m>s6mrqn%!$WV_!~})#e#f=%!4g2hNXJQZ|(Ey#6C1 z2p_ygikNCzCqeh7LY(z32{r0TW{PX-Tsi%9flLpncH^G)mLyzvC*BTv}IrTjuVQ10uAD=QKbCj#pVq{*Dxi+*HkbYUtQNuv>K=@AJN& z1JuMb1CWC{aCj2GC$({kg;=LwNzB=RMul4`!ZDAy+r-EdSw1zJbKxDdzy+uoVOsOB z3*g^6=}_k_JNBL?9ZkzVW-HZQYzj2-=ffCp>&J85_#;Sl~@@ z{RM~~BOh<#O#E+G2pX4gWqX(xWitC=?hewxkFhxKGlp^h!F|`THRCHzXG+UrMh0$t z2so}A^)bTs7)zk9_h*B^07QTp^hD=D6p->J0cK$;=_Z?KI{CW}2>$aHLF60~9>gPk zDMqp)y1Mji5a*jRLC(Z|G2z0fbY(2661wK(3eevSqTFK|k(`jNE_8oqJ z34WOn3`I#!3<{CX)1PjyZSTcS>s8wxHnk~ zu)IT$k?L^Uu4styu10&lP#QAyTW-lhEM+B0y!MPA5tnh#_lX@PPO=4x>!6-i+6Y)l zX`WCFHGoK?ehTCm+VcdT*(An3hP_WoVREFNxUsy*i4v6A5*=02Ojb0jQcB1IKpaAA z_*aMpEV($WPy!L}hQ>>peZe&;$CwG_!S-jZn&I?Lx!gG|a6^ zw{WuM$~J>7kVp>JmQBuV2=r7xj_oa^bnBKH@R3@k&@{`Beaj$=?!PyY;O?!yzi}D5 zS#a{(?D_l?2SOEldhRE7Tc@YIIc}C;EA)O5i&gi%16ue)1+mMhxY2vsNgrAK1o+tD zsafaNepgq9tDlN5s!@49!(4{^)ATh!NMQ=!IgHE>aJ_D&nD5A_%B+F}KmGaN)EbSg zN3Jj%+qaGJ1!8@-N^>PauJV_7(PZ%Eni8x-F%ei7-@~aa2IN@|+G!eNF z;bTLcO*$HWXdcuFUd)DG$k>!^&yNV~EIoD781GH)X$oVWGA-5wz0qm~VH8f0FA+I* zMD!;eXd7;+*nf+Fx=)NCVoE0(>dlZHFD%uo6n)%J{FHXkGYGCpx}Gc%KbsC*-wm3; z>r)HJwDkeHa>&xCwcQl#oQ+9v*pEjP`t?U@Lk50amzrFO?P&MF1-8+o4&|HoLag>W zMYezK1T{3@vVWFJ!Ec}r85Wc`SHF#*A)W7EO+R~n#Yb6`?TjtmmtSK_W~9040AZsg z+1ZWj)uAUZL1TD@Iuo6h(~>C9ZsUlf@8*>|3X(k#o)cy+Wm8nl_H>b{!`K><9Dx(m zGSL@%v!VIk0>#Jd6KlYw95RVK9seQM+mRL%`NbOCs&i9BFCVryp^vnol*h~-DJ@JT z{Y^xwhi^T`OubjlB|eY7EheZ@)_OHZMzld($Z4qvf4SaXKeA1-&UZ`JJv9}UJzpaJ zkrTCUfC_L(oqkJ~=q_jR4DM9k8rwq$ap?%>B%mWxH{n>p3=OQ~Om)uLqxfj?d=kGj zS*e>IMd7d?!Y?--soCaX?px4&zZ9u#47S07S)xFspI<2pSD+DN{$Mk$#?4cfFYRM< z0O;2=ueMl0FAz9JQF(3{vU0i-sdn$CY}e|iDrH6DeD0W^TKr(ht_;5KC^jkTzPZi6 zyuChQcs>4GnAN3k+#+RspwHEOpW^^MpK!BDPs6hp(n1ACc457svfka^Zv3e7DCD2{ zd;OPv`D=d~FzFR^N>x&22*^^Ku0ZB$Ti`f_aIu+}b1d*76+H_M3J)Hym#chKsZBwG z&y<&DOkAY+i=@n5u39Xb3p6DNk$7H>eX|p&PNFb=a^`}@boIhwDm~p%JG5PFaA@DZ zsYzpEQppJyt0o0*Gqgi&He)er1`!0&Dy@Mwm+=*&6OWhm%pJ`zUVcfS7UUDtWd7c# z;AW2~1&v|ili*VjRrPKa$HYs7M7>fJXiu5{_%B zypfWZ6N_HWb(Mc=mV?G#0kl){BP}01-s#B%oBq&~F+`g?jCrWzsSX=} zW_90zS9YBDL|mW-fe^0ok#it6neLn;^)?$*;h&P7!&BLQ?x0njf=tDAY?XF8R9Hxl zm+kN4ehbHN<%RyKphY&zZyr>4xr~5%qsQ8{bz);x zK!||@*Y0|g+t@Z7<^RF`7X09KKIywa8Kh{j+3%@i$FTdjDx%^-U`gvbeB=O--V8!!{q0xa*M zzE|Zzx-AO0Z(1yM6>chixh$rwL1EFEDOf6FJIHhKXWd}*F7AO1ztWg4*Fq;EWt17( z)s`GS5Na#U75l{H91CaWf{4x*r+z|nlLot=ZYqZ5oO-{Y_GGAk?Zv0X)(ef^JTgs` zt!zqV-gs)z2nP00&k zKwzLgw4eXbV+)szd4cQ`n#U-(aBUz_<#{u6FCw==1y_xHGG>uvs$DqmU3$vY0E7E1 z-vxx^(vp@3EK^x&zcF$mMRN;ieZSAuZ{xpZtmHw`RflN6=M-~glU@eJn&5e6PxhSi zwvy#Nd9N1Lu#F;kv5?~;kqN{LV2~;d&qD%Y5Fp!s{)QVgtvJhn7bU?@D4Rj$nr0M2 z0kzu(KymY~BhACY1>` zUc?`|mA;$LYTTL~9!9e)zC;cv!71t?AHr0p0q@oD_C3|p9EVLl_8831$LMbTj$8sK zkS3q>kuT1b@ok_TtblC-G1*v{YHF`LD8H!Z+MGU3;R(GPtG{f2d&S$bL}C13B$g&r zApAGP0J7A7JUl&GIv#o#K8l%b0gj3&&wSYtedkTpo8BP&cuN57{0Eu4q|{b*8}v`9 z+g?Ph-9ZBUUvkXn`k_Z_UJrx7Mu?ZlqHe!3+iIFVW5^`<<3Y4&V|JN%OGC~A{*bVn zNIZG+X~d|k*?#$>YO-L6F`;mc(-c}nAt<2%6H-aGqqzXl7^YtI=fjQv2%dr}w1h`O zXc!?eHMIk=A!85nYdM*f0lW*7P+_%X92DZ<2i{Q~c# zTroe}h7rPP+W?C#RcM{dFKjRd&r^5}VTu@ApV(kff`!81vMEyoUM^6H6KY1Q zmTdQ$CsnTemoxREmD!Bj&Jq+4n%d=d_2nzb6)I8)Kt{c+Fhaa!xDxB-I(scH7|}=9 za%U!vTDS31jBA>2DRkn*pV%M7We7b@eZ247jg~#bU{tHhw2)97#K;9~Gr|(D|D>-} z{x%Mf;rnOA8Z=}@i>%~S`qxfiSC7$&bB|r-(Rh~!@$T~)1?y*4R9*!{8LncdbeQsP zLj&6fLmu{_l+o9^8^b^TiiPyzia6y?Ev?^kY@O*Qia{Hu>s-OI>o6BrRLoC@?>sI$ z`n_oC7S3&Qdl*vi<)>$a_2(mvauWQ`J&TA|m|0)yq_pqR)jX3d@yU*#T$A$G0BN^= z8g|z}9sK;W`bADNhM&?%Zfqq8d`vqy`@26vj4uT6S+A#_)u31HTzm#gSf z^(6q>j|aWB$xZaF-oIiSKkz%E4$|FqU=q+0{xkiMvAq`1FVa#eZ9wKU=%|`=8Z93T z)oV<&l|B5-9_FJ{PhzC`AIhlgq@%=XOOeW81Seg<|HUXQ`fm1qaf6%sy6eOIaeh>4 zU|4Jqv2b6WDb%jCS(IuG5;lKfF|zqC`e5B@tGW;o0KK$*!Wu%a;$j|^c>2iMTGMp> zeRDLleLgo9MSMX+fg`sR_hE0Ny(&b{SE-PFjntlSOrm5WbYO;I<}UoN7}H;H2Rz65#9 zb@GtfxpKBjWaWO$Y;NPyD+L7FyP)vnH*gb%Jw0173(`3v@iV`#eVi%#S5O%oBhY3j z#&e^OwTz35(y@OA#g!^pY!b3_q(&-`oCcMi165d4j*6$LXqOKfgS;=wVmItdWsHX| z6C+hD=5B!orJ_9 z($W@Mof%cRA5xnJI&Ntfm^G4QuR`|R6wpm?p;@nwt|})vtUQZ!nIId+Hvsp_IUG1W&B2s7**Dzk)*KlF5j8wAGp&|1kS!Vy1ALy$u^>{)@O$j&r;1CJhteIm z-zR<4i2GTaR1RwKd*`R)&Z*;gb0@~F^Ei%eGo(z)}?qH9OH3x?7gqsOACI%cgu99TF1f!jd758TvY<8)gh;^@)>dC z{2ece1NU|c!`DRc*C@P?^@VOM@v@lgkRplw_*)3$!STk;Kfr;ccH^q-6ZyInh85it{CEOI`9!?BKo9iJX!_k8VSkYh{Pf=u@?|)6Qug>ZP%Zijk0R`Pv)i;X~HP2*eut`BD3Fs z-)nrBn^Eb=tz2T=`vL7X+pVbD3cCB>0V?(cqs|KL5EX@!lyQKH!P?b=DXO(;i^-Vj z`K-I_{IA^&MSMsGTXgBvrAGsaS@w`~#orbz);ZfFt;U5aDwRA7&BWlwALzqn$qmLq z5pps(J@vm%H2Lcoj0r@>_UUIpr|JJmwK0)H$Hx;#4h0g24enPKR`UE>F25kPn~QJo zM!b7uvOwnh1_;^}+HyA>*>^G$jYmuf6Miplu*Pz-7fV&EpgpCB#=bd1(<4Xz5^=rO z=2zR|7i}q|ZgB;#L-D)+JjnKbrLmm;bh+NAj`VW+L@51>-XtsBD&dTNr!B&&B`M?_ zXm?L58T&vcOXplQ!^>sc>$ix+%8Ty=nggb@e)UZa{*p$X%q3eGucHD?_tZ-Xwvx92 zulgTAP5?#0#8#2*VZFd>MnS9rcX>PGtGovILvmeNk27C%oCu^m7s!At zvM?)>1Px*KT(gPsluDCTSsv(-Vyqv!HE<%Eccb>j#o&1}N51)qCA7L=Rq+J0-t5;p zr9?#wDy|36Bh1W$dR0X4KSM~6)uO``f~)>(w)dX9Tl6MXGle@ei|sdb2US({`d_YL zJ;vuAUv_@;V?y8zNIc1{kuZ4Qf2`Kp zK5gc1|72c6K<)hvuP@JqB)C9_tI5fBNYQBDUC)uV0R=-i;bXTZ~2~mJB1v zRU##J(~lgADnyZq^H%1olZ&6rNac%a(AQtV$w8dk!_UcSRV-7t!`Qg=GR+^d6ou6v z39qNhACxE@WCkr^rBTiuZGowZ`5yvvGI3?yAKp=SSzD3gK4 ztb7Gpsu!*w<$FETi$TOh@My9GbDULW;EHdD5|!mFa`0OPn>LNfFVFiuLw+9^hZdy{ z34{l}Ghig|^ONDzcye_ze@*7~q(@R(?pdN@j8@VmixA1(vQq`$4Q^J`rY_X1G-57u z*XlK2Z(Q9QFn9LIFY`q?NsQfIQ4Ncy`t~p)uxf@}u2@p-l*-ri^ul+I6I!^}g1pKu zuow@S35`A%@@P8*K?ui>cM7N8K<;k6q$d|-Z{F*2J@W~2TgDqd{4F!!Ckzk@yLlr5 zr`aS*cCa(9^q==+EXoxBRv}8qc)J_LKgkY^T^47EPa0K^6x&s{gg(&DEO8@PVEQ5k^)1wUma9mTY+Z^;XZ^Bv5H zit>*Roj(bRw-%}`oiM7{E@epJRfSv{wS5jMTbWPpE_qe+N8u4+7hNxr2+nB?Ojf^B zQY0hJ@609=)gGz8@}(UzKNjqmeFcg`6chYlTN@iiE)u?T?xpYp?bFl|9Ot?uY4Rrv zRFeo7-^trS<9o=;^>;4(_<%b$tUT++GHb6N2g#jc)Gx$FlSpZ0-=()t&Tw@?^~YlS3yD zxxPPsZ(q%1Ia!^I%By2rI_D~d7U3d~?p_4%1pt*_KX;4TdZA~FEly6F$9oRVGO9uW zE^MS8$<_a!uKGPB3;x%a&!J63;um*zcD{)^Uf$l`n~ZlJJb0iU?6OF9 vOUFZ7$bV%6rDn+}!0~&X{ONG~oXM`CwO8 literal 0 HcmV?d00001 diff --git a/stealth.min.js b/stealth.min.js new file mode 100644 index 0000000..495bed1 --- /dev/null +++ b/stealth.min.js @@ -0,0 +1,7 @@ +/*! + * Note: Auto-generated, do not update manually. + * Generated by: https://github.com/berstend/puppeteer-extra/tree/master/packages/extract-stealth-evasions + * Generated on: Mon, 03 Feb 2025 06:22:37 GMT + * License: MIT + */ +(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:'utils => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, \'chrome\')`\n Object.defineProperty(window, \'chrome\', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We\'ll extend that later\n })\n }\n\n // That means we\'re running headful and don\'t need to mock anything\n if (\'app\' in window.chrome) {\n return // Nothing to do here\n }\n\n const makeError = {\n ErrorInInvocation: fn => {\n const err = new TypeError(`Error in invocation of app.${fn}()`)\n return utils.stripErrorWithAnchor(\n err,\n `at ${fn} (eval at `\n )\n }\n }\n\n // There\'s a some static data in that property which doesn\'t seem to change,\n // we should periodically check for updates: `JSON.stringify(window.app, null, 2)`\n const STATIC_DATA = JSON.parse(\n `\n{\n "isInstalled": false,\n "InstallState": {\n "DISABLED": "disabled",\n "INSTALLED": "installed",\n "NOT_INSTALLED": "not_installed"\n },\n "RunningState": {\n "CANNOT_RUN": "cannot_run",\n "READY_TO_RUN": "ready_to_run",\n "RUNNING": "running"\n }\n}\n `.trim()\n )\n\n window.chrome.app = {\n ...STATIC_DATA,\n\n get isInstalled() {\n return false\n },\n\n getDetails: function getDetails() {\n if (arguments.length) {\n throw makeError.ErrorInInvocation(`getDetails`)\n }\n return null\n },\n getIsInstalled: function getDetails() {\n if (arguments.length) {\n throw makeError.ErrorInInvocation(`getIsInstalled`)\n }\n return false\n },\n runningState: function getDetails() {\n if (arguments.length) {\n throw makeError.ErrorInInvocation(`runningState`)\n }\n return \'cannot_run\'\n }\n }\n utils.patchToStringNested(window.chrome.app)\n }',_args:[]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"utils => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`\n Object.defineProperty(window, 'chrome', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We'll extend that later\n })\n }\n\n // That means we're running headful and don't need to mock anything\n if ('csi' in window.chrome) {\n return // Nothing to do here\n }\n\n // Check that the Navigation Timing API v1 is available, we need that\n if (!window.performance || !window.performance.timing) {\n return\n }\n\n const { timing } = window.performance\n\n window.chrome.csi = function() {\n return {\n onloadT: timing.domContentLoadedEventEnd,\n startE: timing.navigationStart,\n pageT: Date.now() - timing.navigationStart,\n tran: 15 // Transition type or something\n }\n }\n utils.patchToString(window.chrome.csi)\n }",_args:[]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts }) => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`\n Object.defineProperty(window, 'chrome', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We'll extend that later\n })\n }\n\n // That means we're running headful and don't need to mock anything\n if ('loadTimes' in window.chrome) {\n return // Nothing to do here\n }\n\n // Check that the Navigation Timing API v1 + v2 is available, we need that\n if (\n !window.performance ||\n !window.performance.timing ||\n !window.PerformancePaintTiming\n ) {\n return\n }\n\n const { performance } = window\n\n // Some stuff is not available on about:blank as it requires a navigation to occur,\n // let's harden the code to not fail then:\n const ntEntryFallback = {\n nextHopProtocol: 'h2',\n type: 'other'\n }\n\n // The API exposes some funky info regarding the connection\n const protocolInfo = {\n get connectionInfo() {\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ntEntry.nextHopProtocol\n },\n get npnNegotiatedProtocol() {\n // NPN is deprecated in favor of ALPN, but this implementation returns the\n // HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)\n ? ntEntry.nextHopProtocol\n : 'unknown'\n },\n get navigationType() {\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ntEntry.type\n },\n get wasAlternateProtocolAvailable() {\n // The Alternate-Protocol header is deprecated in favor of Alt-Svc\n // (https://www.mnot.net/blog/2016/03/09/alt-svc), so technically this\n // should always return false.\n return false\n },\n get wasFetchedViaSpdy() {\n // SPDY is deprecated in favor of HTTP/2, but this implementation returns\n // true for HTTP/2 or HTTP2+QUIC/39 as well.\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)\n },\n get wasNpnNegotiated() {\n // NPN is deprecated in favor of ALPN, but this implementation returns true\n // for HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)\n }\n }\n\n const { timing } = window.performance\n\n // Truncate number to specific number of decimals, most of the `loadTimes` stuff has 3\n function toFixed(num, fixed) {\n var re = new RegExp('^-?\\\\d+(?:.\\\\d{0,' + (fixed || -1) + '})?')\n return num.toString().match(re)[0]\n }\n\n const timingInfo = {\n get firstPaintAfterLoadTime() {\n // This was never actually implemented and always returns 0.\n return 0\n },\n get requestTime() {\n return timing.navigationStart / 1000\n },\n get startLoadTime() {\n return timing.navigationStart / 1000\n },\n get commitLoadTime() {\n return timing.responseStart / 1000\n },\n get finishDocumentLoadTime() {\n return timing.domContentLoadedEventEnd / 1000\n },\n get finishLoadTime() {\n return timing.loadEventEnd / 1000\n },\n get firstPaintTime() {\n const fpEntry = performance.getEntriesByType('paint')[0] || {\n startTime: timing.loadEventEnd / 1000 // Fallback if no navigation occured (`about:blank`)\n }\n return toFixed(\n (fpEntry.startTime + performance.timeOrigin) / 1000,\n 3\n )\n }\n }\n\n window.chrome.loadTimes = function() {\n return {\n ...protocolInfo,\n ...timingInfo\n }\n }\n utils.patchToString(window.chrome.loadTimes)\n }",_args:[{opts:{}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts, STATIC_DATA }) => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`\n Object.defineProperty(window, 'chrome', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We'll extend that later\n })\n }\n\n // That means we're running headful and don't need to mock anything\n const existsAlready = 'runtime' in window.chrome\n // `chrome.runtime` is only exposed on secure origins\n const isNotSecure = !window.location.protocol.startsWith('https')\n if (existsAlready || (isNotSecure && !opts.runOnInsecureOrigins)) {\n return // Nothing to do here\n }\n\n window.chrome.runtime = {\n // There's a bunch of static data in that property which doesn't seem to change,\n // we should periodically check for updates: `JSON.stringify(window.chrome.runtime, null, 2)`\n ...STATIC_DATA,\n // `chrome.runtime.id` is extension related and returns undefined in Chrome\n get id() {\n return undefined\n },\n // These two require more sophisticated mocks\n connect: null,\n sendMessage: null\n }\n\n const makeCustomRuntimeErrors = (preamble, method, extensionId) => ({\n NoMatchingSignature: new TypeError(\n preamble + `No matching signature.`\n ),\n MustSpecifyExtensionID: new TypeError(\n preamble +\n `${method} called from a webpage must specify an Extension ID (string) for its first argument.`\n ),\n InvalidExtensionID: new TypeError(\n preamble + `Invalid extension id: '${extensionId}'`\n )\n })\n\n // Valid Extension IDs are 32 characters in length and use the letter `a` to `p`:\n // https://source.chromium.org/chromium/chromium/src/+/master:components/crx_file/id_util.cc;drc=14a055ccb17e8c8d5d437fe080faba4c6f07beac;l=90\n const isValidExtensionID = str =>\n str.length === 32 && str.toLowerCase().match(/^[a-p]+$/)\n\n /** Mock `chrome.runtime.sendMessage` */\n const sendMessageHandler = {\n apply: function(target, ctx, args) {\n const [extensionId, options, responseCallback] = args || []\n\n // Define custom errors\n const errorPreamble = `Error in invocation of runtime.sendMessage(optional string extensionId, any message, optional object options, optional function responseCallback): `\n const Errors = makeCustomRuntimeErrors(\n errorPreamble,\n `chrome.runtime.sendMessage()`,\n extensionId\n )\n\n // Check if the call signature looks ok\n const noArguments = args.length === 0\n const tooManyArguments = args.length > 4\n const incorrectOptions = options && typeof options !== 'object'\n const incorrectResponseCallback =\n responseCallback && typeof responseCallback !== 'function'\n if (\n noArguments ||\n tooManyArguments ||\n incorrectOptions ||\n incorrectResponseCallback\n ) {\n throw Errors.NoMatchingSignature\n }\n\n // At least 2 arguments are required before we even validate the extension ID\n if (args.length < 2) {\n throw Errors.MustSpecifyExtensionID\n }\n\n // Now let's make sure we got a string as extension ID\n if (typeof extensionId !== 'string') {\n throw Errors.NoMatchingSignature\n }\n\n if (!isValidExtensionID(extensionId)) {\n throw Errors.InvalidExtensionID\n }\n\n return undefined // Normal behavior\n }\n }\n utils.mockWithProxy(\n window.chrome.runtime,\n 'sendMessage',\n function sendMessage() {},\n sendMessageHandler\n )\n\n /**\n * Mock `chrome.runtime.connect`\n *\n * @see https://developer.chrome.com/apps/runtime#method-connect\n */\n const connectHandler = {\n apply: function(target, ctx, args) {\n const [extensionId, connectInfo] = args || []\n\n // Define custom errors\n const errorPreamble = `Error in invocation of runtime.connect(optional string extensionId, optional object connectInfo): `\n const Errors = makeCustomRuntimeErrors(\n errorPreamble,\n `chrome.runtime.connect()`,\n extensionId\n )\n\n // Behavior differs a bit from sendMessage:\n const noArguments = args.length === 0\n const emptyStringArgument = args.length === 1 && extensionId === ''\n if (noArguments || emptyStringArgument) {\n throw Errors.MustSpecifyExtensionID\n }\n\n const tooManyArguments = args.length > 2\n const incorrectConnectInfoType =\n connectInfo && typeof connectInfo !== 'object'\n\n if (tooManyArguments || incorrectConnectInfoType) {\n throw Errors.NoMatchingSignature\n }\n\n const extensionIdIsString = typeof extensionId === 'string'\n if (extensionIdIsString && extensionId === '') {\n throw Errors.MustSpecifyExtensionID\n }\n if (extensionIdIsString && !isValidExtensionID(extensionId)) {\n throw Errors.InvalidExtensionID\n }\n\n // There's another edge-case here: extensionId is optional so we might find a connectInfo object as first param, which we need to validate\n const validateConnectInfo = ci => {\n // More than a first param connectInfo as been provided\n if (args.length > 1) {\n throw Errors.NoMatchingSignature\n }\n // An empty connectInfo has been provided\n if (Object.keys(ci).length === 0) {\n throw Errors.MustSpecifyExtensionID\n }\n // Loop over all connectInfo props an check them\n Object.entries(ci).forEach(([k, v]) => {\n const isExpected = ['name', 'includeTlsChannelId'].includes(k)\n if (!isExpected) {\n throw new TypeError(\n errorPreamble + `Unexpected property: '${k}'.`\n )\n }\n const MismatchError = (propName, expected, found) =>\n TypeError(\n errorPreamble +\n `Error at property '${propName}': Invalid type: expected ${expected}, found ${found}.`\n )\n if (k === 'name' && typeof v !== 'string') {\n throw MismatchError(k, 'string', typeof v)\n }\n if (k === 'includeTlsChannelId' && typeof v !== 'boolean') {\n throw MismatchError(k, 'boolean', typeof v)\n }\n })\n }\n if (typeof extensionId === 'object') {\n validateConnectInfo(extensionId)\n throw Errors.MustSpecifyExtensionID\n }\n\n // Unfortunately even when the connect fails Chrome will return an object with methods we need to mock as well\n return utils.patchToStringNested(makeConnectResponse())\n }\n }\n utils.mockWithProxy(\n window.chrome.runtime,\n 'connect',\n function connect() {},\n connectHandler\n )\n\n function makeConnectResponse() {\n const onSomething = () => ({\n addListener: function addListener() {},\n dispatch: function dispatch() {},\n hasListener: function hasListener() {},\n hasListeners: function hasListeners() {\n return false\n },\n removeListener: function removeListener() {}\n })\n\n const response = {\n name: '',\n sender: undefined,\n disconnect: function disconnect() {},\n onDisconnect: onSomething(),\n onMessage: onSomething(),\n postMessage: function postMessage() {\n if (!arguments.length) {\n throw new TypeError(`Insufficient number of arguments.`)\n }\n throw new Error(`Attempting to use a disconnected port object`)\n }\n }\n return response\n }\n }",_args:[{opts:{runOnInsecureOrigins:!1},STATIC_DATA:{OnInstalledReason:{CHROME_UPDATE:"chrome_update",INSTALL:"install",SHARED_MODULE_UPDATE:"shared_module_update",UPDATE:"update"},OnRestartRequiredReason:{APP_UPDATE:"app_update",OS_UPDATE:"os_update",PERIODIC:"periodic"},PlatformArch:{ARM:"arm",ARM64:"arm64",MIPS:"mips",MIPS64:"mips64",X86_32:"x86-32",X86_64:"x86-64"},PlatformNaclArch:{ARM:"arm",MIPS:"mips",MIPS64:"mips64",X86_32:"x86-32",X86_64:"x86-64"},PlatformOs:{ANDROID:"android",CROS:"cros",LINUX:"linux",MAC:"mac",OPENBSD:"openbsd",WIN:"win"},RequestUpdateCheckStatus:{NO_UPDATE:"no_update",THROTTLED:"throttled",UPDATE_AVAILABLE:"update_available"}}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"utils => {\n /**\n * Input might look funky, we need to normalize it so e.g. whitespace isn't an issue for our spoofing.\n *\n * @example\n * video/webm; codecs=\"vp8, vorbis\"\n * video/mp4; codecs=\"avc1.42E01E\"\n * audio/x-m4a;\n * audio/ogg; codecs=\"vorbis\"\n * @param {String} arg\n */\n const parseInput = arg => {\n const [mime, codecStr] = arg.trim().split(';')\n let codecs = []\n if (codecStr && codecStr.includes('codecs=\"')) {\n codecs = codecStr\n .trim()\n .replace(`codecs=\"`, '')\n .replace(`\"`, '')\n .trim()\n .split(',')\n .filter(x => !!x)\n .map(x => x.trim())\n }\n return {\n mime,\n codecStr,\n codecs\n }\n }\n\n const canPlayType = {\n // Intercept certain requests\n apply: function(target, ctx, args) {\n if (!args || !args.length) {\n return target.apply(ctx, args)\n }\n const { mime, codecs } = parseInput(args[0])\n // This specific mp4 codec is missing in Chromium\n if (mime === 'video/mp4') {\n if (codecs.includes('avc1.42E01E')) {\n return 'probably'\n }\n }\n // This mimetype is only supported if no codecs are specified\n if (mime === 'audio/x-m4a' && !codecs.length) {\n return 'maybe'\n }\n\n // This mimetype is only supported if no codecs are specified\n if (mime === 'audio/aac' && !codecs.length) {\n return 'probably'\n }\n // Everything else as usual\n return target.apply(ctx, args)\n }\n }\n\n /* global HTMLMediaElement */\n utils.replaceWithProxy(\n HTMLMediaElement.prototype,\n 'canPlayType',\n canPlayType\n )\n }",_args:[]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts }) => {\n utils.replaceGetterWithProxy(\n Object.getPrototypeOf(navigator),\n 'hardwareConcurrency',\n utils.makeHandler().getterValue(opts.hardwareConcurrency)\n )\n }",_args:[{opts:{hardwareConcurrency:4}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts }) => {\n const languages = opts.languages.length\n ? opts.languages\n : ['en-US', 'en']\n utils.replaceGetterWithProxy(\n Object.getPrototypeOf(navigator),\n 'languages',\n utils.makeHandler().getterValue(Object.freeze([...languages]))\n )\n }",_args:[{opts:{languages:[]}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, opts) => {\n const isSecure = document.location.protocol.startsWith('https')\n\n // In headful on secure origins the permission should be \"default\", not \"denied\"\n if (isSecure) {\n utils.replaceGetterWithProxy(Notification, 'permission', {\n apply() {\n return 'default'\n }\n })\n }\n\n // Another weird behavior:\n // On insecure origins in headful the state is \"denied\",\n // whereas in headless it's \"prompt\"\n if (!isSecure) {\n const handler = {\n apply(target, ctx, args) {\n const param = (args || [])[0]\n\n const isNotifications =\n param && param.name && param.name === 'notifications'\n if (!isNotifications) {\n return utils.cache.Reflect.apply(...arguments)\n }\n\n return Promise.resolve(\n Object.setPrototypeOf(\n {\n state: 'denied',\n onchange: null\n },\n PermissionStatus.prototype\n )\n )\n }\n }\n // Note: Don't use `Object.getPrototypeOf` here\n utils.replaceWithProxy(Permissions.prototype, 'query', handler)\n }\n }",_args:[{}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { fns, data }) => {\n fns = utils.materializeFns(fns)\n\n // That means we're running headful\n const hasPlugins = 'plugins' in navigator && navigator.plugins.length\n if (hasPlugins) {\n return // nothing to do here\n }\n\n const mimeTypes = fns.generateMimeTypeArray(utils, fns)(data.mimeTypes)\n const plugins = fns.generatePluginArray(utils, fns)(data.plugins)\n\n // Plugin and MimeType cross-reference each other, let's do that now\n // Note: We're looping through `data.plugins` here, not the generated `plugins`\n for (const pluginData of data.plugins) {\n pluginData.__mimeTypes.forEach((type, index) => {\n plugins[pluginData.name][index] = mimeTypes[type]\n\n Object.defineProperty(plugins[pluginData.name], type, {\n value: mimeTypes[type],\n writable: false,\n enumerable: false, // Not enumerable\n configurable: true\n })\n Object.defineProperty(mimeTypes[type], 'enabledPlugin', {\n value:\n type === 'application/x-pnacl'\n ? mimeTypes['application/x-nacl'].enabledPlugin // these reference the same plugin, so we need to re-use the Proxy in order to avoid leaks\n : new Proxy(plugins[pluginData.name], {}), // Prevent circular references\n writable: false,\n enumerable: false, // Important: `JSON.stringify(navigator.plugins)`\n configurable: true\n })\n })\n }\n\n const patchNavigator = (name, value) =>\n utils.replaceProperty(Object.getPrototypeOf(navigator), name, {\n get() {\n return value\n }\n })\n\n patchNavigator('mimeTypes', mimeTypes)\n patchNavigator('plugins', plugins)\n\n // All done\n }",_args:[{fns:{generateMimeTypeArray:"(utils, fns) => mimeTypesData => {\n return fns.generateMagicArray(utils, fns)(\n mimeTypesData,\n MimeTypeArray.prototype,\n MimeType.prototype,\n 'type'\n )\n}",generatePluginArray:"(utils, fns) => pluginsData => {\n return fns.generateMagicArray(utils, fns)(\n pluginsData,\n PluginArray.prototype,\n Plugin.prototype,\n 'name'\n )\n}",generateMagicArray:"(utils, fns) =>\n function(\n dataArray = [],\n proto = MimeTypeArray.prototype,\n itemProto = MimeType.prototype,\n itemMainProp = 'type'\n ) {\n // Quick helper to set props with the same descriptors vanilla is using\n const defineProp = (obj, prop, value) =>\n Object.defineProperty(obj, prop, {\n value,\n writable: false,\n enumerable: false, // Important for mimeTypes & plugins: `JSON.stringify(navigator.mimeTypes)`\n configurable: true\n })\n\n // Loop over our fake data and construct items\n const makeItem = data => {\n const item = {}\n for (const prop of Object.keys(data)) {\n if (prop.startsWith('__')) {\n continue\n }\n defineProp(item, prop, data[prop])\n }\n return patchItem(item, data)\n }\n\n const patchItem = (item, data) => {\n let descriptor = Object.getOwnPropertyDescriptors(item)\n\n // Special case: Plugins have a magic length property which is not enumerable\n // e.g. `navigator.plugins[i].length` should always be the length of the assigned mimeTypes\n if (itemProto === Plugin.prototype) {\n descriptor = {\n ...descriptor,\n length: {\n value: data.__mimeTypes.length,\n writable: false,\n enumerable: false,\n configurable: true // Important to be able to use the ownKeys trap in a Proxy to strip `length`\n }\n }\n }\n\n // We need to spoof a specific `MimeType` or `Plugin` object\n const obj = Object.create(itemProto, descriptor)\n\n // Virtually all property keys are not enumerable in vanilla\n const blacklist = [...Object.keys(data), 'length', 'enabledPlugin']\n return new Proxy(obj, {\n ownKeys(target) {\n return Reflect.ownKeys(target).filter(k => !blacklist.includes(k))\n },\n getOwnPropertyDescriptor(target, prop) {\n if (blacklist.includes(prop)) {\n return undefined\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n }\n })\n }\n\n const magicArray = []\n\n // Loop through our fake data and use that to create convincing entities\n dataArray.forEach(data => {\n magicArray.push(makeItem(data))\n })\n\n // Add direct property access based on types (e.g. `obj['application/pdf']`) afterwards\n magicArray.forEach(entry => {\n defineProp(magicArray, entry[itemMainProp], entry)\n })\n\n // This is the best way to fake the type to make sure this is false: `Array.isArray(navigator.mimeTypes)`\n const magicArrayObj = Object.create(proto, {\n ...Object.getOwnPropertyDescriptors(magicArray),\n\n // There's one ugly quirk we unfortunately need to take care of:\n // The `MimeTypeArray` prototype has an enumerable `length` property,\n // but headful Chrome will still skip it when running `Object.getOwnPropertyNames(navigator.mimeTypes)`.\n // To strip it we need to make it first `configurable` and can then overlay a Proxy with an `ownKeys` trap.\n length: {\n value: magicArray.length,\n writable: false,\n enumerable: false,\n configurable: true // Important to be able to use the ownKeys trap in a Proxy to strip `length`\n }\n })\n\n // Generate our functional function mocks :-)\n const functionMocks = fns.generateFunctionMocks(utils)(\n proto,\n itemMainProp,\n magicArray\n )\n\n // We need to overlay our custom object with a JS Proxy\n const magicArrayObjProxy = new Proxy(magicArrayObj, {\n get(target, key = '') {\n // Redirect function calls to our custom proxied versions mocking the vanilla behavior\n if (key === 'item') {\n return functionMocks.item\n }\n if (key === 'namedItem') {\n return functionMocks.namedItem\n }\n if (proto === PluginArray.prototype && key === 'refresh') {\n return functionMocks.refresh\n }\n // Everything else can pass through as normal\n return utils.cache.Reflect.get(...arguments)\n },\n ownKeys(target) {\n // There are a couple of quirks where the original property demonstrates \"magical\" behavior that makes no sense\n // This can be witnessed when calling `Object.getOwnPropertyNames(navigator.mimeTypes)` and the absense of `length`\n // My guess is that it has to do with the recent change of not allowing data enumeration and this being implemented weirdly\n // For that reason we just completely fake the available property names based on our data to match what regular Chrome is doing\n // Specific issues when not patching this: `length` property is available, direct `types` props (e.g. `obj['application/pdf']`) are missing\n const keys = []\n const typeProps = magicArray.map(mt => mt[itemMainProp])\n typeProps.forEach((_, i) => keys.push(`${i}`))\n typeProps.forEach(propName => keys.push(propName))\n return keys\n },\n getOwnPropertyDescriptor(target, prop) {\n if (prop === 'length') {\n return undefined\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n }\n })\n\n return magicArrayObjProxy\n }",generateFunctionMocks:"utils => (\n proto,\n itemMainProp,\n dataArray\n) => ({\n /** Returns the MimeType object with the specified index. */\n item: utils.createProxy(proto.item, {\n apply(target, ctx, args) {\n if (!args.length) {\n throw new TypeError(\n `Failed to execute 'item' on '${\n proto[Symbol.toStringTag]\n }': 1 argument required, but only 0 present.`\n )\n }\n // Special behavior alert:\n // - Vanilla tries to cast strings to Numbers (only integers!) and use them as property index lookup\n // - If anything else than an integer (including as string) is provided it will return the first entry\n const isInteger = args[0] && Number.isInteger(Number(args[0])) // Cast potential string to number first, then check for integer\n // Note: Vanilla never returns `undefined`\n return (isInteger ? dataArray[Number(args[0])] : dataArray[0]) || null\n }\n }),\n /** Returns the MimeType object with the specified name. */\n namedItem: utils.createProxy(proto.namedItem, {\n apply(target, ctx, args) {\n if (!args.length) {\n throw new TypeError(\n `Failed to execute 'namedItem' on '${\n proto[Symbol.toStringTag]\n }': 1 argument required, but only 0 present.`\n )\n }\n return dataArray.find(mt => mt[itemMainProp] === args[0]) || null // Not `undefined`!\n }\n }),\n /** Does nothing and shall return nothing */\n refresh: proto.refresh\n ? utils.createProxy(proto.refresh, {\n apply(target, ctx, args) {\n return undefined\n }\n })\n : undefined\n})"},data:{mimeTypes:[{type:"application/pdf",suffixes:"pdf",description:"",__pluginName:"Chrome PDF Viewer"},{type:"application/x-google-chrome-pdf",suffixes:"pdf",description:"Portable Document Format",__pluginName:"Chrome PDF Plugin"},{type:"application/x-nacl",suffixes:"",description:"Native Client Executable",__pluginName:"Native Client"},{type:"application/x-pnacl",suffixes:"",description:"Portable Native Client Executable",__pluginName:"Native Client"}],plugins:[{name:"Chrome PDF Plugin",filename:"internal-pdf-viewer",description:"Portable Document Format",__mimeTypes:["application/x-google-chrome-pdf"]},{name:"Chrome PDF Viewer",filename:"mhjfbmdgcfjbbpaeojofohoefgiehjai",description:"",__mimeTypes:["application/pdf"]},{name:"Native Client",filename:"internal-nacl-plugin",description:"",__mimeTypes:["application/x-nacl","application/x-pnacl"]}]}}]}),!1===navigator.webdriver||void 0===navigator.webdriver||delete Object.getPrototypeOf(navigator).webdriver,(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, opts) => {\n const getParameterProxyHandler = {\n apply: function(target, ctx, args) {\n const param = (args || [])[0]\n const result = utils.cache.Reflect.apply(target, ctx, args)\n // UNMASKED_VENDOR_WEBGL\n if (param === 37445) {\n return opts.vendor || 'Intel Inc.' // default in headless: Google Inc.\n }\n // UNMASKED_RENDERER_WEBGL\n if (param === 37446) {\n return opts.renderer || 'Intel Iris OpenGL Engine' // default in headless: Google SwiftShader\n }\n return result\n }\n }\n\n // There's more than one WebGL rendering context\n // https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext#Browser_compatibility\n // To find out the original values here: Object.getOwnPropertyDescriptors(WebGLRenderingContext.prototype.getParameter)\n const addProxy = (obj, propName) => {\n utils.replaceWithProxy(obj, propName, getParameterProxyHandler)\n }\n // For whatever weird reason loops don't play nice with Object.defineProperty, here's the next best thing:\n addProxy(WebGLRenderingContext.prototype, 'getParameter')\n addProxy(WebGL2RenderingContext.prototype, 'getParameter')\n }",_args:[{}]}),(()=>{try{if(window.outerWidth&&window.outerHeight)return;const n=85;window.outerWidth=window.innerWidth,window.outerHeight=window.innerHeight+n}catch(n){}})(),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, opts) => {\n try {\n // Adds a contentWindow proxy to the provided iframe element\n const addContentWindowProxy = iframe => {\n const contentWindowProxy = {\n get(target, key) {\n // Now to the interesting part:\n // We actually make this thing behave like a regular iframe window,\n // by intercepting calls to e.g. `.self` and redirect it to the correct thing. :)\n // That makes it possible for these assertions to be correct:\n // iframe.contentWindow.self === window.top // must be false\n if (key === 'self') {\n return this\n }\n // iframe.contentWindow.frameElement === iframe // must be true\n if (key === 'frameElement') {\n return iframe\n }\n // Intercept iframe.contentWindow[0] to hide the property 0 added by the proxy.\n if (key === '0') {\n return undefined\n }\n return Reflect.get(target, key)\n }\n }\n\n if (!iframe.contentWindow) {\n const proxy = new Proxy(window, contentWindowProxy)\n Object.defineProperty(iframe, 'contentWindow', {\n get() {\n return proxy\n },\n set(newValue) {\n return newValue // contentWindow is immutable\n },\n enumerable: true,\n configurable: false\n })\n }\n }\n\n // Handles iframe element creation, augments `srcdoc` property so we can intercept further\n const handleIframeCreation = (target, thisArg, args) => {\n const iframe = target.apply(thisArg, args)\n\n // We need to keep the originals around\n const _iframe = iframe\n const _srcdoc = _iframe.srcdoc\n\n // Add hook for the srcdoc property\n // We need to be very surgical here to not break other iframes by accident\n Object.defineProperty(iframe, 'srcdoc', {\n configurable: true, // Important, so we can reset this later\n get: function() {\n return _srcdoc\n },\n set: function(newValue) {\n addContentWindowProxy(this)\n // Reset property, the hook is only needed once\n Object.defineProperty(iframe, 'srcdoc', {\n configurable: false,\n writable: false,\n value: _srcdoc\n })\n _iframe.srcdoc = newValue\n }\n })\n return iframe\n }\n\n // Adds a hook to intercept iframe creation events\n const addIframeCreationSniffer = () => {\n /* global document */\n const createElementHandler = {\n // Make toString() native\n get(target, key) {\n return Reflect.get(target, key)\n },\n apply: function(target, thisArg, args) {\n const isIframe =\n args && args.length && `${args[0]}`.toLowerCase() === 'iframe'\n if (!isIframe) {\n // Everything as usual\n return target.apply(thisArg, args)\n } else {\n return handleIframeCreation(target, thisArg, args)\n }\n }\n }\n // All this just due to iframes with srcdoc bug\n utils.replaceWithProxy(\n document,\n 'createElement',\n createElementHandler\n )\n }\n\n // Let's go\n addIframeCreationSniffer()\n } catch (err) {\n // console.warn(err)\n }\n }",_args:[]}); \ No newline at end of file diff --git a/w_token.py b/w_token.py new file mode 100644 index 0000000..0ac6f9f --- /dev/null +++ b/w_token.py @@ -0,0 +1,85 @@ +from selenium import webdriver +from selenium_stealth import stealth +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.chrome.service import Service as ChromeService +import json + +# 读取配置 +f = open('config.json', 'r') +content = f.read() +f.close() +data = json.loads(content) +executablePath = data["executable_path"] + + +# 获取token +def get_token(email, password, proxy_ip, proxy_port): + # 设置代理 + # proxy = Proxy() + # proxy.proxy_type = ProxyType.MANUAL + # proxy.http_proxy = f"{proxy_ip}:{proxy_port}" + # proxy.ssl_proxy = f"{proxy_ip}:{proxy_port}" + + # 浏览器配置 + options = webdriver.ChromeOptions() + # options.add_argument('--proxy-server=http://{}:{}'.format(proxy_ip, proxy_port)) + options.add_experimental_option("detach", True) + options.add_experimental_option('useAutomationExtension', False) + options.add_experimental_option("excludeSwitches", ['enable-automation']) + options.add_argument('--start-maximized') + options.add_argument('disable-infobars') + options.add_argument('--headless') + options.add_argument('--no-sandbox') + options.add_argument('--disable-gpu') + options.add_argument('--disable-dev-shm-usage') + + # service + service = ChromeService(executable_path=executablePath) + + driver = webdriver.Chrome(service=service, options=options) + + stealth( + driver, + user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + languages=["en-US", "en"], + vendor="Google Inc.", + platform="Win32", + webgl_vendor="Intel Inc.", + renderer="Intel Iris OpenGL Engine", + fix_hairline=True, + ) + + # with open('stealth.min.js', 'r') as f: + # js = f.read() + # # 调用函数在页面加载前执行脚本 + # driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': js}) + + try: + driver.get( + "https://account.weverse.io/zh-CN/login/redirect?client_id=weverse&redirect_uri=https%3A%2F%2Fweverse.io%2FloginResult%3Ftopath%3D%252F") + + element = WebDriverWait(driver, 20).until( + EC.presence_of_element_located((By.NAME, 'email')) + ) + driver.find_element(By.NAME, value="email").send_keys(email) + driver.find_element(By.NAME, value="password").send_keys(password) + driver.find_element(By.XPATH, value='//button[@type="submit"]').click() + + btn = WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.CLASS_NAME, "body")) + ) + cookies = driver.get_cookies() + access_token_value = None + # 遍历列表,找到 name 为 'we2_access_token' 的字典 + for cookie in cookies: + if cookie['name'] == 'we2_access_token': + access_token_value = cookie['value'] + break # 找到后退出循环 + + return access_token_value + except Exception as e: + return None + finally: + driver.quit()