From 9441d0a846aa91ef5873313d966dfb6d67de7524 Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Fri, 27 Dec 2024 18:00:15 +0000 Subject: [PATCH] Use Assets and Resources based on platform. Assets uncompressed on Android. Assuming that the AAR file will compress. Use Resources, compressed on JVM. --- okhttp/build.gradle.kts | 55 ++++++--- .../assets/PublicSuffixDatabase.list | Bin 0 -> 132737 bytes .../internal/platform/Android10Platform.kt | 5 +- .../internal/platform/AndroidPlatform.kt | 5 +- .../internal/platform/ContextAwarePlatform.kt | 7 ++ .../internal/platform/PlatformRegistry.kt | 7 ++ .../publicsuffix/AssetPublicSuffixList.kt | 36 ++++++ .../publicsuffix/PublicSuffixList.android.kt | 18 +++ .../okhttp3/test/BaseJavaTest.android.kt | 31 +++++ .../publicsuffix/BasePublicSuffixList.kt} | 52 ++++---- .../publicsuffix/PublicSuffixDatabase.kt | 4 +- .../internal/publicsuffix/PublicSuffixList.kt | 2 + .../publicsuffix/ResourcePublicSuffixList.kt | 35 ++++++ .../publicsuffix/EmbeddedPublicSuffixList.kt | 54 --------- .../ConfiguredPublicSuffixDatabaseTest.kt | 110 +++++++++++++++++ .../ConfiguredPublicSuffixList.kt | 30 +++++ .../publicsuffix/PublicSuffixDatabaseTest.kt | 114 +++--------------- .../kotlin/okhttp3/test/BaseJavaTest.kt | 18 +++ .../publicsuffix/PublicSuffixList.jvm.kt | 18 +++ .../publicsuffix/PublicSuffixDatabase.gz | Bin .../kotlin/okhttp3/test/BaseJavaTest.kt | 18 +++ 21 files changed, 423 insertions(+), 196 deletions(-) create mode 100644 okhttp/src/androidMain/assets/PublicSuffixDatabase.list create mode 100644 okhttp/src/androidMain/kotlin/okhttp3/internal/platform/ContextAwarePlatform.kt create mode 100644 okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/AssetPublicSuffixList.kt create mode 100644 okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.android.kt create mode 100644 okhttp/src/androidUnitTest/kotlin/okhttp3/test/BaseJavaTest.android.kt rename okhttp/src/{jvmTest/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt => commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/BasePublicSuffixList.kt} (74%) create mode 100644 okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt delete mode 100644 okhttp/src/commonJvmAndroid/kotlinTemplates/okhttp3/internal/publicsuffix/EmbeddedPublicSuffixList.kt create mode 100644 okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixDatabaseTest.kt create mode 100644 okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixList.kt rename okhttp/src/{jvmTest => commonTest}/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt (68%) create mode 100644 okhttp/src/commonTest/kotlin/okhttp3/test/BaseJavaTest.kt create mode 100644 okhttp/src/jvmMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.jvm.kt rename okhttp/src/{jvmTest => jvmMain}/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz (100%) create mode 100644 okhttp/src/jvmTest/kotlin/okhttp3/test/BaseJavaTest.kt diff --git a/okhttp/build.gradle.kts b/okhttp/build.gradle.kts index d3dbdb38026c..30ee556a21e2 100644 --- a/okhttp/build.gradle.kts +++ b/okhttp/build.gradle.kts @@ -3,10 +3,8 @@ import aQute.bnd.gradle.BundleTaskExtension import com.vanniktech.maven.publish.JavadocJar import com.vanniktech.maven.publish.KotlinMultiplatform -import org.gradle.kotlin.dsl.compileOnly import org.jetbrains.kotlin.gradle.dsl.JvmTarget import ru.vyarus.gradle.plugin.animalsniffer.AnimalSnifferExtension -import java.util.Base64 plugins { kotlin("multiplatform") @@ -20,30 +18,17 @@ plugins { val platform = System.getProperty("okhttp.platform", "jdk9") val testJavaVersion = System.getProperty("test.java.version", "21").toInt() -fun ByteArray.toByteStringExpression(): String { - return "\"${Base64.getEncoder().encodeToString(this@toByteStringExpression)}\".decodeBase64()!!" -} - val copyKotlinTemplates = tasks.register("copyKotlinTemplates") { val kotlinTemplatesOutput = layout.buildDirectory.dir("generated/sources/kotlinTemplates") from("src/commonJvmAndroid/kotlinTemplates") into(kotlinTemplatesOutput) - // Tag as an input to regenerate after an update - inputs.file("src/jvmTest/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz") - filteringCharset = Charsets.UTF_8.toString() - val databaseGz = project.file("src/jvmTest/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz") - val listBytes = databaseGz.readBytes().toByteStringExpression() - expand( // Build & use okhttp3/internal/-InternalVersion.kt "projectVersion" to project.version, - - // Build okhttp3/internal/publicsuffix/EmbeddedPublicSuffixList.kt - "publicSuffixListBytes" to listBytes ) } @@ -90,6 +75,19 @@ kotlin { } } + commonTest { + dependencies { + implementation(projects.okhttpTestingSupport) + implementation(libs.assertk) + implementation(libs.kotlin.test.annotations) + implementation(libs.kotlin.test.common) + implementation(libs.kotlin.test.junit) + implementation(libs.junit) + implementation(libs.junit.jupiter.api) + implementation(libs.junit.jupiter.params) + } + } + androidMain { dependsOn(commonJvmAndroid) dependencies { @@ -158,6 +156,20 @@ kotlin { } } } + + val androidUnitTest by getting { + dependencies { + implementation(libs.assertk) + implementation(libs.kotlin.test.annotations) + implementation(libs.kotlin.test.common) + implementation(libs.androidx.junit) + + implementation(libs.junit.jupiter.engine) + implementation(libs.junit.vintage.engine) + + implementation(libs.robolectric) + } + } } } @@ -184,6 +196,19 @@ android { consumerProguardFiles("okhttp3.pro") } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } + + sourceSets { + named("main") { + manifest.srcFile("src/androidMain/AndroidManifest.xml") + assets.srcDir("src/androidMain/assets") + } + } } // Hack to make BundleTaskExtension pass briefly diff --git a/okhttp/src/androidMain/assets/PublicSuffixDatabase.list b/okhttp/src/androidMain/assets/PublicSuffixDatabase.list new file mode 100644 index 0000000000000000000000000000000000000000..e9ef95722533ff8ca14896d46d4f2812c16db618 GIT binary patch literal 132737 zcmb5XOOEThwyv4Dg{(zK60ot?G;Gu_3@aZ)#la={dxH^0I#--p}$`Ci(i&ibKbW7%d$FF zuYFg&3^{+hu7_n;Utaq2L9d(^bv0bRdgHX{`txP~-^upt=ie_&`|Yc2-?rqG8vEtP zT*~)VpR)aAY2R1fAN~FF7QSri+j3oL3|@xnbUI(Vu0H2sdcB_Ob>Cg8M!=>g+iIhq zdRJc#`qaa8Pfvah zo<0YJD9p{gGwbubWhx&2r63Wk`9vsV>#38glIb=5)zoa6g4K3~1{%ZWa{X$IFn zmfPz^>+m=%D~&r4FyYX2+dcyrr{>6{9Kh1M`dA$_Zbru2=3Fyfmg_xlZZ$~T^L04f znIwwOOWrZnUMfA)1lsq*rQW3RSEA{5%j5mI>3U{-${<*O+ovhnY?i0%ibqZR6C>Mn zj}>^|&^HpluWnn|YbCf>2xovTaJcL|jo z)epzM?}jzIZXn*{9R%9lM%0$mQ6ZtRuG;nYD*8b6UsW`E%~W7{PAeW1vRrBPdBJSS za!6y`slSa(-eZ=2efkLD^lQ53gWTPsTKDHJYTkE?!*9bFKU1l_HVL6{eX(1dn?5~0 zSL?R+6Yx&%`rgo8fBT6CSIzPMQc+!PSN%(GbSJ{(RNY_p&ACkjdfEw=$eUrGw~W)d zxv>tG=laB)Ps=C)h3A$-*T2whhdOoJpV#J8w{@()m@BM4YJckUF2U}YG7t29bxT7! zRNs+3+LHToA7eVK_e(c#sJl&-*2hqvZ;jD$3(7t(N+kYR)8WK?KC@Srt5_RMqhU02%5DA?hZD~cTpU0yiOh^?=tVE`<`eFBU@sEEj_gBK-{!`2H*XD=5 zsDKYD;CoOeAH4sY-v8~_`1o(vOVc)&CJ}-hF+OksGu=ZE?Ksr>(`pa1Ef-L+a@wHH=O zR!c@;v)pnHZSSUMJZtzF+8OlML>Os$R~6eRzm@(}fWuqAIS6uIL4(wh<9vFmSdxGt z%Gre)=&Qq_YBomh)oR6qRe!lCxHUDwT7RzIs)pq1p^3c2s#SAfQ`$>G#?<5cBjX$*6mCe< z!$lH-5i3e3&8CMOx^P}eAlkBFkBi^sUXhqL1V^g6x$kPoT8&+bYF^W~b#!V?$JWp1 zCKg(KjFS`RS?2ss+0?uIERQ#bD_3U(uiGo9)|_c`W;>aZ5MLMV2vvRQ82>H*M`FHi zK^4uKqjN_S+k;VAwcR#dbGf%H<@$VA4c%?q=l;AgCfKqHw&zBez`=6Gw2PQA3atT$ z(F;3pOQSgw%Y0X{s+ox%=-C6Nl(=cMQfI%*a4n|;hZe0&on1ITx|zGP7Z*p4vvz`N z2Qqrr+tg~QX->pvou~#qrz-9gIv2=u?lGgQ@NgrlP)r8YFb(Fu@apeA)Ho3C`sdap^NIo|Z3&wIa%$=aNjHRIgCu)Lmc zb<_ITlNt+@Y0s#v7b3LIeLFr_U732#dCgwF0jzo=r5njkUGV+Obw z%FfXs&zt7#X_HHY>{W(Ti~OO14yvZs5Bq+}w!oOXePDozkguB8>#FJ?akke32i_(~ zErE|-w2!c%y7ce!zOaA9^q3d(9DCpa3iXLBtLAY#IaHf2cz8VCHLB;aqP40iI~YUM zA1ZAh3399&EqchST`X~Z7aS#=;Ap+saVCD3L*OFUe)B<|J&R~8r)Qov-3PhiL6P&d z{-`jZIS*|rX4GNBLW2Ww==1bEG$5_Mz>tR~24cdQnlMY=O6zrs9BP+dZuf_-Z?FA< ztXeH>=hJLHoNI{bE*@O&*A)~jhfXHh;Yz170)2d0-OtQwnSg-^TaFNcIa{yXcA59l z)}^%`;kJT_zG2YyWpPDBDT}v15I?h#3HOkMi4s|MRl;0t13Pi}<=0j(gZQE`>XaRu*>UW+qmdR{ zNFqR()6*g);hs-Z{|I_ApK2PrBV#mxx~|9S*s}&TL`0cLvr#j9m?x`iiK$@avMY4; z4=8|vrI^xN-d8^!>mU4(;uqYys?Lc=MpB!}v1N(TYkWAuQ`>Cs`Cw2TVdkATdK<0` zBivQ(UFZHOw#e*1q%j@)-Y9FCakIx4KhDm{q%mNg@ zYqn+=SKXgi5mQ1}v?vZioQ}Zx(`qIin0CVP&^u+{_Tb$YxR^IflnKBNsZ$-%;j&>1i@of` z&S9pk&pW5nf^!*6O*0qCe2S7z9Kx5|dILY2qrQX#vH9>^ncT6Z7yj z1a=f$cTh0J?sz)syv}daO__$pFD!<%?TRLiqzNH$$+xRv1^Y&urIIbwX7mF*Xtvdo zU%_*MO1@)$FSDyD&ft}sK+~!^S4S9$yxY&W&a>qNFydh}!It9q1_WY7zZZI+Q;$w2Y-_Q< zpE>@V55`gI@)4T39AGE7_K3(*Jv2o`6_2#*8Hmpu4^Wov^p=icyShz8*_pYOSS{xx z+w>WXDkOOp590i%C(fCkuDAY`yJHk#)LEz^n;_Q_fV$BMMOWx95;X8z3kZF_P z;Kspt-quE6mJC)CVK_9$6iNH%aJcnt%-G?Ox3~d55HvnP%RC?QiGFxk62q`Ou*@OW z*`nuPg*G3O5DH3hP)Q)VffB^5Q>ZDYFdrBc7jr}5PJ>OT`KU0y0@DNrpwe9m#nd9b zZlLfr)gn5vu?EiIUX}1hVqC70l#LrT#a|!}y3GQv7)V=K1~%0Z(E@45({bkF*TEVO z80Es;rh%6|P}Rr+Zzw$eFG{Atb^<@|N7&%Qd-Dl-lISPrbpQRMe&hWF>1kBXUceO{e8 z4Hbu;kIKqa)OR_)`qD%peKvGz{FLkG%0kHVX+KS6A=vpi*Ib+H(>z~}J*%ozp!m3u zBG0D{Baa7dRK9vQ6y*43D8?LLedXKcIK#IkeA@SO#hH&gWUh7cX`XMITPPoVT*PPlLu!Adj+2TciRIyVC($pDW2X|PgK)V zhGGG6=ve76iD*D$B5lgV@>YC9NFQAPh*_-XXwaLt{tD%(jT14@OZ8ly8Bw|lMas}! zA--#SDdHd!Y9U70Qv%m52`Nls9^Hc+g?*Gc;diO@&9*K! z^;gq*ul0FVHP4*)#Vveoj&zE4!k`PqET+{3Ehm93`S@MvJmjs|sbjxtko}B+i7~6k z+r%_goUwt4R)vHV{Ms z?wW2N(M`44JbR~JRr_^yyY@(cv|%ebPjhH6sYmB;t~`IAtA7%FOHJ=xsj0EFdRjw`G;fOj8xYHme9n71aKfH14?IT#Sk*(VK6z?R`)dr zwHzN5K{V-4F{S!m1AN}0XzWKO9RV=Tw`;e%K!ACGN|w`tDkOe2In9eQFKGtm(7Nci z3;69XZJd`-o7AUtn*I36aQEayRYMwg%Bu)c!W^|AG{ERE5C;Wl=f2=wWZeOg z%4Uw{2;%H`2t>1k&UHr>^ERQi}{&^gbY@-T`42YB8uK)}2aG zuu(2?xJuJ3e+(9hvq+AeI2TSwCBR@}qRb(h#+09OOsz?PT!SlIZm;`FifA5xl*ja4 z@LIi&Fl8R3!l)HK?2*54%0>n}CA_ExSl9>xsH3n-HK3CM@=ge2q>>T&N_I1z>qwUi z;EKpWJ$0|o3>CeI?!{^~Xt!9csM_krG(f{azw|p=4=WCm^ql_ZlL2zz9r|s(q$R40 zcB%GOQFFI4l5c+%=`{aqDx>Vz3wW&Fyh_8BM%VQzh18;MU@SyAD0m6bvLsF~iXi9~ z9%VjDLZz-m9xN4toVdV$6!5}{L#wEU!L#g>oC*~>OIs8oJBats8T-_%s~hrYjg#YV ze~$@G>zdQ;hN-9eathJU>Z*?^j!;$gGUJ1QiL|)DJ6T>>D%&S*0K2jCEb?CMpQM0x zVe;=^-6&##3L13JUz++gP(Gk(-3Svx z)oXh9%(ex_(9NAf-?Ybyqa??d`7=1uf1Gj;n??c+ofScmt^Js4kf|MT}nH zhwf$PK|wioAH}bIaJ=>4w7>S&Ls88O+U8se8?ICs9&zG zYYvZ|qK(GHh#!>@)Iy};;~-L62>?+aP=NZK0*x#IdOiwv>bY0x_c&likUD78UZu37 z0IdrL%vGhLFgN>EIy(Y(8opQQ>o|xq(c4i9Ntgn3a~uQ^H7TX8EJy;)X@VE#6agAK z1k(SW7<+IDSI+bBY{2ujpJ(rCW46^&_TUgaMRfU39EqS<0T{5^O3ijBQ4< z6Jpb%{W8VrE@d)23UXW|RE7&tjqy~d@~dAmT-a@l)0JbKMLEWcZ?Okxx{QxN9n69< zInS(#Upz(fQYN*X6i<=#7RjPj^p&y7l$SKSLYdZjn58{J(L;J4Ui0j^CU}`2Ws-Ti z=rO$y-)r{#IO_&BwTJw|*Jb%akYk$FF~*B75n++xT6sB+tbU3Y<%-zIdGVpo~1TVgIEat_rsM`_xGM6d5kmKmePVr)_ zPDP#3*&XxzSxgquGr1g*L1VmVm#Byg*DgNBi*Xx@b`3?HVbG8HFGag9ptoEOx`Sg} zxJmFkOE|6b{;0hc@KxWwN+sT+C*rW})zQrNH*Zbh>8X+8M33`t!3brJF z)twM=vF!ox&@iVnXm@Pn9QRN=%dA6yQo%na8409{2#>xBH43eoUUDD3jpQ{V_5RHE zBn;MXRq`P)W8ZGt`>y8^gf+$-2|x9mW7tuf8s$p{5f1$=G$V<^Y>fT2N1+3?GeEEC zEG}ls8VP7BL|CyuhD>@TLAAQ3*Leg(0Hh(4SZLL&&Q`Y|V6^!0&PtfbPmZVpAKBxL zn|q8Y0KlYHc4!H@Q)dwLE7zEEq)g~I|EW>JoE4Fp$FFD7_6Xb589%nj(Y%wgrMPx? zb_66(kzf;=AJqDQl;^Yn&5mgTxdX6GS)-xk&!)K0LW;T>j7zGQC2`o6Y-$7{Ksg1O zL_M1(hReX4l8|#48H`!OL814-U^Z`eU29+6r{h?kUgNtvH(03K2 zL+QEiy0oiCG;0r$3q2C&et}LOs%?F_djg7f;RJw|QIgY<8U{!&z;`q%t@1<^;izUL z%$cssyLC>CU*V-VL<~U-A|;_88q|--h&3-S&1KKo zJybbYS0sJ#77C z@PG6C_P2-o?eFq{_V%xQRy0~FFdFF@N_+cvLKx_&@18iaZMuK{)3g(+-u2V^k3X~! zSiCdt^@rLE=yxYM88Nm<{a*BoZUGW@$Os!u0pRSoM*H9V8AaF=*T};8YwN`k%e&D2 zUNiXtZl8nVTXS6GROgkphNpzaT~ffoM2LJQJ_%6Mk7X*$Ar!`-?zl7?PIV|h-_}>=n-j{sV5M-=?C50&MY@*F{dThj(1OxxuEJ} zjcjWMnnU0%3h!VSb9M=^mEf30944s5h%OH^NA(1nMX)F)G!A5QKgAp-4oc=1zOD#- zVz&x5C1Nbd_%g*dv92gRPD}72Yea3za$=dOha3vG5sgg(P811@3hCtI{jx_lnDh65 zXkEBgPmr!FWT$}x)o`vK(0z=`2k-&5(G+l_&Nb*xaj>02MDJ;0oYA*N^O0^y-DZAfpzsm?blG+@@UQBV$JCtN@@)uvSw#_TJzc({Z}ssBGxt) z#M&W>SQ|kRv#W`uwL=7c5^W}ONs$f47ltsKBC^c|BBBq-?wTU#GX#WIr^qHp@>_6K z;?W^j10(2wKodj+32=(!*P#RwB!2?U+yu#W#x6TSa^<^RdG_FV#4eU1m~gsX-E)o{ za|F$#c$6#F=ge?A;t|q=h@5g&PZ5JNL0ph;DBPKeu34_BJIRj&yW83&xPa)>4QpvJY_2AWnLTEX--4KQKdS|7uGe5 zLMj@$!~o?X+_MS-{X@gDbUP6lMu^ zj>H)68f)UkgRa>(Osbr?;oM+M^`z2UoN=ODOPt0y$~@Onzl_1FL-$1d-cZpl1!h3^ z$laj3tdum`)d7E&F@q#zJh1{0u)`G;UQka4u_?U=9gt`6E)vlZWvmT}(AnMJq^2hYoUy+Paxn zbR3@$nc~_-NTWeDQgDVwhc-_5M2FYAMFne!QK7L0F9q!UM9w%-AkazBzuR-o#%z2> z6FH(S;jye4ppBM0R=oaU1NZXg$Fu~8_ZH?riOkrCSf#uZ)T!uTx{HIt^4w6p7F#$| z7>K$LwjBg?K1hO(4j4yplE`X;jN@}tisN9BLb;RHLy16%>X(6`*g!%^YcKQ0=#L#PIy zz@6v*2ZBLSjQRpc3xxkUYG(ybNb=8lR7J(p1TaR`i}XfnStK~ShO?c>?oG4U0Q5?+ zkvhqU#^Kyw+`_|%8js(2ZnoPnYIY791LdfZq_Co8iXsZgV3BkwhsPr_d-!t{nd6v+ zGfB#g3^Ye|4oOgpKXU^9Z;pzsmE$LkdlW9o<`{n&qoPKX!(8$4_-@c0DXrM;sXJY_ zY}{!xPq=gnIkh~k88)gm`G>;vKQx`t+0dx^oRJ1fh zFs9#%yRFy<6Gz8Dze&?YQFoYdocWphbw;gKOZNOLi!()BNo1+SHRbsAmoXD34#!2m zt~SQv#D$zN-|M64n2rnP5xKZ{gj0ezuSTD9g6pkgb(|Ua^;6`PKyI!q5)a}Cuk@=g z!}aBNec<@Y{wvU!GFtw52 zYyq(Dw_AiD=+Gr|8g#8=>R|zZNi|7@ThPAOu9>?6tMQ0g#GPybwrf>GZ{R0#=@UV!`RAU=y8zf(~rstZcF+X$l3?pRV$31p_qf;SikQBQX# z28hwVUDV8L3!r8ufz}B@dLatiMLj(Uk4r>8%Ce6a5c)V3IlUBZ*eIYEBf+1}g4wr# zho~-sTc@IehxqIvy5JC9aER6-Wl+vG2FL4_R8*pkucOB9Eb*R~?s19uN5Esuf@6GL zB!qxbT`zA^@w%5eDfSj+iNd_zVT;5BGfpHGl}DDWoPD$bBMhaG965*=w8sb-bY7FhuW)Un5|A4?&VsQJAp| z&*HN~w0(%L8@C*nMlJ;L9x9G{9nqqLcu(6KKqDQ3_$<6(17qOu!lRTi4?*;q_-g`2 zi$ukcx<}=Wk&c`iQSSl_!yZb`olDf@qJhK~Y}jdu#3KVtf?yICm>(`<=laM*OXbO9 zqT4Wd0UL6;9GQJXUNfBhZGnJ6WN!UcFk?mW_`vT3Pa|M9I zwOUAM)I^Alh11?1Nn>l_wC6l&PkO?Wx{A;{k(@C?io>cgqElzP?PpY=GzVcTpdI7= z6&o5*IhY zU*y1jteF#>0M&s6+RU+)MvX<`v4%yZkD@foFJGb`vBUEtyvNlWSyRdvthPdy?oRIXG`uu0I5?mna5a2JI)oW^AIakT zQ5X~bK)EBNhKj`ky7xR_NKr0IB(!Bq>sRD58;hlg(jG81Qt=%>yPMpJS-`nL;6epZ z*X6Hp5fq|L zj38J8$JA6HB_D+>!e|5tL>0&*pJW?aphZ%s*hzF>@$xx7^%8K_8)}1SNWo!8s<5e? zL~vK6hXzqlJiU|S4j*rC2Gj-}b{SU}Jgea0Z`RNSo6SP!OlHl7P=|3>MljHXU?Tut zMX+84#VR-W7D`B_AGIbi78dwzg9JvUr&kq#j!C8|MeGB9Xb2ZJHB_m7*ohRVr0UXH zI~htDo=Q}%MqZ(*hHY_#SbU)h09R~NZ(zk}-0H1XJpsH3hATi3cZ=&C&Et6sqX$$( z1iwt6Vj`-8bdn_&ls339nIMk<#K)Q!HTxRB?5vC_M;Y-ey1Zpf$wNQM*}c^(uOYSYlH=O@?@ zo5Q$XQQQH?YNYJ3Ovlen3oE{@QMVPCHkiADp(UFlQr~lb8_b{F;En<=5y86$^aJQ; z+RK$<>B@yltnm)R+R&)s5w2|zTDn_v!izX3+!@`l>EZLIT#lzqj;A~bbd2ecw#dPl zP*pe3k8Fhr6KDL!Xh5_k1gRLy8>&X81Ad^S_g~JR8~pF;2MUz{UVYNhQ5<~m17>ej ztVp{;Xrod)WTLKik9#KUE;f))m(+!9SsjYh+Q5jSwtY(RG?RyXRDY!2 z=|d3@xSfl}_r>;}F~B$IVr}}Hq=jnbOV^@`^t3sNtk_t&nqLk-8(ar~37iXBb0?eI zl(;YSS#|Wex@-H0DkzcRECjJ-k<_PWa=DFR(2A{F-#sJag3LI>@)bf+sCk9@QO+^M zR1(v4lj2%1IVwAj&2VIbr7xtoyD7!p8H`gnF4>?QzrouV@1duyn)>;b4q)zzT&H8M z*m*H9SF~c9R4_{VPsr)?CyjxaF1Pboz};KJy+hGKuFBjmq?*&Ozvnpk9;4*w2_D@} zITs*&sHRS1pHpW>&yvt|#tay5skXvUf79G);pBvyoD*&n36`BlDXMD#dU?#_>1$F+ zNcwmb419t8xIvyeBS=PWx$es4Q&^E@A}ivR$09P;il;1yL_S3th8WgbW%+m-NL?Q} zbYx+j7GEq$y~r~XS}EBeWGr5IXo48N>P+_qJEVPhYaS*L@H`62lKW8c)W3>qKE(^1 z>m&9{8gZVcudAy0CCDD_WB2a%#~8~~AsI_NQc7YVw{dZ6J*QlRrgk~(I z`jAD_XhhIN?b`N@9Bm_BA%F-5y zI6$I}7jy`cslf4opmAck!3TYmhC=YsoKj#c2n^@KOcMwu2`^9ZETk)t<+3IVYnc9! zDcqZ(KdIO|Fa%mIq<4V8TNubKthC2|28549?v7g?e9V{oeTw18-1wJ5tf<2;{OWqc zUdS&7u}OraI3AOfaS6l^1)X-cUX1Zn|6%E^=<1*g}+DgtJRfNC)T-KXFfK^H+3re4;w zAp$jxRFvrs!*gT2pt0Z?yj=&k2-JgD$vqrI7ACY(8dwGD6#}NUg7}d8kW`#i^#G2p zg54&9cnOZKfzb{)x=uxX;OIIP4cJA^;piH8cK}CMDLA?gA`2%5r9c7>{)`}=!O9g7 zR<48iESx2$;ypOJPQh+*7##p-*QsbZj0~mV>^g{k-~{JX)RzO2Q_+q1rc=rjh#)=> zpVz=>^)WsVyVt;Y9d@r%Q3@nuU{DmaZ z13)aB$&=zr7tbYL84t=jaC68-eKF2|X!eKUsUTyVcB4n0^{;Cz0S5bdA6>N8Fbg4} z2u4F=;yN!N#y4E9PI5FmE~#T235^_c6aupzz@Hp0;VXTpvCCC6Ew+jp@3@XZ zw)Pg66=|^r>eiNnb;|)Lj8HlLA-AlLt0m$Nf~xr;t!!AxB;IckLfuR*0t_YLarq#L z7ih?y1*#(zw6jj{0hs~J1g_B?(CL`Na(y)4lmHxl#i5av*(N8$Gm*4%m)Ra1o+QEb z`&`|p-W=Z*IAvwSwO@#zC^dVt_%!R>6~#B%zWwmzoFqGz__{$N_vQV} z%%HT$_U%VMYVX5xpfKn9xw5{V3LiLY`MBdg@YwQc#-HhtN8c?U7xw7Dr4fu0`<{Q^aQlJolk_y$$KFZZ1zzha|!pZg~VHzW5C>I*vuJF@R__AKA$2>T)1 zm)QE#yxsyWu>4RDLQ0}J_<->g6f7|7KhMqqv^E2H1Y2Ke~(`Q(@Eca`a{E+jr z*)+@cH8TDv>qo^VOk8F!FzW|s_>-L94A)l(_@Ts~nkHYN-iPu&YPIn0N7=q_g-iQp zUVM#i%kO@TYaep{RL6XQWy|8eK(QZX`=(#ML9P!aeuY^dvi{82eTq}LK@$&Z(nLTO zCdNaDRZVhr4}${FG;;7KWLWNW8G_g)Qj=y(}3<- zt?N7moMP#*#g4k813PB&p?Eg;`%F*5p+pM}eLQKzJ1XB$MEM|I+n2a}bayAN)G#uU zhpejrdkd{4ev`%mY$D0nrkmmbNLo4v1y^Z+A3R(Z)uNS|F&DCjc(;H_W*^gld>E&n zDjNfNVgNzO!E&=}o#cSLD#cjI2v9kx>5~iYF43TvDLd5{UsETeJ52-h!_3zs%;QcE zTxq`S3C5dffp90l1B4p@9w5KJgG{`NkGX&o0sPtXj9xx_p4Q@*k3YH3fL0~E`N`YS z{fG}(mbz;>O$C_xnsVZ!UuxYi5K0sPMt9R$-~cPToaZDlVMkrE<91tlV)1Bl5vrsX zSJ;VoEnpvMoUcYrDy(t6*tX@}B4 zvHz1M1CaqMMM5M+VB`ohmNjt64MNs{tbd>_8dufSuh3jrr5>(reFcllW)WGe5|?_&LjC;h-3r8C$ML*|PN`|Kpx98OWr|$0FE-zQ~x6Ho=$>X^26X z{!|<~qQf0?;2l1hQKsKwy#{SSaP*Iyqmak~L@wRkYiCNK+%(uyO_%Ws$c?-UsV8`E zOKIpg9I7qU6FW8%)By61ME1gJOiLd|;- zk=Dev*42yZCNxhq25iO>h<>1yj~z^y)DV$dnW&{Zgx7Fx4CTFrY{P3;XcFRg%T1Il zGu%vX?Q(UyUmUN{(e$Q7!P~v($==k!c8@Zkrp+D?)&xu)4iRe9NPr|5RcqE9qU)h@)61) zm00pUrdV>~hW-5Vf{<89n{e+w~^- zF+$UXjF<{Cv&{?8;ThM)Vqc8fUtJZgwkYhH|Tu1v8dFt?(+q;Tbvzb zG5yxY_vCGONi(vwx_``j$Eiw-WiPio+QymCWA_w#6i$8LJFNms^xj_(QMlMi@TCP|Dfbii=-; zk|jl}u@mICx*l&fqz&a?jW; zs2RKr<^jRfXgjWP2jk%+4KF}S=O|dJ8IeX)G^e>ZDcsUT%TNfNC*S_-;rZKt%`#wd zEOdogoTsb8gi}y7U{g{za>+9TpkJ?OMX>6T7W1~xw;OHcf>wD!Nmf25ss`EoOlbJb zq0wr>@{)yeE}m_RbTW=k54rCC!-pfHvgQSN`j-X$=?ONuNdSy? zhpd)!j9ocJkJzqNIdR%!cE&1*{8EJV+(}6^Jkz7K9GImMLQ^@G1U7HyW?G*z4Y8go z2D}QfF42bMQJs?R7(bjpOFI@Bt?lf6CnvOTDUQGH3oA4~JKmGps~)Q2X@4YjY1s+A z^QI2RuZrdz`u?)`2^63OjYD(vP_@!QsjzJPspiTYyDfGKWBssG3sipu`yg9abAkOw zdHvx13y+ZZ-~Qm!OsIzn>LmQphZFo=_7cEWbVemorTI$ zl%FFW93#gwic$H=Zo%;6Rn>90Lt~l8qD;_POgr91`F6@vln+fa!Slpd{-V9$?lBKo zXNnhX$Bp^~XP?Y{(j{V1_3zT|=Xm%=as6?+Hs;6g+7vIwh^=dcCcU_)HKRvW2T`g4dlNk}+OEjx}+{;)P zcPdKvsI=+6A^|tFl6OHluKeLzXmIMeRXG(os%m(_auF$Sx@A$1&;8>#>uzo4%6Rvp za?vI#FvU_i0e)!IWJ0U_{_Mllg-E}4Sa$RJWm*p^NSi(8EYU-yt6|3H|o(MB;L&*gfrZ`rKhs0t(ty{MRv@tAZv| z!X4*8{x}KU9rpgk>JebHnY&H61r_`}wi^hg@&jKR^rpSZsmwH3J1HvS|0QZMibkml_0inznaLERDHo5JTWV!63HTx{=F{PzaG z6Vbn8^Pr_0{)@Z0W8I?GOd!YDjtPkMb--ze&s7|*iJ`%bhXjQ*ze+yJcBp3S3K^r_ zU5#9f8!&YvjvFDdAte&9c-6baID9%#QJlbON8KGj-g#}4>`mJ#!j8o$iCFx=!;0-& z5FKL`a_`jzIb?o-wTsH6<5hhE8UwD{)t8YhB|h3T?zT_Z?C)q6KNdI=Y@^HePdgYF zoM%<_hX1tN#*6qe+;i3T6<7DMry&)khWsca=IU8WI)zyCcmv%vt;l7_G>v8?-u_N0 zm=MLQ_`oMEpY!RKHpHAg&Nya}b36Hlm)iuNj(1=HpXE@+M;a&Xc6>+3?Jl3ZEMO`? z)wAo7kVpvb9kD%b9^lnP3|8Q+sb75b4ano&&OmV@o!-zlqL`cJG%o%$IM4Ml33iB{ zF?94XS@Fy}AU;mlX9P(x~wW&PpPgHhs=8SJMNsAalx zMin7ovJk*$Qvk=z0X;H`Vfl+bpjKHVlT46#MeuX zaS}<H!(7EqGilV;E56&!{JHpjkS_cg*8*!5SA0vcYz zoQ4PKG{#^K@xJ8{7gS78{fV99Kz&6@{Z62K1nN}+l}@06Akds6(Bx!}YbFt}i7ANJ zwThI|R|)*FSPi726uh(fndTJ0C=5^1N_lb<#OvAw1&q2tJvkNcVZo=A=RZM|;$?6X z*ICbyg*%Av!97(<+pB`eg1w$o>O6q)J$$Y?6|F_rMJY`46mW%(gXkq~p8`e&n?EBJ zuWM)I8T>~DSm-&34|z}k#_L$<`I)c)z-S64c}iiD=OBg(lRT&53z+0N6(7Q9mQzt( zJSZw9B@j)9(2QF#pXoQet_qfFeg85nKHHf+Gh}D?DQ`27{n+d&g|VIjjP(>?tmh!UfcHmIXcJAUNu&|q(Ai86W)>d}rUOCJ3L&OhW-dLK zFn}_B#b}U6XY`z4`}4SZu3usUrhINVpL@RpL)7!NU$ALLB< zhZgMqTqQ|gqU_K%lQ>CO5=J5o#yb@!3Vk1U!ATfF9HUKsU%X3d9-Mppr_=S^EHiLZ zAQY|G#W@MxnA32J&+asM8oQ`5=O^xch&~WI8SRu!oHrBhHxP->R7s1 zCEmp1FCtyeiUwLhdgxh~o;E}*`G?lWLOyZM*@v8qV@qTo5Cy~Rwv>mQm;7n`S4RfO z^At(%J{#L&w5g6~;?R8Grm(vr_;qTv#B(4l5bY*c;m9i-75!dxKgI5fM2g!Gh4$p; zd?W`DJV!&X9S3vGfop%0r!6kW4VOwg4zWPBUE%;@MkKSL(0qQWQLG%+0<`sxD|srz zQ7uHKtbpR^vKKF>xIC3Kl8L;INd^1P+_I=F=P%YJsBT}`i`tC70XE)kNgVmfnD@*J z2i0DjjKm580@-QF#H0i%AZTmegad95AEf?tLR!HaZ8qRUicf&(gyV1 zdsAZ`tnjz5ukrR)I$UXL9hpcH@u#A%(51zE(Gu_g5E0XCWFCSTS#|c@FtTj~gHtr) z9|?gnjj}s`CGilpmCJQ^OSj|5Hl5^n4o#_EfjZ|b?5hVmx#;)^)*}*$5lyVI3mf;oS4;8?;Q7{e&fj%E}eQhU%KUF@NY90OME=v zAB5Q5JU!#3>0DtLMPwWoX_4tKOxMi51PX6^-k^a|(WONq3-z2al6DW#bZq9@49RYz z$`@2JN4GV4l9KL5r4T!EW0JW0@ifv8k9Dr#ak@&D7zkm`%@xeGo^?L+7VeH1LNlf) znJ-(Z79`#rS0%%xV26!?!iT`P);Xi;VvY9l2lP`{Dr#`UoL?sAfoUmjcf9f;^!WU}6W5c#i~ZWtvFQM5V;<$f^5MiUiWpMVgiQ zGw(z)e_HCOUg^_g(c^BD&Cn^$rPJDqI*mD@OY|E-tT#@tz zi-Z(6qKlldMNAt-K&c{LSG5~Wv&8LXc(^Tw$Hm?fuP|~VXEHB4ebTsgT)>gj4S}Qr zb5C6?Ab`jAaWhT$H+rn0E5Qdx%)u?+Q5>|`xXVCvfL+`b5|c#+x66Y-H@OA}iw+AC z0(m3P$dmi(SX1mM@*-#L0*Ws|Lr*d&U;R_Gg^Cu}=jbV1ui0~Nt_6hE0byl!77N0) zghtcqNg7=mA>9*Ou&4ym)Gp}^k0ZoN(SIBhJ~#lyjU_b ze59U85?$Sl#GIf<9hL&y1nPtY3kSpr9P;B2;1oWG(yOAQnj3%ePL^dhdroag(}UD! zS3hEf>D zIRV9;_WORd!V#HtjJ#`2Nq+`jbCln&-u|6p99-@c;S(zXzKw)g#^qFQ8^lMNguU_1 zUOvN(aS;3fq#`kdNh>thp%r1vwu`q>_an-Gy62rV%MWGi)Meaci~?Mo9*83y8WTZd z!2d>@zwnJ{uY>l8=U5>vP}+CU27^LL`P8NN6-z$-6h{dow$>Dn?mOaxsYj7pIg-k+ zqOd@&p<^^6T*`)^c)Q&K13(y`r}=>{Nm}M6!O!Rim)ZTPM)YoId76{+1K* zDWQPTO%#W}56(RJ+N~(CgQ`QdOcR+iBFj-ra9nSF#|e4bew-}n1OObKiwvih+R5D> z#ht+TFhnB~^+LwZXVcUZ)=)*~Ge&r0HTS)ZO_X~A-^Xbl3^*xeEpbH@%Uk^-s*xXj zr-#Ol5|X;55O1`2SQk?uGT#&2X9kZyoCnFBQ8Xk1hbkgmFyn{@jt9EBIH~8x`r;-t zgjv1^nBN!vxK=qS{}R`_51nw7g!UsJaW85k(bwleybVx@Z4&px3QC-|TrMXTbzlc- zHG0A$=Hb5X@Zbp?wLtWZ7SFU!f)x0Fx;c#ljF2@kal~{Eyk_%IVj+0k!_G=vk~_zb zr~Mt)%gAsT&vlREhU*|C+Hp@OU{*P3cID{Yql$Sj-`JPaHAy1J@hLdHvM< z`rGfCc?g*}K;Tyztp$FJ6N6V$9Fa0k&mkT6L3G?;8*!=PJkhKmAPOR?K?>8@r~xi9 ztX;92S+vcXF=cT0^A&oK0h5x9U?vXYnLbWT8UO_|C_sGaArp|1XvukSRx3(thH~}H zjID9&4Twf^I)D|h*>^gOWJ=~ngD8|gC{s-`WUi+qA5{u8BfioCqvl%@V-ug!xiR7F< zZ*Z{3?3<{l2BgInJtK~q(DEuXy}~Of&sz=DUpFfU{7H8~1#4YqTA4JY%830*GEYVn z-5jLHr%!tUM=~D+B30t!fE2az>(gprVz7iIlU1I~?18{`gTZr}BGxIJRh)rp3;V$j z&3NHbyFBuem|Q_C zaYloHNk`1K6)CZS%Mf72gx|@bs5VWah-ntEWzqHcOW^nKw)J z#BgyN2a5=OBM_$jyX#kw8HuZ8G4iB}t)GYN(npq(Mp)Tq*a$$uH0L?TmgxW$>GBK# z1gb-5h7n7f3oso?W;_RAFUkp5f4+P=_9V@7VX>$ZNEcx#a%2L_^$}e_eRy065XdOy zA=}6!rBX-OehM*#BB;?|(M=38AOx@4uphFceA0AWhABqXdvL=p`~VIw$`8P#Ta=)Q zd980`|Ifs+P^0@{)e&c_*K{iqPy%xKFdn+$YDFuzQd?09NwflCy$%a5T}Dbo#cd(q z)DsF{BSgc%Y1{%wnDU_z;51VI2-AB=`kh9i)} z-x@~{sJ{;*FcJ0Fwj>F28j&m##o#?oD@_Q zWS3KY2~ISJ)86&Hx)wOMhg+Sw*SSxKf@yw-6V3@?|ws#!yr!>lSxn zOgTn#(Q1Pe4EY7lb=<1)c7bjhP8A(59deaIpH`dI_-t&1&fIK|%y2)Gw!>7ijXbxLFTI!oZ8C;rKuC{ZrUb$WSZK0N zBU+q1RQ)42$#Nf1@e&&!)a7hqbh;vLD)xkC$*cuW(8C1U6DaDeG;+IqR0p zpxjJVrXjqqD-`j{YKc;3$cla&dfiPsTMR@0V>UD8ZV4-`CEnF~V3CKlJUIp#9_Na2W&OGQh%U^6=o~XUjTUqw zN(ZbA$>6n_YGMHQKaA+ifZ;_oPg%r25jAUKHd;1rZQ-3sdwh`fII$>jL`npnONl77 zTI`vs^}S2BU7UaCtaSlAh}e=OX7+eav5stzutV*0c&YB-3+ZNTdLXc{th=gc+&btO zSE`_u!;GN*xQ~Kr9mQNyh1dyF@Zdu|f)mH=uq6^$RP3Cz%}^2AIsQ--R!{oCBz0=Q z=kh9r%Xry^5bDjsG6Mi79!+?Z1-MZv%>!Xz^v~F>6u~K($H1*(gXfsw=oM;y;t}u; z)C(JZnxPZ9a={%H_ST$F(HeQKyBq6JQQHBN|Cf(|$uww`mT*|cYNtFG0FdNq>R{A7 z3i%B$SRzxhSuWyGTo`{JOeXOHs`34`-K@~q<*!(%D%HDA~_*-G>OZI4|wId5|c~x3J^mUER0tfSxUw-=es(%nI ziCv+jHM{2^6qXA8F_&Ww=e#E$#mdTu1qwZ0&Ix!lF!<>4vIo!v+&w)*w6pI5-)g1k zaQKWxJ#1KbW1vkCqOM(-!G!RhF)V=@@r+o8qrx-FN_WgZu8M_whneyt3D|F_UBXRE zOta_eR*{=2o-8Y#*UU4>D2Vyz^@>0F8xcldJR^W;4y99zhVC3@}_tQl?|;QP-MEwaZcPW(_xq z_4$l(tctxMID|qlEMBtL&0S> zHT4cEK2vWTw8RhELk?I`;)DR2!!a{29pm2S1RKWKYmT9nnw|w^cw!kOn ztTG0fSP>QBw;ntfARLq8;7p8`U?oQxkj-yJ@r{*)1f1h#a#_q$bd?lScbpYOVJ7#! z2Qa=1p{gTA2oUBJyFWn4K$AAWVl+m%91v-&PUI2Bt_^6I{fF4`eqgD>p&R4u>%=9` zaZFlX99l+Vo66BH#%4tNf|!^qPc8s!_40^J1u(Wx9DCBUF(*}4k*o1ks*X|+cU-z? znpiJk9WP?3qzVPL*>}Q`cM@H3B85) zJ%#3av1jTlDAmLieQYyVC^B{Cllmz2Cyv3>?M^3U(8RL0(vqRld4=J zT3p3)NP?C5D(zSfKI9hDu!{*cqnRab`=ARMj%jIO@H>fZc)=&xY5X9?rjs6zElQfN zLmaI@29?MNXLS!;0NyN*j3jkxnTM+KGM?U+2RqTona78?;-|HL`Es7~e?mQFDQ+zvwT?5hM6bpr7eI5+3x*42)=>;xxc4TjNu4yJrYwc*J&0&uOJb3Uvq>um^RO7jq0*}0&%^ES zFi18Q$tzJSLd$X*TOjXBHfS0Ivd}ZdR5gH7iYaQ)<3WsSi$jxmd8C9>XSmy)wS1Y`xn2cRcMp-8KDXY*9asmY{3O5qAoS-p`w z6e;w|E7ROp{}@CUc#;ATDxIS@aYFz;pfa&UjD6;$mUtq}k_S=;C_Y+H3Y}35K)rhx zvo3?mhDE0Nw)3K;Gn>B%!iBKPeOs&-rjc5ld7SDRHjD}1zElr<6Rp_?jXQ1*W{<4T zuZvCJB1-c#ex2DEkwq%u(>}P_fGauu$n6P=T?L&7n)9v9J`x@<#`oyYc02SN5!)VW zE@1Y@aIcDv9%o4iX~mJcac-1>tdlsb;E0B+Eu}B#SMJDG6>I5KGAGT4B?ZT0vtST( zVmxg3PgsQ?b~@J|I6PGRG8+)<2M*>;yhoQ-VoDyI;o7A<=L3pd&TcVFL{a-hjLzNi z5c?`g={xB=#{i}A-U>61I?*XOGCZIx28Vb~J;Q!SCM4}k)o)Dc=z8EDPyhHRfttx^ z0(5BVsEt(OGc`vXN_wKAWY{>HrSN{O2Cg|T^>-ooLbn%~$7DwB0eesM!X@y+LG32O zBL(7Ob>cQj-JVgLVIn|anF8r>ufuztROo4T5Y|{aQ=sgCV+jB|adc8IbufeHYb_IR z^DnYmMgg@NKd+)Y11=Fy4i8Tb*-<~w`dg3mj8m^hPzuiz`h(~@Yb8yHR4W_4ZMikc zET=#}Bqy9Qho_|+rwC!BiF8+L!mmnA=$urQwXf)O4=*6&v}tLQ3oT8E_*w62TcWTL zGmy)Gaq~5Rv6#+=88V++7w88HD&L!!U-M}O>t6VGA{!~u`f5|Zq&67(_#Iw-EYF9N z675rBN0}HugMuDg%n(fT|5~MG@Hv8P6v0!O(d3yXFFZ4Z(jRY_9{3#{+lp!_ zS@Z*z7TMo4U9!V8Hmg&U1nqk8@O#$3;7m2AaHDn^Ck>u0Q5@Iih;9wiE2giS&G_R$ z9M`Sr{*Z!Zov&o=)5#9^z|)b?j9$@NN9v_EF+H4ODbIgt0KpKovd^)=~>7hmMGF~dvpg!Tw9zIg;Pd8Zw#f5mT?=mX#Q`&+JexQicla~YG*c9B z1F%JzKj#g9+`+(4%V9W?YI0Ui09mN5=F zd=Q=J4-8*@(ke*_VCEVXr+<#g?v!cELagFr@a#o&V;(UE`AiH=-2^sFS!8l@lSR&AKHEhN!^T9kPDIJH0GKrMwUKz-a325ALlQQ5_A+R0 zL#}nNOQ&#|^%V;1`HmDixV}$eQe8C&oBS#Z$WJsIFJnS6T!iM@PCOA|RT{iEg z3sX<{;Hm@kxW$3&yu(f-7N?zCA;Q3NDH|dlZsDbZkQtcVCLP$_Mo)@LbQ7|;VI0W@ z5_p9~W~wQgd1<$|e@*fd5=F@`PluNYIlh#b^8S>BXZLh+yz9QO0^4E}jqJXp>;(zt zLAICHa-kh1Pgjp9I`iP~_`xhr-A>Lr_Rbt;295j7>(c={EPU?#H8CsS{vI3HF8al8 z(JZXm!?gmtCs>{J6Z*y6a5tRfsa;q<#DOhGi+Z?SYvBi|PWilqbR>`!f>hnD5{-SR( zd|H#~W~NU{$QiyW!F70_VO=#pG_Z2I>W#mx_9sjxJ(Msgs;ekGt}{X02ziIq+zM_4 zn_;6k4v_6}h$ti%`b+o~j=9pU8SsE@^kB32eW80R#Jy0GgLFLI)wjyt#DEfi`+H32 zCPja{`=QHM+N!6r0pXGp5Jg*YYb4XqlQEk!;^;R~muN`HIWgJFNvnyAA!vGwnC2|^ zF>+-S3eT()o4zWVkq4^3Jc4S$yg(s-<3bylfXg*h;Hy;HiL9R5HUAx7qd=LDOX$e8 zuy1I-a@Ex)oX%p}MxyjzOj1jYUoRd=C?#gjvDzAgLm0`bI3A(kR;VlL)uq7^N_cB; zYy8E>r%;$p5o|lDTfKgz?S2DIv;zR&AVYx4KfkDJrpGȖvI3rH{oQhXqGp0EXp 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 E2kis8n*aa+ literal 0 HcmV?d00001 diff --git a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/Android10Platform.kt b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/Android10Platform.kt index 02df7e3fdfde..5b982bdacce4 100644 --- a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/Android10Platform.kt +++ b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/Android10Platform.kt @@ -16,6 +16,7 @@ package okhttp3.internal.platform import android.annotation.SuppressLint +import android.content.Context import android.os.Build import android.security.NetworkSecurityPolicy import android.util.CloseGuard @@ -34,7 +35,9 @@ import okhttp3.internal.tls.CertificateChainCleaner /** Android 10+ (API 29+). */ @SuppressSignatureCheck -class Android10Platform : Platform() { +class Android10Platform : Platform(), ContextAwarePlatform { + override var applicationContext: Context? = null + private val socketAdapters = listOfNotNull( Android10SocketAdapter.buildIfSupported(), diff --git a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/AndroidPlatform.kt b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/AndroidPlatform.kt index 3539edc91156..35b8d0aeeb63 100644 --- a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/AndroidPlatform.kt +++ b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/AndroidPlatform.kt @@ -15,6 +15,7 @@ */ package okhttp3.internal.platform +import android.content.Context import android.os.Build import android.security.NetworkSecurityPolicy import android.util.Log @@ -42,7 +43,9 @@ import okhttp3.internal.tls.TrustRootIndex /** Android 5 to 9 (API 21 to 28). */ @SuppressSignatureCheck -class AndroidPlatform : Platform() { +class AndroidPlatform : Platform(), ContextAwarePlatform { + override var applicationContext: Context? = null + private val socketAdapters = listOfNotNull( StandardAndroidSocketAdapter.buildIfSupported(), diff --git a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/ContextAwarePlatform.kt b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/ContextAwarePlatform.kt new file mode 100644 index 000000000000..b8737c497870 --- /dev/null +++ b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/ContextAwarePlatform.kt @@ -0,0 +1,7 @@ +package okhttp3.internal.platform + +import android.content.Context + +interface ContextAwarePlatform { + var applicationContext: Context? +} diff --git a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/PlatformRegistry.kt b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/PlatformRegistry.kt index 38ec6920953a..3438feb3de5a 100644 --- a/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/PlatformRegistry.kt +++ b/okhttp/src/androidMain/kotlin/okhttp3/internal/platform/PlatformRegistry.kt @@ -1,5 +1,6 @@ package okhttp3.internal.platform +import android.content.Context import okhttp3.internal.platform.android.AndroidLog actual object PlatformRegistry { @@ -10,4 +11,10 @@ actual object PlatformRegistry { actual val isAndroid: Boolean get() = true + + var applicationContext: Context? + get() = (Platform.get() as? ContextAwarePlatform)?.applicationContext + set(value) { + (Platform.get() as? ContextAwarePlatform)?.applicationContext = value + } } diff --git a/okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/AssetPublicSuffixList.kt b/okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/AssetPublicSuffixList.kt new file mode 100644 index 000000000000..158463b5bc03 --- /dev/null +++ b/okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/AssetPublicSuffixList.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.internal.publicsuffix + +import java.io.IOException +import okhttp3.internal.platform.PlatformRegistry +import okio.Source +import okio.source + +internal class AssetPublicSuffixList( + override val path: String = PUBLIC_SUFFIX_RESOURCE, +) : BasePublicSuffixList() { + override fun listSource(): Source { + val assets = + PlatformRegistry.applicationContext?.assets ?: throw IOException("Platform applicationContext not initialized") + + return assets.open(path).source() + } + + companion object { + val PUBLIC_SUFFIX_RESOURCE = "/PublicSuffixDatabase.list" + } +} diff --git a/okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.android.kt b/okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.android.kt new file mode 100644 index 000000000000..ab03b226d5c3 --- /dev/null +++ b/okhttp/src/androidMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.android.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.internal.publicsuffix + +internal actual val Default: PublicSuffixList = AssetPublicSuffixList() diff --git a/okhttp/src/androidUnitTest/kotlin/okhttp3/test/BaseJavaTest.android.kt b/okhttp/src/androidUnitTest/kotlin/okhttp3/test/BaseJavaTest.android.kt new file mode 100644 index 000000000000..144566f174ce --- /dev/null +++ b/okhttp/src/androidUnitTest/kotlin/okhttp3/test/BaseJavaTest.android.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.test + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import okhttp3.internal.platform.PlatformRegistry +import org.junit.Before +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +actual open class BaseJavaTest actual constructor() { + @Before + fun init() { + PlatformRegistry.applicationContext = ApplicationProvider.getApplicationContext() + } +} diff --git a/okhttp/src/jvmTest/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/BasePublicSuffixList.kt similarity index 74% rename from okhttp/src/jvmTest/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt rename to okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/BasePublicSuffixList.kt index 3efacb9e66d1..86bcafe7667f 100644 --- a/okhttp/src/jvmTest/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt +++ b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/BasePublicSuffixList.kt @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package okhttp3.internal.publicsuffix import java.io.IOException @@ -6,16 +21,10 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.atomic.AtomicBoolean import okhttp3.internal.platform.Platform import okio.ByteString -import okio.FileSystem -import okio.GzipSource -import okio.Path -import okio.Path.Companion.toPath +import okio.Source import okio.buffer -internal class ResourcePublicSuffixList( - val path: Path = PUBLIC_SUFFIX_RESOURCE, - val fileSystem: FileSystem = FileSystem.RESOURCES, -) : PublicSuffixList { +internal abstract class BasePublicSuffixList : PublicSuffixList { /** True after we've attempted to read the list for the first time. */ private val listRead = AtomicBoolean(false) @@ -35,7 +44,7 @@ internal class ResourcePublicSuffixList( var publicSuffixExceptionListBytes: ByteString? try { - GzipSource(fileSystem.source(path)).buffer().use { bufferedSource -> + listSource().buffer().use { bufferedSource -> val totalBytes = bufferedSource.readInt() publicSuffixListBytes = bufferedSource.readByteString(totalBytes.toLong()) @@ -52,6 +61,8 @@ internal class ResourcePublicSuffixList( } } + abstract fun listSource(): Source + override fun ensureLoaded() { if (!listRead.get() && listRead.compareAndSet(false, true)) { readTheListUninterruptibly() @@ -65,10 +76,12 @@ internal class ResourcePublicSuffixList( check(::bytes.isInitialized) { // May have failed with an IOException - "Unable to load $PUBLIC_SUFFIX_RESOURCE resource from the classpath." + "Unable to load $path resource in ${this.javaClass.simpleName}." } } + abstract val path: Any + /** * Reads the public suffix list treating the operation as uninterruptible. We always want to read * the list otherwise we'll be left in a bad state. If the thread was interrupted prior to this @@ -85,7 +98,7 @@ internal class ResourcePublicSuffixList( Thread.interrupted() // Temporarily clear the interrupted state. interrupted = true } catch (e: IOException) { - Platform.get().log("Failed to read public suffix list", Platform.WARN, e) + Platform.Companion.get().log("Failed to read public suffix list", Platform.Companion.WARN, e) return } } @@ -95,21 +108,4 @@ internal class ResourcePublicSuffixList( } } } - - /** Visible for testing. */ - fun setListBytes( - publicSuffixListBytes: ByteString, - publicSuffixExceptionListBytes: ByteString, - ) { - this.bytes = publicSuffixListBytes - this.exceptionBytes = publicSuffixExceptionListBytes - listRead.set(true) - readCompleteLatch.countDown() - } - - companion object { - @JvmField - val PUBLIC_SUFFIX_RESOURCE = - "okhttp3/internal/publicsuffix/${PublicSuffixDatabase::class.java.simpleName}.gz".toPath() - } } diff --git a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabase.kt b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabase.kt index 88094ad1c600..31dd91efd944 100644 --- a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabase.kt +++ b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabase.kt @@ -26,7 +26,7 @@ import okio.ByteString.Companion.encodeUtf8 * [publicsuffix_org]: https://publicsuffix.org/ */ class PublicSuffixDatabase internal constructor( - private val publicSuffixList: PublicSuffixList, + private val publicSuffixList: PublicSuffixList = Default, ) { /** * Returns the effective top-level domain plus one (eTLD+1) by referencing the public suffix list. @@ -153,7 +153,7 @@ class PublicSuffixDatabase internal constructor( private const val EXCEPTION_MARKER = '!' - private val instance = PublicSuffixDatabase(EmbeddedPublicSuffixList) + private val instance = PublicSuffixDatabase(Default) fun get(): PublicSuffixDatabase { return instance diff --git a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.kt b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.kt index 3fdfaa659edc..2464ae1e3810 100644 --- a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.kt +++ b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.kt @@ -26,3 +26,5 @@ internal interface PublicSuffixList { val bytes: ByteString val exceptionBytes: ByteString } + +internal expect val Default: PublicSuffixList diff --git a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt new file mode 100644 index 000000000000..fcc4da38f276 --- /dev/null +++ b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/publicsuffix/ResourcePublicSuffixList.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.internal.publicsuffix + +import okio.FileSystem +import okio.GzipSource +import okio.Path +import okio.Path.Companion.toPath +import okio.Source + +internal class ResourcePublicSuffixList( + override val path: Path = PUBLIC_SUFFIX_RESOURCE, + val fileSystem: FileSystem = FileSystem.Companion.RESOURCES, +) : BasePublicSuffixList() { + override fun listSource(): Source = GzipSource(fileSystem.source(path)) + + companion object { + @JvmField + val PUBLIC_SUFFIX_RESOURCE = + "okhttp3/internal/publicsuffix/${PublicSuffixDatabase::class.java.simpleName}.gz".toPath() + } +} diff --git a/okhttp/src/commonJvmAndroid/kotlinTemplates/okhttp3/internal/publicsuffix/EmbeddedPublicSuffixList.kt b/okhttp/src/commonJvmAndroid/kotlinTemplates/okhttp3/internal/publicsuffix/EmbeddedPublicSuffixList.kt deleted file mode 100644 index 93f14cff3d26..000000000000 --- a/okhttp/src/commonJvmAndroid/kotlinTemplates/okhttp3/internal/publicsuffix/EmbeddedPublicSuffixList.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2024 Block, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package okhttp3.internal.publicsuffix - -//Note that PublicSuffixDatabase.gz is compiled from The Public Suffix List: -//https://publicsuffix.org/list/public_suffix_list.dat -// -//It is subject to the terms of the Mozilla Public License, v. 2.0: -//https://mozilla.org/MPL/2.0/ - -import okio.Buffer -import okio.ByteString -import okio.ByteString.Companion.decodeBase64 -import okio.GzipSource -import okio.buffer - -/** - * A implementation of I/O for PublicSuffixDatabase.gz by directly encoding - * the relevant byte arrays in a class file. - */ -internal object EmbeddedPublicSuffixList: PublicSuffixList { - override fun ensureLoaded() { - } - - override val bytes: ByteString - - override val exceptionBytes: ByteString - - init { - Buffer().use { buffer -> - buffer.write($publicSuffixListBytes) - GzipSource(buffer).buffer().use { source -> - val totalBytes = source.readInt() - bytes = source.readByteString(totalBytes.toLong()) - - val totalExceptionBytes = source.readInt() - exceptionBytes = source.readByteString(totalExceptionBytes.toLong()) - } - } - } -} diff --git a/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixDatabaseTest.kt b/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixDatabaseTest.kt new file mode 100644 index 000000000000..e677f18685d9 --- /dev/null +++ b/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixDatabaseTest.kt @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2017 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.internal.publicsuffix + +import assertk.assertThat +import assertk.assertions.isEqualTo +import assertk.assertions.isNull +import okio.Buffer +import org.junit.jupiter.api.Test + +class ConfiguredPublicSuffixDatabaseTest { + private val list = ConfiguredPublicSuffixList() + private val publicSuffixDatabase = PublicSuffixDatabase(list) + + @Test fun longestMatchWins() { + list.bytes = + Buffer() + .writeUtf8("com\n") + .writeUtf8("my.square.com\n") + .writeUtf8("square.com\n").readByteString() + + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("example.com")) + .isEqualTo("example.com") + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.example.com")) + .isEqualTo("example.com") + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.bar.square.com")) + .isEqualTo("bar.square.com") + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.com")) + .isEqualTo("foo.my.square.com") + } + + @Test fun wildcardMatch() { + list.bytes = + Buffer() + .writeUtf8("*.square.com\n") + .writeUtf8("com\n") + .writeUtf8("example.com\n") + .readByteString() + + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("my.square.com")).isNull() + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.com")) + .isEqualTo("foo.my.square.com") + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("bar.foo.my.square.com")) + .isEqualTo("foo.my.square.com") + } + + @Test fun boundarySearches() { + list.bytes = + Buffer() + .writeUtf8("bbb\n") + .writeUtf8("ddd\n") + .writeUtf8("fff\n") + .readByteString() + + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("aaa")).isNull() + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("ggg")).isNull() + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("ccc")).isNull() + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("eee")).isNull() + } + + @Test fun exceptionRule() { + list.bytes = + Buffer() + .writeUtf8("*.jp\n") + .writeUtf8("*.square.jp\n") + .writeUtf8("example.com\n") + .writeUtf8("square.com\n") + .readByteString() + list.exceptionBytes = + Buffer() + .writeUtf8("my.square.jp\n") + .readByteString() + + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("my.square.jp")) + .isEqualTo("my.square.jp") + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.jp")) + .isEqualTo("my.square.jp") + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("my1.square.jp")).isNull() + } + + @Test fun noEffectiveTldPlusOne() { + list.bytes = + Buffer() + .writeUtf8("*.jp\n") + .writeUtf8("*.square.jp\n") + .writeUtf8("example.com\n") + .writeUtf8("square.com\n") + .readByteString() + list.exceptionBytes = + Buffer() + .writeUtf8("my.square.jp\n") + .readByteString() + + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("example.com")).isNull() + assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.square.jp")).isNull() + } +} diff --git a/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixList.kt b/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixList.kt new file mode 100644 index 000000000000..610f19524092 --- /dev/null +++ b/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/ConfiguredPublicSuffixList.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.internal.publicsuffix + +import okio.ByteString + +/** + * An implementation of I/O for PublicSuffixDatabase.gz by directly passing in ByteStrings. + */ +internal class ConfiguredPublicSuffixList : PublicSuffixList { + override fun ensureLoaded() { + } + + override var bytes: ByteString = ByteString.EMPTY + + override var exceptionBytes: ByteString = ByteString.EMPTY +} diff --git a/okhttp/src/jvmTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt b/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt similarity index 68% rename from okhttp/src/jvmTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt rename to okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt index 02ef95e947a3..e82c9492ba20 100644 --- a/okhttp/src/jvmTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt +++ b/okhttp/src/commonTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixDatabaseTest.kt @@ -21,100 +21,27 @@ import assertk.assertions.isNull import assertk.assertions.isTrue import kotlin.test.assertEquals import kotlin.test.assertFailsWith +import okhttp3.internal.publicsuffix.ResourcePublicSuffixList.Companion.PUBLIC_SUFFIX_RESOURCE import okhttp3.internal.toCanonicalHost +import okhttp3.okHttpRoot +import okhttp3.test.BaseJavaTest import okio.Buffer -import okio.ByteString import okio.FileSystem import okio.GzipSource import okio.Path.Companion.toPath import okio.buffer import okio.use -import org.junit.jupiter.api.Test +import org.junit.Test -class PublicSuffixDatabaseTest { - private val list = ResourcePublicSuffixList() - private val publicSuffixDatabase = PublicSuffixDatabase(list) +class PublicSuffixDatabaseTest : BaseJavaTest() { + private val publicSuffixDatabase = PublicSuffixDatabase() - @Test fun longestMatchWins() { - val buffer = - Buffer() - .writeUtf8("com\n") - .writeUtf8("my.square.com\n") - .writeUtf8("square.com\n") - list.setListBytes(buffer.readByteString(), ByteString.of()) - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("example.com")) - .isEqualTo("example.com") - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.example.com")) - .isEqualTo("example.com") - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.bar.square.com")) - .isEqualTo("bar.square.com") - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.com")) - .isEqualTo("foo.my.square.com") - } - - @Test fun wildcardMatch() { - val buffer = - Buffer() - .writeUtf8("*.square.com\n") - .writeUtf8("com\n") - .writeUtf8("example.com\n") - list.setListBytes(buffer.readByteString(), ByteString.of()) - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("my.square.com")).isNull() - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.com")) - .isEqualTo("foo.my.square.com") - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("bar.foo.my.square.com")) - .isEqualTo("foo.my.square.com") - } - - @Test fun boundarySearches() { - val buffer = - Buffer() - .writeUtf8("bbb\n") - .writeUtf8("ddd\n") - .writeUtf8("fff\n") - list.setListBytes(buffer.readByteString(), ByteString.of()) - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("aaa")).isNull() - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("ggg")).isNull() - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("ccc")).isNull() - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("eee")).isNull() - } - - @Test fun exceptionRule() { - val exception = - Buffer() - .writeUtf8("my.square.jp\n") - val buffer = - Buffer() - .writeUtf8("*.jp\n") - .writeUtf8("*.square.jp\n") - .writeUtf8("example.com\n") - .writeUtf8("square.com\n") - list.setListBytes(buffer.readByteString(), exception.readByteString()) - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("my.square.jp")) - .isEqualTo("my.square.jp") - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.jp")) - .isEqualTo("my.square.jp") - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("my1.square.jp")).isNull() - } - - @Test fun noEffectiveTldPlusOne() { - val exception = - Buffer() - .writeUtf8("my.square.jp\n") - val buffer = - Buffer() - .writeUtf8("*.jp\n") - .writeUtf8("*.square.jp\n") - .writeUtf8("example.com\n") - .writeUtf8("square.com\n") - list.setListBytes(buffer.readByteString(), exception.readByteString()) - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("example.com")).isNull() - assertThat(publicSuffixDatabase.getEffectiveTldPlusOne("foo.square.jp")).isNull() - } + val pathForTests = okHttpRoot / "okhttp/src/jvmMain/resources" / PUBLIC_SUFFIX_RESOURCE - @Test fun allPublicSuffixes() { + @Test + fun allPublicSuffixes() { val buffer = Buffer() - FileSystem.RESOURCES.source(ResourcePublicSuffixList.PUBLIC_SUFFIX_RESOURCE).use { resource -> + FileSystem.SYSTEM.source(pathForTests).use { resource -> GzipSource(resource).buffer().use { source -> val length = source.readInt() buffer.write(source, length.toLong()) @@ -132,9 +59,10 @@ class PublicSuffixDatabaseTest { } } - @Test fun publicSuffixExceptions() { + @Test + fun publicSuffixExceptions() { val buffer = Buffer() - FileSystem.RESOURCES.source(ResourcePublicSuffixList.PUBLIC_SUFFIX_RESOURCE).use { resource -> + FileSystem.SYSTEM.source(pathForTests).use { resource -> GzipSource(resource).buffer().use { source -> var length = source.readInt() source.skip(length.toLong()) @@ -152,7 +80,8 @@ class PublicSuffixDatabaseTest { } } - @Test fun threadIsInterruptedOnFirstRead() { + @Test + fun threadIsInterruptedOnFirstRead() { Thread.currentThread().interrupt() try { val result = publicSuffixDatabase.getEffectiveTldPlusOne("squareup.com") @@ -162,7 +91,8 @@ class PublicSuffixDatabaseTest { } } - @Test fun secondReadFailsSameAsFirst() { + @Test + fun secondReadFailsSameAsFirst() { val badPublicSuffixDatabase = PublicSuffixDatabase( ResourcePublicSuffixList( @@ -183,7 +113,8 @@ class PublicSuffixDatabaseTest { } /** These tests are provided by [publicsuffix.org](https://publicsuffix.org/list/). */ - @Test fun publicSuffixDotOrgTestCases() { + @Test + fun publicSuffixDotOrgTestCases() { // Any copyright is dedicated to the Public Domain. // https://creativecommons.org/publicdomain/zero/1.0/ @@ -282,13 +213,6 @@ class PublicSuffixDatabaseTest { checkPublicSuffix("xn--fiqs8s", null) } - @Test fun contentsMatch() { - list.ensureLoaded() - - assertEquals(list.bytes, EmbeddedPublicSuffixList.bytes) - assertEquals(list.exceptionBytes, EmbeddedPublicSuffixList.exceptionBytes) - } - private fun checkPublicSuffix( domain: String, registrablePart: String?, diff --git a/okhttp/src/commonTest/kotlin/okhttp3/test/BaseJavaTest.kt b/okhttp/src/commonTest/kotlin/okhttp3/test/BaseJavaTest.kt new file mode 100644 index 000000000000..a6f1e689ec97 --- /dev/null +++ b/okhttp/src/commonTest/kotlin/okhttp3/test/BaseJavaTest.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.test + +expect open class BaseJavaTest() diff --git a/okhttp/src/jvmMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.jvm.kt b/okhttp/src/jvmMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.jvm.kt new file mode 100644 index 000000000000..997a4a750c80 --- /dev/null +++ b/okhttp/src/jvmMain/kotlin/okhttp3/internal/publicsuffix/PublicSuffixList.jvm.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.internal.publicsuffix + +internal actual val Default: PublicSuffixList = ResourcePublicSuffixList() diff --git a/okhttp/src/jvmTest/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz b/okhttp/src/jvmMain/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz similarity index 100% rename from okhttp/src/jvmTest/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz rename to okhttp/src/jvmMain/resources/okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz diff --git a/okhttp/src/jvmTest/kotlin/okhttp3/test/BaseJavaTest.kt b/okhttp/src/jvmTest/kotlin/okhttp3/test/BaseJavaTest.kt new file mode 100644 index 000000000000..75219a5cca8a --- /dev/null +++ b/okhttp/src/jvmTest/kotlin/okhttp3/test/BaseJavaTest.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Block, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.test + +actual open class BaseJavaTest actual constructor()