From 03f886f76d555084d76f1fd33b446ea04445fa85 Mon Sep 17 00:00:00 2001 From: "LAPTOP-SB56SG4Q\\86185" Date: Fri, 3 Sep 2021 14:45:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=BC=80=E6=BA=90=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=9D=90=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JSD-8235-需求确认书V1.2(1).docx | Bin 0 -> 63861 bytes README.md | 5 +- plugin.xml | 20 + .../java/com/fr/plugin/JHHandlerProvider.java | 23 + .../java/com/fr/plugin/JHURLAliasBridge.java | 29 ++ .../com/fr/plugin/api/DataTableExport.java | 165 ++++++ .../java/com/fr/plugin/api/SQLQueryApi.java | 67 +++ .../java/com/fr/plugin/api/SQLUpdateApi.java | 71 +++ .../java/com/fr/plugin/utils/AesUtils.java | 89 ++++ .../java/com/fr/plugin/utils/DbUtils.java | 212 ++++++++ .../java/com/fr/plugin/utils/RespUtils.java | 34 ++ src/main/resources/com/fr/plugin/alert.html | 35 ++ .../resources/com/fr/plugin/demo.properties | 1 + .../com/fr/plugin/demo_zh_CN.properties | 1 + src/main/resources/com/fr/plugin/js/print.js | 476 ++++++++++++++++++ 15 files changed, 1227 insertions(+), 1 deletion(-) create mode 100644 JSD-8235-需求确认书V1.2(1).docx create mode 100644 plugin.xml create mode 100644 src/main/java/com/fr/plugin/JHHandlerProvider.java create mode 100644 src/main/java/com/fr/plugin/JHURLAliasBridge.java create mode 100644 src/main/java/com/fr/plugin/api/DataTableExport.java create mode 100644 src/main/java/com/fr/plugin/api/SQLQueryApi.java create mode 100644 src/main/java/com/fr/plugin/api/SQLUpdateApi.java create mode 100644 src/main/java/com/fr/plugin/utils/AesUtils.java create mode 100644 src/main/java/com/fr/plugin/utils/DbUtils.java create mode 100644 src/main/java/com/fr/plugin/utils/RespUtils.java create mode 100644 src/main/resources/com/fr/plugin/alert.html create mode 100644 src/main/resources/com/fr/plugin/demo.properties create mode 100644 src/main/resources/com/fr/plugin/demo_zh_CN.properties create mode 100644 src/main/resources/com/fr/plugin/js/print.js diff --git a/JSD-8235-需求确认书V1.2(1).docx b/JSD-8235-需求确认书V1.2(1).docx new file mode 100644 index 0000000000000000000000000000000000000000..b29e3f67f3df1ed3ecc53295a688a1a3442b3515 GIT binary patch literal 63861 zcmb@tV~}Vuw=LSXZQHhO+s1C&wr$(C-M!nkZQE~u=e}F_oLleb%a4`RtdW_SjJ1-g zl`$2hfkB`E{!_x_4g~&F|L+3%uVG?mtl(&8??kWg4~Fv30P$Zi9C#`r3qSw>4fqQw9L#;Emi!em&&{Rv`!%7gV+wAvCt_Ie>!L7=MRcu zM$=U|OR^~Vrm_*PR}XeyH=_5(GsR8map-|S>;z`~>`8RDI`WF+iVs}i9GLa*93X2d zGW2xp{($&pwTZ@gcu)JVFgAc=eQ8Aod_P1eo5V);Bp`;yb`Y2~7mx$Kinii0PlF~X zL#$NeAQaw0F;7krAOqo{z^xk_DkI$Bbg&<6%|#D74bNv2bZ)swX!3wzAX<}}H$)YF z>^b8BdM5?@WdF6ca^mLM7yp%(d$?AyXjA)}9^OEjMV2E`-`c9I6s*CsYtuTu=*C$W zeSD98GS zQvlFHRXjOH*Pbrg2LoNUr}9vttGo)j{0y7jV1>o_{hruh>KfpLJ3k-Fii_t#&AmkUbG6HbCBEdx+8n8XLU zqAlW$>}r9NwfVs<5kad6}VB;x|}0BUFMGr@#YSsrvM>L|Rqp>ZceU^Uy z5#;xeEad+|l#7$Ioy~uJLGjanf*CMGUqgC@|MHQQa^!?_spPCX&kL0`rIE})oP?2V zNS$}FGkveSy*u#3o$eUD)`~GmpMn=jr;~vIRdgT*@ul58y9;PTc%L<&i4~bbqMz^A zcJ@%_<}@sX2znwQZlv8I1x_=*d=aUhCShErKaEz<4KL<2oPP#PuG~pV;xdq$1ic>x zDgOOA*h@*9-S3kyeEV}MKQB6TRBFSVNZ4r(D^gRXxQ--b zwSluX^n(o4#itD6TxRq6%nf1L$iTS!twA)C~0IJoAjyw_LV z&kv;O)O!oa)!>VWDx182QkFv{U!}){8JDHEGKscus;bhnB3S%ZsfZz`+5==yFm zGxUEp)xo|;C)eE*<3hQqr_0pUvDWLkFOG*cxvA;5HvIm0l`v+shV{7mu}rzD-Iye$ z^nFkGebejnb#P?toSP?s@fdJ)aGc##L z+VL}6#OY_^@-O4U#%?ZlC%rzN=a_3%Rb^2>rO(eySo3sC#JT^8cN;4jKeL~(?cm_z znd-v)CcVK3i=Mpg=DC;wTepuS=3}1uxPvR&Kce8z4KIUL$^%p8L4x;KXOBn&_qp#% ziXV^@JKVWxwJ`mtO<-~7F91oL^uD+K=`~rW;uIa_p!!o}4 zkfwfy)z!qEAqBrR?e#vvtpEPN{6=+fdyul%_%cW!N1y|)L%nBNv~J(ow6Fn^61Zy? zroSmJyQYbVu7`nl+;fF3zJ3=XxdMD$gpX$u^z~=w(o}}{d;@xR8|So$@oaKtA_Us` zexv+TX@xs|u>YzeTHssqc7l5QDqWHd=F`nc#(PEv8$sVBHBEjL8rjmlo57lyYS+MS z*BnLjh(cU5%TT_kqdGuq63fCy6S#)nDnG^)w)vl>HI;Slr4g)CVN(DH^udtc%k+L@ zJgnie6j0+KYrSR4D@s?tyKRkh_g^Elr){ld{$HcEyKRYx(8?kaC)JqiVuhG7rDzS5 zYym=MFaRs8 zXx^D4(=5jFCGuM=1})&n)C)p>B%J1L{IR`hYJO^TCBo{Kf0iOzBUTaT=r}cQYfrRK zuPr7(2zTf%f7ldIqj(hqmksW5vx%`7!CEmmh+zHhxEg-mv}pTspvLkwwu$lx)hLv9 z*gG57%=mAF$x0WiW<;9H?;$SB`RPzKV>T=o-1@@KA3R7t+g-gCh4uQd{sVH!7$;<4 zu7oMUp9+N27i-Vqzy}_=VsIM?E6tH{*1huWJHf!iR;%~n*ty(Yc31On-;;J5JV7J+ z#rFMF&0X&GZ?0WjSA3gV5C}Pg?U~jNNaNQbZ{{QKKf_6(w$2I?;tY5?`&;K?;E>H;V#Ae$QWji z+#D5K>G>!|Q)1m(C~c$EVh&ZhtT;|RaJhJoJhgNqvi#{TrE)!$ihS@J-& z1!VPSj8HaKSEt4dH@O;0MFqi_N+AP3-5i2_14PPXEOdVtcZ%^4>aq7jU`$uHLtsYU z&+~tY#G7a515mnr$^)0dK6V&hE^-d7VH#GYqgJZF75n(P#yzF6?+m!`IK6`<#M-w^zI)9K0&3*h1((^qISH z6|p^utT}3CE=au0z%xW|uoM0UhhTagXBhE^rIaKA)3ASyJV>(-@Gz&T5K8qg?Y4VGLy$ttIHle>jCS|wG#y;vn#oYCR0PXugE)9GlNd&!?ER5(CKL5dtHK*@X z+cl>z^1L1T3hQC4{^$ky*>{Kh8u~Yk zyph{0adra|*My_S#t|O7c#B=0y`R`k@pbLGmhkno>*mD6ZS38hpPP3-@5v%UAcW!1KeDh4aP$4&XdE*c$h z=(?P!RYhBKXKy~-UwzmVUmP7s;Pz7g_THU*JY{}sOsx3Wr(JQs_VF-7M#k?w@pyZ# zPMZY_WT8W?dU#@A9SXBAH$FzdUKY;(wqLuSI2}?#B!>={diz>>-L3TH`{1p(g}=0{ z+`-Sw`}pY7z|Pfl{(Ik%n$gUY9u%)xa_!RLCXsGxD09Ti8()i}dlgb|+OR&7xI43Bb-SN&cZ zzNU@xjZACEF#36_3Tc)#V8DMXFi`%V#~uHvfT63wj-WSzNy+DivO$r9n%mTX`(96}19bG|25j zV16%$OM%6`3=Rc$CjxjR!0m#7Pldu>4)}Jd!Fx?1n)E*)K6eVR!~t%H{5zfqfY4!o z+r=?5>quP?xm{tw9eP637_$n8Mje(&01y&Utu zN9*u!mKv1*Ca(7XPW=DG`Jc5QheHA1sR%0e|A*qUreIM0zx|zMRsH|uj~xyKyLf`T zu+c`?Va&k7FLUruQBI0+11rE~c;L6<`b=H(KIP9H=N3}R_Lv&vfSsQ0P;1izTk%r6 zKXmW+`Sx6@RvL*lC#d3Br{&xKXro0+=KS+oJVzB^7g_cmD9Tw~YRL~j!} zb=w1=wU0M3wkQ zc-08#1y@#g=NQ|-F+Y-n9CoX0iPidD1v=as!|_}l9&d|VknTl)Z!0(T^}RB9nnfjt zcsi3(PoO-gxmNpj^%UktzL+zP%SL_0wR%*?To$~c6WD!fVF(=B5?WfO$(ympr&22J zuKy{~w+Y{2$l*3#BZ50OF6^)X?;FVE<(_dGZ8u=xR4MU`!^6c4RGZ@536xSK{rFJ; z9pI>%yTF z;mE%IpQ82TYY>-fQ`JK1lGk~2elo`4=|nfR3Fwmky2N40-pe*vL5l0# zzmkbTnH-$^+cyHKaN4QR;R4*AZSaOI*7p(TgcerFyn-+L@0gpLIEo_$Re|nsbSXOi z4Kdd<$3BxWxU{t3h9&_}aN!)HRkrYWS7!M8kAR#XH# zYLG(?P!!a7){Ou%(jjxQxD}ev z$KjFEHGKDM;%NC>bH4IN5+lCKR~a(Oi3jPz1O>5)GTtGY@*-K#vy(}xC5lM~9Ay)2 zl#t%DDe@v^QwCY~lS$vDWPLlsrZo$53Xv%#{W}??i1KE`61RyZ7@XHr$@T;|AE2>i zg@t^$(Nm>=<0mhGf&l7KnfAh)2TsF$RJQE8Y_*`AE|WcW5!uQIGGw@Y@CN(&UmAUX zJ-wzJffwf)y9sb~gSU@)k`}#6rf&@kD1Tc!A~8j-KZ(HHw)jUu^WWSzfdyiZ()RJ! zr3d?PNK_MLL>~$*8*^}#5TI{;YXU-gB_slkIVbEIF@XA5hCGEeQO4vY6tE)GC9xCn zJudmU69r_H%`CMbYw_}a2{$R@N5*Md2)i|w4JaQ``6aXJGH4WBdD>=|5(^)gGc_ce zEM9v#vt;tj6Jb<9ZTdO#e2vADreUWJl~~q~Kxyz~Yg6zkGPCuJ_i@h2O}gox4a?MA zi!(4nr^C0We2pLybBCQr@rlfmk%dh;A|16uqq3uD9LO-c-q*~`z@}iguey^;oTHXF zLp_p;0*$wQSHuz%mpYnuAn3NIjlKvM!I{MK_669k(@5 zc-fhUm)iJRP(!)m05Y*<< z5A$*c8=E2I$wDtk1)xRrx>J~nij68Kayyrq&E$}o7;Gk{9IvX=&B9W|?ixyA)fwX* zKN1%d<29*pnNfrawTS4GibMM`PU0sR5uFZoXi%k6Ok?~Zy_B}1 z!-u39+{`N;zCBk1}%B%Om2 zg09qp9^UI4ls}0Ba*3`Cuv$|f;GV`7GFK_ne7&BKVz%7dv0$5NVyx11(p_1eI~iDp zxu9LdH^-9hZfI(dTeqndMu(U6igXO=xzozt;fz-gtC09EYU}SBiHq%s_Q7oyjM(IL? zQ(;BUmsS&LI$eNIpWZ-7$}4TR~}cFKe)Wi-#aZUFI>0EfZp zo~O(LJcEpo51OD6Gp2r&u7S}VAOU&ep|GR!FTC+gG_LmWgFC^jp_Xq zvKGA(Ykt`T8Y%+OdInpaxoYUd7GWp@oGHmyWhiSxM*BH@w#lO{gJDJH1APQz;bG`b@#7>!E;0DCAm8wyqmq>Ti#y&J+P zO00Q;8N;}n<2=m*RN*^tLC;G*a8DFWq$r7s9;J``h3hb;+gn~Ln7HCAg=$B)Qe)HE zoHUgC>Xo39HFbENO>VQ86DkXbioWR~pS~XOuxy&q(DMr!=NGb??yZts#v7yNQegfS zYB`P*)nBL?B|ZX)#H`*K=0blBUq%&UY=HE-ih?XSVJ3_GW!)5ajCEU2syLMdf&=5k7h*-7hPnFtRe8tTsU z`KC~rz*uIB>m(0zFj)8Mc#q@+U0c*K;d;W(%nHJo@aE$3Xh1i_WL>*v4K$vMbNg(M}5&*KZ>y+-%BQ3T>-FWd~m4F49!Hc3(gc z;tI!aAfzL0RT15ueq=QaC}5Z(0jg+AHu`X`RHuBj?pnXm=@weWdJjau9i&YO}fpnEhbzcv3Wd&JX9TaV+}dp zI?(7D0|am0-dc;~MO9^7+|DrPxp+9tJbc<}XsdAKi9x_4RtYl)VFS!62$FVv`ic54 ze9qux|Lx+;7*$jIZ5%-j}Imp&a5FVP5(J1 zwz83^aM1IdDFc2GMCU9;B~PC`02FOXD+CO#K&J_4LQ!z;VcgD>9V7lf^+uF#(X0U> zBfuP;`fQ^9GM=TaDSxdb>Ka9d(!~sa>wSrFjNd1z=lZ-Y2Ok@@$Db&$1wL%z|NX1d zT}$)tD}V_!`E^OOoTeIdoYS6^Mt2oArqH`5{cLwG=xipT|0Q2DWFj&`wbPt%v=dRB zbZpZ=N_g7ftS?Q|mGyD*{ajtN1>XkX`+MYIwuIMjt(&fFZ zawi3}GA%oW@Cw8ZSL*h$KFw&KMPDG4^z?NGqL^nev!WLv<>nMEq0duGZE1+2d_=^} z=(1twvSvky2kW$fY{F&h5-BTjMs=vq$>dwuqILY04ol6C+7$9wTDD=5qUIc7#&pzW zKCND}&Zv?y^q9%SSK1R;S-Wjq%zS%2vP>V}@$lhZsYKhq5zxMPu!@k(r0>6f znRH^y2;9J8RWTT6B=>U9&ome%imR~Z7_o1%6lMVHkFXm`PlbX=p>0y$jZThg&g=o+ z8!|g_@k(SJJW|R9fzu!BKD2555a0n#6fYwW=x@v8*d3eUiPAH2c*THiK14@n8spWJ z*2JifNi8#F;tE4(;FgUqZ%QWKSCc`@ZM!>z6<>G7@j-0p7oadG))$k}yMaHTxJ<5j zOLbMpVWyeBHvny1bvDA5pGzS(17-A3E0eCqv^veRm@;s$=#?n{25m*CjDbj)5mZce z-^@8SPr{~+R473WweTbbWs@PezI$4yLvAzO9iKeEoID|T%IVaE+L5`Itd6d>7zY;a z{&ACEUo0Tr)Wq-ox{v+)`E;WVf8)F1Ug_X@dovW*=k)S&S=Q%uIv;jBpboqC33x1$ z<(*zc47E2r?<5&VX$0~OT7_<(fN`?$V!Ry>P?2-TPO z0NKYVJ_6gUsTu>Io4O1rt{+ecZ`l&wYq~BdFB%?MF}?7wBZtmkukVcl5Ro5Vb-Fs; zoj%7B2ExyFL}_him#Yift4S?ktFiI`K{E!;+St)LU&C=Al|h4qch$Ezp^xO8W*#}r zc8N~qmn{U>nGm%7JA-lt0b+;~IKuJ{PHfjGC>)Ou8ffqS?2t}Z3CbwSLB|JB>f;O4 zC!A9|xcSLJ0Tb~7j9x_3rTpu|W0&HnP0*b&-zNB*t7$(jpI3RcI&MKCpbQnYu5Rgv ziE8FJe8C^k@R=%bv&sCZFW_J42Ws5evewR}IC_zWKiDwg3(j^C*DP7Ei=K+0Zn%nt#emuHeBsLXN%J1N1 ziHMvZ3~>R4i#Z5a)YB~7DInV_4aJ5mOv~gsbhhC2zW2%T|IW#=|1o=bokLKypaaFN zgdq29I|B>C5^WqXq*9oqPNa9atjicb6w%@Kx%D~~60sJfDY=axD9kYRw!ghzWdC*l zO|qlahZ^w=Czphp&L$@(V2!iP=sh7y!N|JGWq4<9D$n+|^6T-wAFACTkMgZAOUApi z|M*t*`(VHHbMg9MpCl)ad_xu!W47Nj>2CIZxG$-b$M~LdKYU8k&-p%SgTMJ%mlO15 z9ZiFDJ(i;jZEdm2SrTv(-zrgw=LI}V#Z=~bdmby}?_FIB%4vDa*0ez(vbt(Us1gV| z6Ts{qL{(OoE&wMBQ!w$T%4XVsQw7N#0I3%R@pFIMn2iTOahOCwpcei{nTyQWv0Q1T zO^BN<1@^nF@``DC)%Sbam$yvKJSKP55E?s6EIUhbJ2_h|u!kcW70yMgjx2%i1%-4E zYku2E6^#UMyYWc8T1Y*OnV9^u9b1h5f0Z#{!bIBZFkE1y>YoJ(#{qy4GrO z2oJyGHAJ~4n7h*m!mZ&q?G6C7W{&@LFksHl`I)v#ka8l#1d`aUhgpa9h^q^ba9p!( ziBJ(Up4Va?1J@k^Qr|--$-w*5#Lmb2$=}EMx#tzFcKe+rLIevU!X6RmFKA^faW)R- zPRR}r05%zM-liXtvysnRHea3Fi+{CTanXOk!y&*;k{{Gg$mNS_Kv{BdR460aa3~Z( zbDYAYPF<^N(iH{r=53zq8I1tZdh>Z0(bd)D%b&$oyMB$J3u^=@*xhi%$5Aut!@<8M{#NyHM1cY5)U1#qRKvhvQEKa*20LK*wz=OAo-_qxf|9t7y&Nz{fz28}_16GesDGD$9)q?1f&&?E zYsaao95+Hg6Dp`zcRtAYY$k*?!CjcQA|TQXBUq(7V7f96oCz|WQbav|R@9=kGp4HS ztwhqoYP^+Zk>K!+xi>%DBs472U=5K{uxn5TjaLJdmNp7LUg=7o6b6AVh17>A?TJ4l z`tPR>JQn5j-rK@GDCBRnh1K8U%sk?xKB~ z8E6g8^WC?56oPct`+gAGgx#u~(MYQ^1H_C)XWH#f0HE-E1L2Idp(rZ#iNaoqj}~#_ z@y6M9j=_fY;v8X2Uc)U;2633*PA@u`a$|0(e{rJX(uQ%S1Hen%yLmt7?z}dq1bOmc z^YyPgC{LB*8x@!YVIudNEHI<+sdv< zC+dvI(SYgnG#X0$XW-T7(j)$<27rC=m5+4ZT@|=eOlDHr+;wXDjYsL2ZS0>(o-@^#%CAU+9*R zeapq^@nH0-*8@B$Cu8mW$zvgA`E-I_ID2oMtL<3B(yAF^Y1$lXNZKZ*;Cf!&DZUJb zup$kDCH!uRz~z_sMGM^tm#$Pva^?{~QEnWcGh8PQSGKcy00VJ=}}ZZLsbKvkYVK zHw|-=(b8)K}g>$I75`xQ3OtuC?352*=`MC+OgyJymEre!{3fwin-I&* zK4cwwv&@vavFrvWZ(Y-#_w8QCWPp`NMT8X@j#2~xKF>hiuz}&PL%Gl#)?Y7fgFKU5TbmO1zDlOp1*$9r#POAQc2=}AQvU6*lvz^kD$ zf6%LtcG3%jm@;ZLsu&oM17Sl%{=GX>x8wiX1Bbu)o(=Q!UEPi$^o%p<0{cV)PiIBN z0wS}qI;@Dho>pZxB2`{+l-JMC=kcMs9j*7~lP3C5F0}mX^yacK2SXPTYURK}(k@?U zxIP3NANE~S`|X9OqoWU%Wb)0o6uarlbGmv_+=&TFB^SSp068v8#OMO+^~ntS4Rss8 zPOLs_7KXg!YJ}_OHI7;jYU*B-SzLg*N5+DHS^mcMblUTLSJbtIr4f;dAeMG6(vPrv zFbL{g9F{Z$;{gY@DE@oMssTPFIxPh!Bt$yjKbrvS+&nIAkd=HL+w>ycg;_l`tDqJQ zqon9iqg6_wlYS67_<)7jr*ht02uNr3-|WWw-*5Z{o(mNjkX+ZD@OY{;XuQ zWS`}?E5lo>+z~Tma-u(Rx_eZaJUw&Zlo2u(Eq!*DqclRwLXlMyr_r;qU|tv*?uUsc zEWDY}yZoUnL^Bn4qWn46Q>5fi=YSvcqd;w1;sP3hx}pIrc_Q_wQXpL1?)2Yir-bw7 z*lBkEsda+B%vaBK1i!?ieUYRX5%v)40S$<%5193jpE&%lD^}Z}bJQ!Y5)4DRE`mXt zVG#Bf)zPiY#!r^~YjG;*%~~S?dw123>W6W$5*O+jpv0A= zJA^(g!NCq|ND)%Hq*1!yNh#SehKP_M5-$xB=ewMxrfWmHk~Ayk*b^Woz|9t>&LDTi z#;i7$Dvz*_b(@F`QrFF_5zyt+OD7ovcFEnw^_U^7R$jrnTfZ0cyFh(!*S3*ZJ8@rZ z9s2Bz1@g+g%hYt;11`+{5$X=^`RL|`%5I3u)anP0EB#~`jYOD47zH$!dnN?1Cz8Zx z%U;Nf!Rc)5C0Z@L!cGlZx~@M3AGlZhY}3(@$45Y^Y!h;{0m-}SMZIj>uVpMb4vEGd z1NQC|lIAMZHk>C5*nwU4it{|@awGgyk=L>o4f8%b|1Qt~_2mWtb;#6{x>8l&NgMOj z0>>eDtD?9`fB8Pv`Nv3~G3kMc8p(s%m+|~K zB4{~*w?GRU5XJWiJ`%l*Q@(RjoGgqKSazG#Fk@BO>-Y9A`*^?4%wPF^hzUSmj42XA ztmBsN3-Zdz6q51I;D!X}x23b*_g5=PsnV6=hZYr;i<0eqmxsP3UQbGs!{t%X88ejz z@yjK+LzG9Nt63}Ei)uP5gjnK|@Wn>=+ORXby(G*86w4C4#2@FJTDrA_k{A(YFY#Hb0713B4j%A4QENi47=sQKV3f_V! zxR%j~)=n)l04IvzBYVQz^GYjv%4Oe{1)M=Rzo32I(Pc7+*B)dsbCXM?&EW+pKX@{w zCpSZo=U`;~{f*KZ>FEH6Y8puE^VOt^0Aqxws@ml9yOe4Xb*)*nU^%eP2mZ-sr0&br zSRB7atcbs8S(MgkhO7f=_REkAqs^{id#CEwSZv^5-hw8=TB{728U5MKBZdA18K_*0 zIRcC#EfMI)AeAHaCB+?$VKf$jFfyetTrcR%qt+mEOcR)7%73maSMvu!8}?6jy{4nMKT@4oSt z0Py;wni;FUtK%k;meg^DQ?@o6VD3S^p?Hb@g_E@?QfTK&zp<2b2(8TiW?Bn>g_=_* z2LOK&n0P+ISV$SBiBfz{nt1}v*r;c=Gy8r~S{`+-l>7bpUey2jxC+A;V)s0x!eQJp zAA>RP8C~5x#CiRGQvzno47)ygk0Rr&;R~Uvwm7d$-6`KM*!cE!P%yJh+au6^vux3Y zaxGhtal5cm=iG}|T%sU0vg-)#7W;SLVhR2vD)J%K#P=pWCHqPp{`Dk?a+ff{$7?ln zq_2J>zt-UH8BHGv3GOm<$H2H^ZKjhNNTE$_%|%YAy;HA|N+_@wKc57iXCjHv;ozka z0!-4yOWam!4&P?lK$8sZRI((X=zIiR2>ro5{$a61W?a`vM5TnGf%HG}WZGc31OZ-@ zL^UvwcTn1qK1Zqog`ubd-M;)z`y3=BXr+iy=msO9utk8#r?biOCth`Ys7{S#;lsKSh@|VJIx;PqA z{Ojc61ucpK(4nB+U>h2KlBrphvDhvXD(kwRb?M9)`g~JLE|`Xt&w)%ODrBKehy>)S z@}#vhxTSOvsJ?wc17Nh2m{|iBx<>%tUIQ##LSYEWTN}Frk|4?gmq;Zg>~aUEEuv#r zB*W1#g#%*4q)+$JR#+h+L=h>5H;6O++&Dr|laj4g*d8c?QMg3OXBO+PeDp(}H&B3W zOK4e}v`LawY+&`_3EVcdB$dBMfb?)2>bpM=yUfa$!6e&&LM-8@<6x4ZMqlZfD_{x<%F*iEi&21$s&HNdw9&q9gxz)kIpB;^o7nlyppv*1hR zb?v)@d3uEkVKjmYf+$J*M;(xPXb}E%4<}Vcz?7oG4?!5Wgr8A#toZv*U_BDW9U{$_ zIRxm_ou~ctGR&^m?PI8|T0`;{RRkUBX;3`A2Wr9XtyV`I@EVE$&fm{DY?E>+7=q&J zX_Nbol+7wJjum>$$~c1?Lvy6Itvoy@4>sJESV7E6l|s#46yZOM2!sPwm<}> z5OEZ@lzP<_Ry}Ftouw^aXQvBk3#F5YBVWf+w#|T41HGS3HnS7->+Mf|pwneL2?Ssp zPkZ#KK$WLU1SH=vVneUAJPFkNqRD!#k1$xg} zf5|3T*$K!KXSBI}GvGwElVT`n+1%nr2*KA%$WF2Yh++qbC#d638X1*l%`SHl`w()S zO-fMRs>cw_4xK31J~m`;gyK}jf8A*O6RG5$uqW?uS_0Xb7~)g${#n@uigR*b3cdJ? zpt{%QjypefuojQ(JIWpuwdTvJb29Con0|!hWJ&A&}%tpw3 z!u|cjT~@ct`*{Wr@AuRp9A^l>2EdBO-F9JCRhWPs%+cs3A57AMI07?+xApC_FpzA* zYkVh1?}AbC*fVdPZGJc!a~0eq$c7Nwu>yc(tlz6hQC}~&%y3w^8239o^CZJL$81Qc zj)02dOaLyZXM!P^VZaQS8*qcg*Y5T@;I(^_yw8)ptFRRNQW8Z>1lURl`AA`p&&1q@ zk>p?Pn5Hqyc!amg(B!d%w-Y+Z{u}*QnGAOr&MyP{JDgQsKr(e*u9_oY{!FP0A)^3%{x~p*uHFk}Cf~P33(RmZCI&N!$NiOf zt$e}UEV;J~f=Mx)NGqVYm(X-vV$lN26GlcFSuPt?fF|%RCk58t>X^E44z$D5#KF>O zLZof;LdCr!aSo!n0>T;CIKy6&(KsWl&-Z#CzE?TN9CD$+WdANS9}qI*@lma{p^_>h znSZhAudHl`x27wKt2+;t-YT87SvDn?dcD;P|Ba8n-kR%glKvo7!f*R)D13`iv3-I6 zP>+$@#q8xI7DS^pMmrUu1Nb*!VKZ7R4^=TwA%mzAR&?+(zv0^I4%+GV&EB|jq zW64G%r-j%Ke05>d1@jIP3+>o`!oDH%p!|MNb0-+pWE@B7*5 zuTYe7-;)2+?m0Gp_u87LXV?86`mQbkjGe*iM@Jb7%qV?Um|5oDlWr5Rt0A9N+oO6o%@`OrW*X`^W=b!Rp?<4>55 z21wyJu7v(vx30Z@D=&7z+8$DJj*mX-g|#H;V`K%>%mMt`AKP^#z6VHctJTJ|CST*4 zfmrIEPS<9!vDCqoGOQxsy4hY|hwBrkRcx!IYHl08ZO@PMvKk7Zq}YT*Dsq2-krYS` zbgNihe*c{55TK|6=cfYUZYq25hVe~c>Axz+t?cTI)cxM>QV{lA)J_XVsFD$?%bb=E z^yn=o00x{CPsI4UAPN?D0oh#wm7*%5ty3^~!QSS5zl5*41yJv2LGpw&M>WQx6d1(S zrAIV9{teS{a4E%MNnvuDvq-Q?;AmcFW?&?G%<7j_d>chP>GT^aH&NGdj2?t43NCDY}f)&+4=;H z({aS3q89DRkg{N2fG#b@^?je6;%n7lHSmE^d|`_BuG1lSVn(y2oqIKjKRiJ9s-YVe zIgVE&-UOTS-R(Q7Mh_E+Xk4H`FlRx`UkvSfU;g@BZkE071p3_>A*97|R$(U<6~5MS zz$MF}ZIAuBa~16FY8K2&kS@MiJ8CQJx6j3D=&hRC)K;g_Fq@JVji&n44Nz(~1H;7H zqvHby8J9}l`aN)`8V-FucMvGLS6v@uB*bUr$D&9ozD4dDJ3f zPgzsElKy^c|HAy9Mn^Kj<<9l|jaNBQsn3Hn)7&B~#8xM0rrk&@!AH3pVmG$H8bi!V zZ*mSx+tQ93s^aR`w-0NBj-uSu<#>p|MAR4N2_ET$cYa=Zwu%wQ?|r!|;?L>vi^Cn9 z4j%`_DcmqBnAcK}mKYf=G0hfG1l8SZy-{`dnzD?r6(%hl<`Isef=ltrL30$|9@)tL zrMLJqlhIpm)G_hFwQg;um*HQOoaVP=>VXe@j*VGkV;v%P#O9|>Gny5& zjZ3|lwCJ(_GA?tf2#e&J>d%x)0wFkq?h)5nE{+cT2Fs<0m&LQvnlW}@(zIF6`qW^h z!6f6*rSYTO?-C`rq_VVZ4`pI~%x-*Op@!TkK#vV9RR?dq4g$q2h#?Af>&H<)w) z#luG?8oBsIYYFD&0-C(dSH+EhzY$^_o$-P=NH7pJ@fjRK(n~2FQM)0!J;mT{gYF4% z1vkScD4{qBA2h$r8DUP=%jiKKE0J|XYNIAoYA*Bvt%UZ~ z`%Zh*$w7tTjr+aK8BpfXH1yn!ZT!xQRrQ9ecZKrD)Q)$FWD*X^FC=yTXt(hh%ue5@UL9>)8)w zG+rgU@a`$}+Q@0X;*mc4lx2k@e4MVERS00a@i$c&yb&!&i%8FoJT`T1lz*d47Sd0bg{5emXWupO&Ylx0XMf zm~^9N`6N+{kkw?PjNJF})T$EXU&0$gQwXBcHp<4lyEnKJ1ipWa9HSo7H01NBH1r`G zp`^d9)qJt~&*zLSg*ql4SUMq7I;6f9+cV=;=-a7`;l^cnicr%DRFVh;-ZK?Mkb;tF zw5=5dA`cA?b$-qplBoUe#Gn(=F|*p#rU7Kp_>ov-zbJTV%l5RYAkS9^4WJeaHpfaJ zO2^!7?1%tK=4lbF_Xkn@#R}o*+2v^Sqq^@P%8xtk|$ykFV zp8{@SQgbKmg=N&$8~-XDA9q1KqqHY5Q&bjM)nYw#%9tNkikXMZ)YmB5VAU~pZsG`> zIt-$?AusoCdFABKla^(Q-aB!AV7P zvX3HAt4lo15<8`2lsmdmE*tO7LmH8hR))P9NFxsbv6>lbY}-KJt?j1LoS`2(h#FiO zjt@ZmS+wsAG#aHe8EMEkXyEM){+m3600mhB#qm&Ejy`fjgNX;B-RQjLJbRpzB#iFt zsm+QcDbNfmR*dQZl#R(@LM>n1h!|j#u`2{TcAVJE8ga-FIep0>;yF5pGc`F(kiv`21v7XXOoPEr}zj z_TvpDqcGwP<(Gd&1;jWCXdpp?6pj@B^lqU?E0~q@S#CU12Qv6>MnwV=$*X$Z*NvtCo^>(Sha(fcRUiNtN`+HBXPbdHRs2P{DQy%rXc)Y#b6(xWAICQ+(R#qkd*|mMn9v1f96OIo**0rtq z%ky*hV(a#Gf4|>VHMBi+lF`MiCzC|B)_&iJdLp`*K#e)N{{<$a#?dd z&9mG$uhQq^`?^^}&C0&GsIM>X+xe~PrEz_#`t@@%}Wv=EKPoNgT)i znS}S-y{Iwu7=+KF!|1e`>-X!|n8+qY;}2jBZ70bd(7^sWx?+u5}g8UkE?Qec~sPM;7708w`G^(YJ22z?iJrHuI;q%im#g=A5Tww|C;)}{j)Il z_uAd*yKCtF1V8Na@#f`w=thdam(M!dCnK~D{&(!hy|?4zxrnlx=YvO6|I=E3)Ajl_ z&-dmFeYVf_^Vj3!=dNt*v+D71@#X#X`~D|S{Bvu6xoq3Pt>oSNJ-w2i8_!l>zYEg8 z=gN?aqU|-$mM{0Wn_v3H`})jo zYlXB1kVC+@m=w(ZofuY(`g*ZUu-zQ3|%vp|pEO@Eh3c5ZK)9diAA z5R3dcbZ+TIJb8A${@B62zO3wd0Q26jZPKUB`q)C}3-5nCeT?O`aO&mdkR@5So_mb6 zj`b>$O!WBdui8v6um8P4m0G5#Z#<@JJu6Z;6xm+Q2vLj42 z6{rXhzb@sNUK`cy>XvA*6WiNL)EgdYL)k4$gZ-r??Htv=NQ~RcYGb@x>xQ2`Ebozj z%$J>VnImh7=ws19&JY$Vw-Jc&-RBIqjhF&w1R1l+EcL)rxT2yxwruicULF7Bu|O{E zaLQs}#nXmrI%I3gfSP?~Ql0fObZ9b`n_6ssfSciC{aL^{8OWWq#IpC6>xK7}zBE`x zKLl%1&YtACK-v;eN zXLmKGx~;ZNWw9{6#A#<=#hn#=U4Be^VMy%ZMVsxZp@T75zL+%lt)`T5H_Nb`psuaR z$d01ejb^Mlz`+>556`x^YSy}$&NKtJ(V667qc#Or-wa2J_ljZWbiy`A=gWw8s@2l6 zIqaU1Eta_8IHE$Hn$YrxWPF^+;5c6!eihj)n@F~xp4Dbre#9Zc#=hxjm?4+Kjy7Pc zUA}#Fgl$vUgSJ|=as&zE=VU$o$xZ044qAs#e#7sm#4d1dsqVRPRh~u zpf_QcpRzN3NLBB$uqtq7B$Y4~hpSlOKH0${o7~bCmf*4D@`Gu!B=ho>Z)#xHZ`eh4)i%i4R-X)debk*AfUbNpJ4I7wwCT=SQ3MRsRz zLNo1T6ontOwX~WYxVCYiJv^I2D*Ovile0QZBcgKP17v-mdqYr+^#&hX>3WL0F&Yg| zJCjRWnQf%wUT1bAnx|E>Fstw3B~(7l9UFaLWlnSS7_ba<}GYybXRb;26UQ}9y(ahw^cBbnZqJd#<<8} zD(5NUw;P+Th=?Yvgk2+pjA>=c2r1=m{#`os$U4G1Sk9g1eaT&S9rQ9p2(i(+L`GG- zYUdIYFA>dv8~J7wd9)Fh;w0Hl?;6!Iczq!7=_%WvPjq1__1QOzToN?>7H z&DUmzBydsi?c7_g{w2rPZfd=sV7r7!{*w3PEdnbcXV8xH zq1_pWv3bF___7hbwZ1*4WI^W|@>*SUeC!X2bsUAI1Hy^X=XwZv^Z>XgIC5Yz_z(-L zk!@HAY>cUnO^o2wgvzit{j~yzC_)tmF5D56D6KEwlF4^s3R(H5MH5Wos`%oX%>}$h z@qY+RW&`nctup{xZ)D`HIiH1y!Zw3u1v%a4P2<)8PfhWlUpmDj_jt+3N(VAJFUEH+ zIE1E!V;sRwJplK#rHcCDgDhu$+eKL;S~;7{eFmG>n(j82OtKvTI(hF2cMtqER4VD{ z?ozsO$dD!y(#e9>{jPX|s~WFK*Pd&~+1uypB$}-(Yw{7r;zae8i-AM6l`61K<0n-} z7LQg(QRKn-3$Tp8-F{%paHM(pIFn`(l*9Y4sIppE3DB++)nc$O$Z>n+=$J@I2?;l= zejPDOJ3?7&|IX-Iz8f=;z~d@V0aijVn9*az%^1hCwerYAANwBE&KubD_rX2gejV!~ZgvXxPd#Kzf>ppo+2DtL{7 z1XUQNGRoCRl8Sap)iI(e6~h#DJ?Xa?czv8w@`!6{As!erk^ZcqVGi+_<)1}bTD1wX zr`EA#p=~kLcug7DsCXEVfB?yuYp81L3qOEt@tzCrqdy4u{vwQ-0H7`?yWOIBO7Gd{Ta(2 zZ^INpLHX#UoQrT2<~tV^IKsN@;Kl(sa|F@T=zIwy^`~Fre?n3W?6}(?ca4-c z!x`8`;u;o{YBk;Q$E?)S8W!QPM4dc`yV&Q6XB`h2p_WdR$vWHScZph{bt{NjSl^Dq z;~DeEKPI`OH+z{LBXvYWIOXp(_2W@GhV&fWNgiUeK?2_V-2xHdl2rjK^hNprZms=C zzzgo5FQ$%&BXe1cJ(1X^WR2YU^;*1HOtbZa55BwEhKD$AGdgKU0Lo^WLxShzyBPo# zKY*A}Lu;g(Q7?DiT3!4esFn}z1WeV9Lt(eg<@s75{yFQ?V1@mVx?oUy&N?Rogio=V zUNdIDi;f&fZQme`-9$1mwP9q>@ONh(##jm9Rs6`>Uq=p{HBXppn}SllXcg1Dr02^$ z$sZk46S{x_o>5A)_+f*`ROwt#@l;uW@@t3~d(qbxz;lYaYsT`nHaqJ0)3Sh*0MXS3v#<_Fk zIC>5XAGzX>v2ATp8=KDPhV6pWQ9m%I~4;?`iAAG_g!%a0v&iF44t#^T!}WB1qHp zfU>IXt&Cd#`pq>cKU5M3jcrjlTkiZG`oXY`_n#&J^$B4ep;!pVt=EAH7JOQf4FYeV zxs0GxL5C*nL=GBy?Zu5(bAU!Kbe6h~d5HkR ziUbDp=yvHa_EV%}Ko0gNii!UishBEzDv<|uwF8-lk-8qi5iy)=gyPXaRZfXmQ7EyF z&?xzgHj}GqEp@A7wHLLLt)?3KD%TewI@vm$I1;31H`0N{@FJ}gqM?9tWhql6NtYxv zIVWT!%8_K03OY`|lWtNCtw?4DmYdYHdhD{Qu(ZJ@Z3~(PDhe4(E0Od*794<^#5A%` z5dmdJK2L4r;&6X9z^qv&3LgNY&D9teqI?gvMJUWnr4-SFz939n)Y+6=7JUtnbTrO# zP4(@=7tUagnY9TCWe9qvG|zrDP|K&TJFVU$&u!C$z_N06Jf+K4uLp4A0-s7Tlj~sw zF}I}8S?u;#DG^1H{|N<9U%<$L@LS`|pd@5Y^FK4JNn{EgBS1}j9m9yU+Pp(e6v+jGEMX@pZFhFjfVb)8YSP2UZz`5QdlREmdF4g!G zFhb*B-nh~+Rq7OdUuex6i>Nsi8Eq5Zi14DdLL?zbdsj`Ke2W|6LpzBAZ?+qLu&&)Z z2J>qw_QvX|fp&t|5MBx4>q@itXpPg>e!Ma0HaQ{4Zx30+7=U2fEFY;V{91|{|A#w` z+70E5DC&Z1<`B)~S9Iswg+?ePLA*<32~3CaRSk^U-nGR-aJopQJwXXIUyn(z?XeGYYu?HXb7PGrLxl{x$*Ig)$`8wF;;j56hx z{!T-r1n}o%Kk{}$t5aG+>zTFrx8JyEV9YpK6Seiu&Kld$qF*VO+h`lK~T0k*DxTw5yk2Ncxx@AlS8lK5$X5vU- znpDt6sO}13u%~#kaQeLCk5c#9D_e#-HPqxM3|uG58zpxR+-^R`T_#xvuxrK{#j9Ck zCg!yYS)WwR#;wGC8;P~C!O=?`*+tcy>CROkt>0NV55sni9dN>E6zvx$ffH{-ThNK58A&X!VYna-~y1|;UWnin#_E1W`oZ3lSkllYH5}R+iz^1M|V8(Juvx2cH zEzH#Z*9GhY*qY!@EBpEyE6YayI%uj=C!Tn!9>FY0OjdG&9=>qP{sCpFO)u@8so9GY#ej2eAvhKvF{zcd%D@1$3R`o#V zq8CgaVEc2pgTI8TwB~8L^&2LOmGV#3l+6lNWfG462f4J#rtC0J@fNUY$(WerX;RTtN_BYRVej zdi>JcGLqO1Ay&%;1B)-!kkttykut^QyE5Hih7+j-&QyX(5ATGq&l>xtyjoYh^;|6@ z>{YN9EmlWGOYy{gvJZDSmWq;8Eu428P#YW5N-0J2kEPnJYKE6gjKf+f&SG^~I5C63({b_+ zQ~t{sRK8$#2whQ)B$SmxAslOMDGpl5szj`JoL4PXYV4n%qS!A(SxQ$LiB*j8N(K(D z>@ab1AgI@GrNZoZIYbkLZ?g0eGm=J0ED=@Q7L&7hd?XVCw|2m6A$nKkSc=J^*5z|i zE^29$I@PSAEd$P?C>Ax!&F!OxCx;;11kIhiU4{b?{1hTqvRU$LCM)EHr_D*V>9 ztLx4)4ml$$D#yu3S>6oUHM_xC2#4iQP};QAorT=0oJHF(TY{05&yF#;WDzvxv72L_ zW|}430@m0rIWf^L($LsLagm7{)Kz1T2DM@tnoY{U$}frCMHepE*?_<-l`gzZ>noc{ zG#-iUHe2+f2-nn9iG0wfb4No49d#90FJ3W=YKq9l zyIOTcjidINUa{1|Skj3BuHizo6*o`C9PuSZ(Nk*(kT^WJ5fvlI zs!ADoQNAwpt@Y_+4LfM=jN=;GQ}4qew@f5GY;;XrEt2y{omfS5V?^Nw!%K;@v7vR( zEH%{lF3EZFAKQ0YIFzH-SdqlTu@ zOb~!EZoqITr*oiF^%HayedgsL%ug%(#XXwD{H(sCAWF0bXQE7wz1l~$jD&!O_6 zWwZ~v{WveRiW}h{^^Oep*$RHz6JqE69`N51!^7nK(<@Q|IYI1|3IXRuiF1y{i*MnD zyx^sjR~Q}YNhA^wtqGZ9DN8Fg%s=k}rfw>3ys`Gl^V)YXrQa9 zDTdBTBJtE;N>FYuXcYHSiiukR4#d5%R_Gyo35CYuBx)(9d+uwh84S_zwSdP3#ZJi< z+G;VHPl;2#7d`+J>=X|`IkN1&GiBpXikEcD@H1t2n!>bd1Z{Q;Y2*XWg$@2TXv@ra z1BE_XNU5RSBx`v@1yCUfCj=-0jejL4#r|)T;fFYfGbt>L);4cgwU2O(E-a>nk6&ca zV1go=qrt)CPP^P%q3bx>d}sw}1>2|Fx5dtLr3Ri=31(jfiEpKERadx~T6 zU3EAwo@=>$l}jd37}KGmnV3jG?NwNMKPW}{ZE*s*qm>oBE}o2@u3UOIz^4+%PFHi6 zFy)e(79M~YqFBL?VyG~Y@V9l*lEy%RDz{jOTCuWX;pa`3@av%=QI(cX%^LAQ`xXRz zVMw)hxe8XSJb9THS&A9hoo7?=lq^oe85!ELTJZf6jge%mw+0tFbn1Y}Th;^z^;5dz zX!iwi3URRR!I5WM!f~G!!j`OO%7lRRu&N+6jTmo*`7cRKt{}6ncsOX^N$R2oo8{ML zeny_cas(cSG4c84{xy|(yX6-2{OjO_Hc#Qc)d3xq>xlS8#VAH#r40&L()kKHr$w8V ziPBGhi8kupg+GSYFnm!Hi=kX=#Go!FzaC4QElaR}P>gicMz)qUP_>C>L*b#IFXgG- zX$@BfyQlDcw|Jutr9IZzTb`NnXZ-s#Ksqd2zCb;OG>i}BP|8c9`d5*Z(hygQGe)9E zT8OceFSx#$)L4YWdmy^B8m7e^(Xdi_VBo#Ud3C8e9zjESS$gr4c~%d3yR|DNa_Lu> zTiWL1z8`n*SIb%JA&1*6$NkFocG#ckt7(E(*bx_+>FuMiKXFILUnyUPb=qam-?ARx zFZ(Gk+itVLi`!REuFEk~b-@(u?Ooj~eDgNnw-uY40vE9Y-j~l7H*RSXACI2jx8EOI ztFGG5UoUo@Ht+kdHu}yEclR!%0>7`0P~y5Kv)=EYIo#@g=iv)<``NhE$qal)6jyb9 zU!VM0+25>Nyg$0D?mBXzYxZ3C=^^&=``*^ywR6M1)~7e|b-RsI*j*N|t#K*2y}bQ& zCHwqB>W2CI?bHJ$m%i)k^K<#Kh@RE&!``Qz`}6DT)5FcTx8?1@;<+A^ z!a6M_iU=`HLBKpC&)5C__W0@P%-)N$x9dg!e9@0S*VoI%_vm^G$X4+0JZd8PG(F?3Qod;@TG!e)n7w!PDSPcCW zOpK9*4@3@tL4hI_-<)z0X$#>LV7nnVkNWVlM^5nOB&D@vjuFn&iW#m(D#JnJ&xijIWQ{= zsiJjS`kX~lDOws2xyy2lDatAs4q&Cc3IJ*(Nj!shU7?9pa)WZDCZr0LT77BcmrhSi zDQnt|Dy6crnZyKbVrJ%f$qr~|sr-}}*%n>>Vi3Og^g&5NF-bEA(j9p*+0wQrY!mu0 zsIT^<@^C6!8oj$LTwR}#lr~Hc!k-RvsD=xw8dva!$|}9O`E}#TU8Fl@OM6T6Af@Ub zZF~5V;yXCYs#%cwyDqA~#itf@`<>BmkwC-B6x*+x%#@UgAk$AuOi4P{oukHQwywgy zc0lIROVi-SIsh_!Lq)@rbM%Lg{zqYNxalR3+6C)&Ki4uppUIZJ^NTLW7r0gPlq4Xx zN-e}=T1m*e#2T4=);asjS^#*<(K@un%+7j5t>jsva_li5{zIc0+T1#|vh6)?ZRl}0 zjfKm!I|7lY-z)PSmsg(@p@0+eks`HlH)j4!xXzwfH}v`vaDDF z02iK7-VZX(rnfQA=19!i_wr45Va07(;-7NC)xn1V`s#PasD`bche1MJgasZ3a8%zv zNY+EP_ISog4w(ay+cO8Zhwrz>I4_n1QGqPaMpcnZCK9J;p7eW$F~Yg;RSN#(9YA$* z6fULcOInMV&X4zZfp4ELw0*IvL0_#L+)A1L88|d=-eg+#9UW>{n=Vw~HqNKR{fn(7 zN1zG?SqkjeiX|Axfz400^`q|+Jr3bppI>y-Pap#L{uonq@DeG6$RFHV@u5;4p4?YO zMrDswL$9>fhaFTr>?|1`86A8VFL@cli?;O6)3`Mg=yCGZUcONj)ELunXs5b5VX zst@v?=uL;HnUwp7-nf5`*8dB=%>RSlNqJl*v~Be>0gWaK7EoyLC@=se6tpVTUr0`T z3L_@pF<0graMddM4Ka0HmwA`({7)P${-V`f31QTbRpMNp+n$r$_oa&qy@;Q384Wt) zzR9kMP)t&)BS-B7JzbnSo00J@qNc@)iH}8ArbXNRlbAeYGb}-UT3R}m8*z>&tg%Ki zPUPX2Q1UU2mWSLb5gIY#*^TWg8%lrw-z#<%Z+Cr*n(ia>mlJKTq zCL;}m$Bu=oAiAidVcmOIIQ2=>5aN$T5ee<&%_}H(N0ywZuNW&<?q~b!I{v-iqy}VyY}kfUy0Z_8HQ4`H!AO51C|8R>}M$S94?b5FpQC9p{;(QapyA~l- z(g{!P5*E}tqJyEsoa}H;|At&G&Cp|8lBC9cuf%Amj?fBLs9vwLcqN|bkKS`7fxE4a zyPf+C*>24WTiYNUU*!}u+ejWBqS;O{s z^E82o`{ZG+uO}{a?{-UoB2sU|b8}{4tNQBwq&t(o;>n44)Oyx3|N1oe!J>QO+o@+J zi@^VQNe(UuCm?uVeeq|-WoKB~ANtJfT*q=naQF%hRoeQ8^-B0~Go@uy z58La?(XYqYHpBi$A_kZ|QU;Qs3@m1Ibf@f)J0$BI!`Ndz6R=7%MQ;7pjwpYgpgTQl zEa<>GadCGUjTI;@92`_nE>`mXxigt}Zzmc`|FDsN$cs%!8H4SErxYZEB40$+PO?z( zU!U?r+Gm@qd0*$~|KJ(BEcV211BGKoE8#jr7EoEx)Bxd1>kCFcf1;&OB{5Q_;$nu2 z`Bb^@znraW`z^5R`~7h8CoYSDfR6^V{RhEs+X3i2)~2%L(_sbI#z;YTh{nWd7h@?1h;L6SF^ zw;2gR<)LA1$vB`2x~an(Ow{iRhIJIQxmp7l<& z1~l@0*jF*Yi+4iRM;G&Vud}o7A=ZxMsksCUCJ*#ypy7O^3y*jHIX* zUDw@b?7jn59}_`eZskoX0-E3AUURdkRlm*wj3vc$$ z$W~~&)2+F`-D9N(rd$c1L=2xKj|ZWGl)=O#Kd7E2fxBsFK#PG*Uz~5@E+W^?;r?da zChAcNT8{yd5?O3$TO$lGmXzmW|1}eyDjsVcCW${jAC8QZqGUF2nmweaq=jM$*UsGs zjFi(DyftC1C@ zek^L3lL1uUXlvq2Gw-WtTr({+gCHoSXIE%qA&Lbd-G?qX>mn)Zv3izBd&+!m#9u1~ ziNwfI4#U|)+lnzaPK0Bs;_LXBseTeLMXZ7=s}Bh^<6Q|G&YKMe8jJHgjZoq!awq*4{OU5WO)6co&FMwMYlPnbYf&u zyA!c?h|*3qDN`vG5$%yYE@e0szp*eygUHTLYKX@{gblBe^%Tl@0OcUu2U$tI8_jr% zgY{CL%NJGFDc(Pp$LiQzE$+aUP8V&D>Z@+NF?CrDsuh++lbs_p8qq5ys#c)jvnyFt z<918rC|Jc{mk_Kq+$Zm`#S233kQ%hT)@)mS#zQMCLMD3>D}gyo%xOpTT=~;q_|xOB z{HR8OY$D6AdRlnHPv|M4n>>Qw-(NTUYn5zclcx{ebcoAl+f;~}{)j5_Vm<{&pz-_W#9z8myTgdKcPWgqVRxA6UeL-MR4|9E-tzj=A6 ztIP;lPIeYcr93cHrJ4pqqtkjBVvVW7vWdGb>MX%a_lBJ|of{~&pLlpENHP(IrX`kV z+{=rFT~$HWp^P1H#+5wd^0@^W#}nkJ7fk>iT`Q5vBcrkRqnVYJ{GriKHadS<{poe3 zRUHH|re$FSUwIsq0)!(UB&82ZK|xNg6!6283+cQDOk)HH}W&krP^rA&Bf-B z&bBs_zS4A)Gx(5!*PLsfu*LH%M5@G8>`9>%N(Gi=Mlr+TNGQc> zQC!pc>4S&E4a^i4sc^N{o6OX5S9weWrv-2?3$o5M#6>=k=JjxGWgCBR5!9yT*3 z5GdJzzQiCBoYDS5bj|Jv-JBrXK~KUi3kIKWJ^eT{qHoa;b>U{$UDTP zBUlV7A>wZaLT2yzQjS>Sk`A{bH2m(W^`$soCt~rDAOIF5)YHPCyTP!<=ZGj9`1G=`()Hvn*Vvl-S%H z;f|L%7#n-sDbw3buKXfg&+7ev3sdhROqSH*twzVXqYmWA%cJ1`EqUOdFUHyG?B>C` zeRs$nNY-l}K{@{cv)}$M9`j!{z zk-6j?1{z!a9=&P=`aa4^mkA34#YvFb`R$S9G$JkV1Fo~O=HWP%gfa&b0cZhyiF?#v zFNU>)ve2XX6>w|{#EO)|BC|=zfOSta=yBF;S(1{C@ zbc8keV06E*8<}Fu=O@w$6{XT5wn!9tFJH#$oyu=8(ljpN+XODnHNad0Lu(2EcIBbL zD~estP)uV7;JQ&djm8p4sxgHWiWa<#)UZ>C7Tqb+#Tw43mC8~o#TN&xi1d)2J`*Po z22}a%HJnHYfAuKEErp7kUCQ6R{+{hd2l!EEw34uiUGL+;`dPZlLk%^Td1zb2M&ims z$jh&|ZguZUfNjYxdO;Y|t;IgS+JEr3YQHTxEsK1@n0-0NXL_Ue8$1!fjsfh#CWqyz z#ZwjgbJeXbE$O#|TQSGyAHXqlxw!rPMG|k=%Vhg(EF2g6ONxRblo6rAr(4LBm+7Ai zclMU%4Z$a&qRI2jFc;U;3?RDQuhy@X*YD*Snrkob~4+OV#P3PjaX(wkruT*k4tPrP2ThBFBGK?uYrl%{?$BPyU6ZZbr ztHT?8y&dn+=Brlc*u}r9Rr zM`$noad+$HnZB5@G|gV(Si(<;M*@EoBpV6={Yl+|BAKk8q@)tL^t+FTrRzM$T`rM5 z5GGUPBFE?W(>L$+W?04z82S_upG;v>=i7Tsl=#A%FSYh$3-@-S#!HGW|8vS+cw;A6 z@_J$8{aSaZikg^7h*2P+s{K+-x}*vgb|K7=cJ@A*^u~5bEE=6R(w+$E1>|tV+OR=Q zTQ8hRjyHJ^Yevz%@BM~ zZ{br!y9xTyQN%k`uX0m(xjdEER`2TYqs}xbJ(H!4wQlpW#`%4{+giB3&D=TCUW2mc z8Mg)&H^dv%z!GEi{IRpglV}#C{yL~^CAD!%+^=M3+$2@->Ad>Fwno#c{U!0E1UpMR zN4{)*!n#2ie$3ZqYERvAGUibX(oPU#H@lyM`+WPVF^GdON}AwnM8XwEmA5X*w3u$UsZVN|`FGThZyN7OdUlLPQXFV~u&R3MpyvwJ_$Z z19wWw6_^|9{t^z?u{0JDEzHE;{0d7if>JCkAoca~;< zS4LwI97x=iL3~txFvQvMKwOIhtIb1>X#f`>ZJcJm=&6hB#m=ciJQ(E%ERTRXBbNr< z`Xyaas1(0@9ALUL(n|iga}dX7Y{F5%gpm@#oVt0(#lu|N0?vk9qTT{!_?7-*i2ahK z5n;|3Da$NPVz+?v$WVEOdvygixuCjmR^539U35wQg_-&%gd-gX-!kLV;HgL8?WL!H z`l45rPmFCx+)TFTs>GkhGsb%UNNBX2aryC;n&=A-YNT4~6D0@4q(a-SO7uW?(i6A6 z>9Gy|(+txklT;r4DR?Cm0c@UDMfZ;C`c;@mgvgnZb(NLOdCH#)Z#y@~WT8d)Hm&hj z=cg(U9NyyL_1|>Bo{=`FnZ&4||Lkv14S=Q{4RYOJrphvOmc(B-{42^+*AA$^o3kCb z?%CF;l=tf)C%=w*i*&996guwTUW-L}j@0sXd+h47fK6htCs*+j$ql+}hKH4`S;o-k zqH|$Fe6x6nQVu|Al9$Ze&LCKDcBlBgGm^@}ZK$&P{#q|BNlKRa0#T|o`+Analtwmu z_R|S`*sQlcgI7Ud%P=TUcX8OglMvBJHG2V<_ib2rY^1v(8k3m zvw&Mdd!PBxeuWK-wh$T@32YN1{EiuKuEmlw-9Y^3FSo9zV+$rt&PlX!C`i)DgeNa{ z374eeZnY^nkR^Gs*axEP^zxMEmgY5%IoCwelx4Q#^2w%Wa?J@E_e`?wHi?Y{vZG^T zXl`?_nq%Oi2*3R14%AHZ4VygCxzhD3BkaEEnEF8KXT!90r+4PG+Ew}{m`i(Uy+fYE z+J1nFWJ`dFvCLrigtR}IR#J;!1GFI@4WxC+?@)9Z8b!G8Omrj(juvB9;$CWsF4jUL zGXfUsBO|dPTQt0UBHXB7aHp#!FkfIQ1IxjNV4on*=G+^{DKayfiz#+>a5J$+sp6bP z+S`R56x!{le+D4#RhSXItD3ht-8|K0C-V|$j+nplIto`&+o?2QoFTm1N71oPeQmsS z%ELinOOPMmf3hQl^5kpn(PQX|0QzkjU(t;9{Wfx&m}RvG0~9Xjkf34C6C%NgHU(u$ z-(r!~W>@HG5={bS#ZsnHD%iXvpP+Hg5p-6py26MlT?Waq;jy;n-<2YOvrlusi)BjB3IkG-&wuR;?HE)UW;vu+IXV&|oMB?FHS6+zW%CgPVY;e9PW; zCzOkKwTHr`;4zPqifSyFZk6Y@d$tnPO7Egz|z9*w4rSjewraGQ~?hz{$nvbWV zmGh8C9MPZTe&%}35PWy&(aNf53LU;IOcj5zvT^mNV(|~BFta2@Ib2h19tKm+m!RqH z$y`hs2cc7ZzfOIB3iwsamARKH8Otnyu>w%atV~QznQ5esEOO+H8?6&C6fn8O_r&<= za!g+eV-?D{LYJ4_iAq=$Jz@N4V0i~4i62f1WmL7Yle1{9tYa9O$o|qy!-{F4DBKH+ zs~3lOmw3ZyF)X5_9l~TU`L|L>9hIHl$0fr{%jG~#lGr(;ZQUoBX=^{JwP7Az?QAYqOg=hf$(PrFK9Q- zcp1*$rs!`?q`5GSQtZCZhz;ie5fCOoAKZAHIe5#!iiLRQQh}Kh+*ZXxNQM*yCm~IK z6}Ne8b8r@oQ?&DO+_FW0Nij4%8%xLQvR`wq51(Of_Fe&l^O1E<;P0lwTxO6#VRf>- z{_uTvML!e0LnM)m(j;R2a>DdPE`G^Tt0~!V3k)EL6QKpGftIF=T7<`4Br_r3**rVB?U&qAsBBkTQ&e$)=Pn`R^ zoSnJ(!pp`~TK?Y)GEE^HXO5KUlqMyI-n2NH&7DE=WzUG;#brCq%3P(XxiV7>TGhxB zr3RX}%1jf(vv1k2?%M<0-I-n@_9y6-uibLYIB)bhXepSjGv0iB=Qigr%ZFbtXru43wSyn$F#5{0wFIo?Kxe#pdm- zw0Rp-jtu^IJ-|3D9A7*3bvW(H%j$iSWl`0cBRfk z;dza!n&9%zom8pJsaO>-+mvapoWCwO2gw}37^M>Tu_ogwO?R)%7*=q-*?ovX=&+qb zI(aec=G;~}t}1k0=`T9B+4m##1R|6MrKRkq7YvJK|SRy`0%M=}l zNK>e4n~}@3i57Iai|wE#6}}A9e5FEmi#l!9qZWH}GbOvoV`qZ)G3F)oMz65g$21Bq z%|3)kL9{K~p+#+p*&iVIqt)ZOyw#;$Ix-ltLJ2QNfvGKnY zk$&m(#wLK3H`|c~mYin)e(tK7FtjIA*31zuO@XX?>(wZHt*UoHOL<%?IqrQwt(Z1m ze>BZCR20B4)q>v3a^Ak(fWe)N2^W!bvPoQIU`{7pANgfWX$F`y0PE`KuyYWh=s{so zZySxXurjn%Npe`1wN10Es&ABm2}9GZ07LhRSK+e|#nT<0J`?vKm-r^k5 zW*qbv4tA=xg8{5RlA7Of{ zX|G{7cUJ!xKQ2vOnK0|zq zsW@`-x2sm}RK{TFwlpoY6#q zuH+P`x}Wv58i!D=g>lyTea22pKXWGhT2dU7CoS$$OXahTF)Oc%niy*XaT!R#i8}@nXH|O_{HI5Gb~-T@ZPCdNlv-tL2i}EKv(s93!;IHkb5?(%Pvj78CcK zq%r*iYq;+eG1%3x)K-3Uy8lv?|J+}O1AFc*xd*x^e?-3*p*h2<{2VDwMV_ifi(18W z$sjryQ`Uvyat_MkIJGh{sl9vJuL*RaG!bfSN;4D+qDK_IK?O{Aasfb&>3P0qBNf7V z+p-0;FU2djl1qta+Pe5SO953YtJ+dFOcK{|@&ic8SC&L** z^Hr(ivVowwVAKfwgTUaj4> zU!%)++sZowd+v^{-wP@ZhAaVmEals0{$DIaDGWR`5WOCu+ydSQA|&^SR|Ja&+)__% z4%vA;tyzA{-}j&yhVLtJm$;Z4ZoL+Mcjp4RdbYZ+n=3g4?AQFEkXozsZM!|4w>K~u z0={>E_nG18*Zm7IHD(E6Ks0p_jQ ztq&Ptu2yY6<*VBAS$ohxLL9lb#n4~uh0_LwPbMTNs4bh`v`s%7Q_K1Vp2?XVk)3|h zaMoZaW)f9kCqkM_a)Zu@@t+8X9tw}ZOAp$MEF9Nh^_ka+JJZ0j&7kDd%2I2P)p0&eBksr`>u^cO)(X71%_RI>lDiYe{N_4m<3>r#bzG^A@t4Qf&+WK?O0M zG6?TUr&&eSn0**SUdIo}=6KzPSEz}1L_-O=gPFA#>fuZ=Niwl?8P1{=9}r^c;>Mlp zc%)Ho3Z#<3P92P5mzg`5MQKxABwVVlHDF{^@K`qyg1R$-O?M|NbE!d_XtJ8l9xi}= zS7U~z#(c)5!T;T+W$$ow#@p6;p%6SsA2rw|NcTSYiiTg1Zc3byg6=nbAX&qd+o4n` zs|uP>xPwl~!lmC?p#bU4uIx)K1Uc2r`M(h@T^u-cEj$ zd^|Y3j-GqZpicbrx^~z;XiB=d7S>5^;@aUXP^QX3#yw-cB=bj4Q!PUV+&$4`H4zi0 z?lj#(wkGuua}})>HEc&I&B!bS^}e|Y(fm@#r7NsM2bAVGP>PLu|E;^m8k+v@R?#*> zp5w1^3`?o-WNk=1+j#wl@V0IJ@-V%2$*g#`0x2|H(NDF-h&B^95o8_h1oJiivMkth zqXGzp(;^d*6;& zYhG|YM!h-7Sv$aqj^vhJk4h0SS`+OtUaVJ$Z+tg_gn2;qY48mLI%AB3nRGwun6m79 zO=m7pl5}B1ZWOjoTF*7*s$@%*5E$B}bW5N9^vanH-Vn>^d2};56_S#&ppHiDY;Gsb z2D~{IQ-0<=#`I&KcA?qCwt;0(8m19LXx7Ep!j5ctoJQrbr^Qoi+fhLhi+WTnj_~O0 z9RV|DV7~&mVJQ~z`%R-0gOc?1=4^W~yfT$ttm3T36p8K}IWiVz5?p0YTV!!pR5X6$r~ zO@8pzwpMRaVWT(x?0NjyS!sITS!kzzbH?c&N{M zP#5DPXALKL^aJ8Ti zeHsA&1ogeBF*A5=9QN*)pD@%L4(NfBWD*hMcSwQ}XkK9YFY_w3$bO8Sky`p08N4Qm zX^_4YdyY1y3lLHMd42rXD!Mys0g!#ah4A}H2>EZX-sQtZ11Z&bd3xdEfX?EECE(#S zpx3+`ewi7?G$?Vtk#gbJ1Nwx2VHq`dDuot*J#UjT2#syD+ZmO|)FbgZV0 zc>O|xOD)6w7#H@py+H?)Y?QaCohelra%>0@jvoPoNU*#?s(#NGOIiJSbw&jxtcIhE zsT=Yf|BN1vVBsIF{R{53LMcRHPYEiG`R4Qh);QTSX`tDY9(M|ZCqsAEq-UIR(R$V- zDC7b*5y8h%03`sjPzG_`kYJ-J(=RsT!`}Cin!l zi4z9R9_wDT=vUJkZG=Th35cT&;fEMjg(M3Ei;{RLq`2v9I*6+hkZlYGTQvkpgOh=9 z4<5bHpJRs0^SCE> zyE+Ra@ph+;IuJIHdpvM@WhFp8&;Oz89fNEMx^>;QZQHi(?$x$!cdxc>+qUi1wr$%s zZ-4vV*b#f5bAM#TjH;X!F)E@mD@Ts^c~w79iDWL;lc#R*qrzDvbT5Op`N+wP>d!w( z_LwQzWYnP4l`ih>wmp3h*2G2fuGm+B<^cCFna*J!iDQI)PL&a2X2Cn?fg=rqskq%u z4Glk*+n;A{5VkxecZ8vcU4bpHF$76VJw1h$)HDEyAb|kyYspqnVL!^sD>Agj-x(FH z!Ee*>+NT8$an&m7f|zmGueXGAB#bchgkFFQQN(Dd)f{tyJ->OO$D++zTc)djz6THV z^Q$EG??@Q(o-yqno!t76&k;j-Uu(ll4d4i5cwiq}2!bThlr;fu*1qT& zegEed&e)k-UJj`~8}5p~X{OVg3p~ms@kgLX`p?nxkkyr3x6RJ`d2*y*%vKl+-Bdn{ z`Gl&``bek+K6|y7bj+Re$G#o?!F{Xx?3h5_>ox^MQ#20s!nrLN+^0a4;M&*x>d-bK z9#-e<>QKBQ0~?<2&im=r)F1S{uqQXDVV~8ZQ>Z13l2Y_}Q_(dhdI^tn7UzzdwY&`2 zilAFu*{0=-XwNsDGUg3eJe%#Vmx{&ox!1&!Q}c-Fy1Kc$em+*Q0GDETR-YIKBsyp1 zq%2%%kaR^7zHV%|IOO2k{7-QpJwLUMSj>C~lZHRkou`RKGM~_z16pvWjrc9x>zA%~ z6DR!H_GyOwfClJRs92am_iKwe6TlrfYu3RBAUd@Jk246oP6tE(sy+4KbtzCK0H|5D zJyr>UNUL_t3G=i6fzdYQg*;`34t}|Ur&tNj)^b9;`yIT4*Szte3<2ICV{O+fL<`#{ zfRe6vlN0FK)x$+BtSF@jrdES76TaoJNxMMlk!?|LnG1eN4VHLy9lvtxf#uY<`@MwbRaM2q#3&7LbS?;UGzjh&%>FNy_`I1O+#N8g z!q$7*%;^pkAc{Igp$-(NYc;IY8Ed`xTKK;A-I59i$ZibqrF*UdKV}RpMH)-eKjGT4 zV2to@hF$t)M-{5^1~leMSP7L?U3TCRZb5`B9e85wL#*b)6|qD#;R7!TZws&cYE)O2 zihog#JC6TCig*}=dQn<-W7Y$%Iow)fhy2{MNRiOhG3C{b;E{ZIPx&N{L_$veik!A654^gN6{iq<+wSej<1=)_ zn{fM1IU+JH{?HEXF}|f@sirc8t#*Guju~=isMeTVZ4j#wDxB+CMKl6xK84@D6E5sx zw7tZEqmKEQ!sZf|wG$aLCt_Nf*Ntn;cou*^ zc@$a*$mb_xC8@4jGg#z@^n@P3*J`)p74Q*dZM8>M1Y?aGgbG6;0S`W(3|=P>kCrm} zlo9TeuP4M`^{HXuzANU3^j+jtU3`&x6Lt4ZM1_ z{1Ay8P=vHA2tc^8zG{pTp;@4T*1!*@$TS6Q8LUGFsxhINEbibrvXCW6Mj%|6t{ZV! zEXzt$smTfPlzHf4sr$NqIM|}kV?!a2(e4bW4Kv2B%L-@R!>gDqYE^RkAcfwcWh>MM zYR~eAsu+DgoG9~1ELTcF_gSa-Ok^0Fwn?fk`3TaxH zG8DYuPV^W8M4I=R5uO!JuM#nfgJ~aOCO?nNLX@=+UL1lD?;h1nV~+$pz<%zqAf19{ zs3YoX@FwD(90#^+z-7-%n%^7*-w-0K9Jc)6sWo$Lx1+t|bC14Qnnhav^IKXj^n)ul zm`rL$7O5SMo~0d;NbH}_NaJ!OjVXy9AoPN&t)ku@a`42!bf_UXHBU_*k2n{wuSVEP z?;~ODlEFMG=e&}?;b01syrYW6S=@R~S=c8v%V3M@1b#jH>4ju*UWsY^vGevF(cL#Kww|G! zU<3gtRKu_#a7IvrJ7$x^A2?g^jVjlB6B!{Ur01gp!vsLWNl`?uzZ3|oD!|A#q!@?- zfTt#1<5*Nb4~#qJ%nvU~jT_KJl5GmQm+8rLa`24hxZ)HY>{}oNP5jBuM3?2lZ+x3d z4%JzQ~r2)kMDlcm8pmqO>gZzg}nnF2-_8|0)l5!G*uL)&UUyW zMpJ{VUnH4vrDP#E2|5UNGo@#!-dd^w6Yej{BZ;QPeeC2SoQG`oo3TCOHq;q z&t-;NWbW&LW^n5EVlGnxJ+hq%`L?BOmrA<8YgLPX`{Q0LUI3DAUqqO7I+}U7sK{I+ z#fPRKDx2^wcW1+HIM}h!cX%rlQ_{?^`>_79R$=^}je#bUC6E@UaxV>sS5Dao_Z%#2kPA2@lmsrLxur0{c#0xa zoH7vZk%B9DYZn9-^)@=Ynx62 z3x4w=m7`E9F87mz*HV>VAaNH1f1uj8J-eN6;NmWpUv6x5z8???)jGv$u-YrcM*mp! zyPUr!T3sB=q-$$k^w{#W*T21XF8`Z}1*=}Cj8mgOkBZt z+vp^34QBG|1pNFQoD~xbO@T#cuv+pFSgNvhBUo0xKbvCdSla%4 zeN}(p+v)xo9K3x9bQ&+5oXXcJ6zWF@z=s9MkPG7dn8AZ$`v2tn7&8;mZN2tc`hN7eSa;nx;oI?W*gKVPJ3Ewr75HH&8uTp} z5LkUC=ESg{1^#YU`&4_0IgiI!n2p}b(diJ}I1FX=I{jm-8GgS>+SbB7C*fLkIlH@l zT@b%TkJAjW?ntIgS#V3dT8mB^w&3+IzqyWLYcJxET^>!@V%bHlf#o zSu!xO_zwbKir@*PIPAU>Fmzt^o&q?rAAqV%G?8jQYG>f{BBXwV5&-C>wZOX(PKs`U zLXm;mCVY%c!pp}8XMdd2KVV@B-79H@$&=^mzgM|C7VuD$@+I*39Sn4Izsp^5^ecY> z7f$8W3nAb{K=74=LLfj0Tk#;6>WUtPK|+z>eK#BvP-W#Iq2kP8mLOb#wLnC)i4a@} z>fBHajDGhfM3Z?lp0Pd940N!cUfY5xD9k{v?1wKDZ!oe?xb0EsPJqg}%pa1@a_di7ghB zxb%zHKb-gDT{!ZG&gU9Ab4h7{)Q%hsg2KvoW!_Kg!w;Du(V@Pid|%Ha@at;V&3L|x z->2iljar9>GuAN!j`))pvEU7`nhXV=a1+Lx)lZ1tiYl0M;p2N!MV9=PY|8{S_fWkp zJ9G@={9avmuU;R+h0!PUy-%hC^k$k?K*kIx6T)wr>yUys)AJLi$Sz-6QSbBIoir&lNz^UBa zIE{SUn(ZC8d)htXb1wj->e?P_oi12;k~lx|vDD>vyDP0!HoTr4j~m&K&6nA&oXaDD zIF_ZWq&0dV!Vsp(d3;e&ch3BRN4^$H;h{254E}&^T%>v3j=bczs)) z&&H1z{x0w`W2A$1G9LfZ=o8S^KsCp|E#!^nF?A{c$v{U=6)9BQ-igy_S|5kLc3edr^W z8N&y-K8$siRo`p_X5#|^P?@;pY<2u7U7WX8N9M+-;>-PH_O1+CeC0~yo`N^6bi7Mm ztj+iV%;GVT@%b=B1kfGK4M;gIkb@LU2Lmf zJycczY*>{#f(N~n$2qw;5=ttkoVEm_pK;Xr`CkAOiA+-D4Mm%+z5(b$e3BkN+wuI{ z()?jNhIG?*a6_{8&fA(Ix3BmBGUv&=w&wA`*Z90$9ReSO1&Dp(KpSCX|?r% ztbz0UpzyNsqQU?Sj%Cd}yN4^hwI5npz&B(IbH}Hz`AZ{R$frs037`O?>gZ~~9SLnK zz6pHYwVZl0@BlvQ6*lj{(grWK>~jr_H}09LdBN`o@A#4Ex$#>>HWKS%#M|m){o__D zqn$q+Q^1TEd`5sddlRp!i#da#^K@zg^e^hep6v_);Sg8*@D7tkR`;teE}atvrCp(A!pZv!a0(~D`Tx|D&YnS?Xz5Kf%P8_fUe6F?k z3mcc(!)qW~N$B#{O)I@N=ol69*xS?cKXC#StyUibP4 z_f21ti$OQN*wex4&Kp}@Zg?%v2Ex0S)_e!Y4Atj#{Ufvv093W*r@I=xj~lzd?al5l z2%DP&>gvuOfu38B4C*>F1(8S(+$-$uHUL2&Z2E5VuSZI(>U}K|Rj{tGLt>wjr&P0Q zD>VWouvfIWR`ZYJx2Y3XLBO33-)}jynSfki+g#pGAm6^cjqEA3$O4SWpNrBUzL6St*1)N<{3S&Tpqgt^dHk)M>k{Mqdri4UUb#yMhQIMD43 zZ6Ydkm%;*qUvLzO2b!a(A!<4V$!m3Ti$+g8sgCph%%Nhpnh|No_{p|73*y zMOTiXh#mF$x!l0fM?BPM5m}cv$SY1&{cQbe!2C!mQ;*MSWNV`t^?#mRpHTRs=R%>V zx?bqUSjzx+hyB>j^+)AUxfN_MgX%F~o$gK%$R7=7sm%z)yP_h^<5H5rNWFvrJ#-Ox zoYTozHciY%in&Ht`iobK?{vxkEWm!#MFD(bRP#I%Tndpxk%rSF4ffSPd!JS!@a!(- zfraFiMlm-Wv4vq5pra1h+7}x~4Kvi`0Oqe?1blCSgTslIU%`0l^#Q1;#{H&G3(>fQ z=2FTwkr9DDoV|LZUM@WOcYn#UGZb2nYG7q_ZZZt9vuKJ6!7jX`?DuE2!s?@d;C+Z8 zdrg2+V~!0e4RH!kslc4qi%u+#B=YO5%a;hM_0BIsA9nmOrJ_xAA^}#8U24u`0qThd zz=xKpivG8ye_j?2Idsy}c_1Be#_L8mtOnA-tNxLV#&!{qbEh9v7m$rgW{_yO5qpc9 zI@D^$4bXLB^+g!o_6d4kjUT`KBTe!^VUcNqe~7Rs&|#hnRdk#|>j$(t4CB+|r!F_i z4|s9A*DpN)cfg#Q0Wvgbjba6l5(BtTeQGoh_!@<9>C*V)qGd4R>H(B^0k^F=wWnMq=_~VoU^sQIT6ml%Uh?K6dx6Wa!G|@^KUE)`#F6D- zF2-w3itAp8MNM zIHDyh1Is~W+54RMD;e9e$@W~wci?hlU>fxzl|G;B`T6n1k3qtEGW#7DXs2XEfHW!FJ) z&DWfYS-Euk&*2rp5yHvyC&Fw2l#4mXeirC6Cd&SFT-;?J_cQc-18DuUA|PmxEK4)K znEaif9S80!={CQ(`)rLB=Vg%r2#IUk{!|~so4W;_G67ui$>Hz{h2!>H5tk^GYEj!t z=L_ib zq_db#XXpEp4pL2!a}A#-^b~cp>falFETQ?4@ASW~l%Q|KS$$C&dJWo-BwRd#OF0qkJ)Wh5m2=V|95EsZJX8ddQvL`M37QhVkpRz^R-+0v2j`@QD3U@N%%(>D!F&TKAJ)*x4SITJ=+pjb0D< zI1Wi_i0)`-+&$L$Ccs6YYd#t%<)1<_^-Dyfz{N{ojSOH$AUG|DK5F2%uDgu9irX*h zh2&`8gE_S=>c%^S2H+p(llQ#jH-ycS8^O#lm3`5`(2Z8#M09X9;)DexL7@B4l_OIJ zSqCEgBOvb1V-#>zno?A7!sn@tOm_ZYSwShJC%n%ViqQ9=hf{(Tx!eE-k#bhXai>y} zRHfJ*Z;|`>%CQ6q>sARhhvq3>MpFW_i?Yv;YC16lgd?b|bQUdIifH{5Iun8wg12bc ze4iMBNSKkKM(g* z5b*oXqV zv|XQZSBJvKpF7-KJP+-x=Wg2mTpd(H`-&zv@x3BocEtLKibBl%M6Yg^iJ?D(+GcD0 zuCw@1WR-WWmK}Q0#HBzMtK1x{9ztJQ@jl%zzDKSuUN%y9LcmOP&W?p=1>+Om$6Bk= za}k1pe2^HT4RNnQiIaOfb}Jwg6hOoAZt||;NJ0*%B+1T)0uq!vU`V$$^2cQj|A`jQ z;#J@jRRT!IRO5WTZseR<4EneAQ>?!d(Ef=vigiHHh>gT-l(+B&J)dz<|S(9o#{FxjQbz?#Wom==KIpusS@D;VGu|sY8)wC z`RkPE0DX8Bk9?m2V>$^&E&Ak-GLr`cVqV1o0*9-EG$(vI0YuKYmM&R{=Q?g|L8w}S zS$ByFE$L6#%ko>pj?p%2SPVhRG5z^pqP_pSy6-<{jhz2F+1aSuSpP3^AGH9SQrGYG z&|lRt^8e^(;bda-U(&wpI6>$D0fgWi!5@Qk&l)u4Fso3SQ#56>cxM?xvs6==j~7hC zWx{}CHs%{oyEOf!By<-gH7XXUTO9N>q4EWw86eq_D`Utg>i`SKxiXMV)IKVlSfG0o zQPot1UsIV30?5&7R=yKw9qwjAaiSFsRS8rJjbtd=+>Y(2*2*X7;Fzc1HCbNgeqPa* zUUU8o;Lp;%otrINH14Kj$=Isyf>E*^(pl3ZjIq}ZIOOrvmGRvbu}QPJzH0FMkpO=DxCX3V>NLI z4U}8WJIutv&29@>zaJH`F&b6&Z!J^O;pE7PsN|-&cQ{NV--RUnfSkw_zjk{G;A#Ej z{!1sL^Cy;g%%L0m*4G@tT#!$i{X){QNH;%s7$Pz_ zPp8ieuG1p}O^;x0i`#R)3P8{g1~|kSVK>tI9!MABR&chj!8htExJu~Tc?Zj;_I+6 z6MbNN&XiksGsbK})N$D})7pdo^_2c+|3i)*9sXfu42zB@z>|iJK36rdar?`q)5G1P zBYl(n7h7h`mtB>bd9?Lx+>n(^cXM5mc=%}1-p%{;p_}`&WBD(OBolV?#Ief_$Ij#I z>UgP>R&5N(=fbu+@#uZ(%&Y7BY~UPp)0=f$R!`1s;YzE`m4Di{k>`T93Y~rd z+#{YJ;o@GANB%wjNnK4W|4nD^!IINGjXaX}XK2BhDbP%vj_qYZg%M_@vk&2>QQTt? z?2aSXWQDi7tM11y*(Q&N^8!751FIxjn=f;OT0D~mMk05CGr!~ z8c*QeIf;Ebpz8k>cwEf2}&@S}ERB2?v@qtc?Y^PlD?OAq?OB$(WCZ2R$;@CHkV zpr|wdKm6K+?K!Xe`=!hwM_wP^Kyr`!eqyrtf3f<_7(Lt8D+goGiJ@=t_bZhfjk>vd z4Xe_2`Bx4++!xv43MgP-J~v6uIsB6?3$ckK#?NaTDhWCR%TXHrJ!q*mCzTq@W!w7C zqgW-keLgVXuF#s$7(N_w@`&q9U02IX6!z+-f!>PmIZ~Q>4 zxt0`#Zm0izRJpKmL4L#5jve^Ol#XpjrX>H~<9}`K8%zsi>k6kx@4Mm?^L37+2YRP( z?{mdBG7d{|{A$oFwTw@`Vbg#nS1kKTu+*D?hwDjx<6VHuN?$e^fj+V#=oM{=w=#mM z^*Y#ggerR_$4J>aX3T|O%3mxy$}sAm${K4f1jeU#YQ+-UJf49*xVEI4Q94J_?bc5_ z6tY|2$!!e*rL7{#`}}uQlSWF{H!WJVmFmtEGYd!x%l@;bmy?rDqym<&&YdyK%6P7s$yGCt-9}9-*8oO1&{a!JiUV%%Bw`8%LbvBYHFKrq03lU=%NdpU%ky7#VT8Cz>j>>lZ-7SWI1~)+c5n`mt0)!$jo|Cljg5LH1+gXRn) zH6+UQ3fyR@n4Nu+#OSOzhaTRZl~gPO;&6t!(k_5{^7%qJEm#vEI;h2f`#-*4sEZl}=K zT6K@RR{GP1Mb(s!y`Lr?hR>X2+L^FY?5*6E8#$L&mV`sPlM+-WjK8w!< zug2)WK(+G+3o48!eq8#z)%k-M-uYDwow$1;dwQ%9L|@1LJkPK#3b(YjQ#!Eg*tOsb zL*Y-nHioSmYPhlt>W$%30w=CtE=-Nsncgn+w;{5xSH-N^ zwwTfJM+Uvs}e;dxe5AfRKRjzFuA4@{avrB zkrz=Ju7BZ2Uy^QNLP@RPc=(GlTPiOAXCxOvcW;c!cH%{Jt6@>pSW>}uA$Z0^;Tdh1 zs#(l*(UA(oXBPn%3wLnQ?GRXJNf%6uOu&E z9(hO*tpIjs-W?AcxfGj_wUbE+hwy@H^|&<-rD4xgg`G8c%kZ6|YJc4A9`B1;cfoZ@ zoyql89%cb2tHLThtF0?aAn`z{#mnA|#}o_wQ4o_(4ReK`xl?9)m>Hy?e4_X@C8l>@+6G)VWAfLlhSe9D!fs#2>q!5H3dcIA~0B=KMd zro}4X&eP&1rX$iDXX*LK=;wViQ=FKsL}P{l|2EnEI3;-~ucgc^eJ)Ki8WPu=*UXqq zk-Zw8=D9P`_Q|3URpqn@gcU5mr3?`B+DUE(f~v$BKRYVMq-G+U=b%`QE(sMKvr=(J zf}=oUlVIRVTF_#qGTXN&OMI4>g)gJ8bv0r#fIoW76LNuD&d=Ibr7j>;VHW@I<#Ed1{OXUxa*q#ZB z4*VRC*CL6Eod6?g!$BPj@!44!QjeFh%OUxL{=3rJIaguN%uYwD=UB@v9|16XW|q&qGh6IDQs7#)>AiO)a^r4P4o z91%vjt&hA2mmazapHR~;YP8Q|i|q*M8fKNQKb~cLi;3C645EYV+qrg=_5sH=B+rV9 zFoFOw)Fz#?of$+28Ce0uH?=mF_Fh}_*uW)BU&*LebCVhCX~vsgD%Rxm%8rJm__?$W z_}irmOHEHxZT+=>KQ5{3?k;tiQ+dOH9M_M!V}5bEUtw6ps56l8evJNigxQ3kdiz^E zQ&MDbwRU28W%%~CC0pLsu;R!gkH+S95;1jNz{A5G9RQJm=dHGHo`lzVfPN1koh8Q) zpcY_?gg?=UG7hk+5kJhlJ02^4SI>=+|J(m@?sZS6JY2!+QkHWR*q*y&ZyZK?-^krq z5L4g{f^dU#@O}mtEB$l8Eb(R1ZHdTzjv}IuKh+fHl-+a_x^mOc(9Bkzl)j1*c>il= zW_yh$qvZA1Og7h~x*-FlouX_7vNChtNvQJ3rr;ryqpMAX9K}Ra$~WRoS+x|Y59Ex{ffaR-P_ou=~@7T^^gjoRG&;VlqGC6-aG8X&!uY@XBrqLSHt(x;lH-?p5$y{{Bgx5yib`rag*2?sH~%&%$$qEUA(7n18dRhY zH7%+-5yYK8jyH&a0~S*3mCgnQk&!+KS$g51LU#OlPD*ETg6xqQDHV90`93R68tY8& zAh~M+MJO;hVmxPfyOT9ZW--meStqsx1c?j=IK~q~+v#4*k`2F} z8A%-pl4-c3!(W*}wAlVc73ZgK!nQq2VOv(ufYVbohrkI_mjg&7`KuwxLar0y6NRCQOr%>&k z`O?S3Cl;~R)WEr|frZ+;MTB+x;8M2G0!dRHi6xz^A_2*GgF14G5-@m8j$Gj@$M41d z`I@3J5>0G*b+0_BKL6Ecm>RyWp9-Vnanh4nP$$Wy>sALS&Aw| z0+OywB^<|rn#U07TqM0tIyew@ygJ_b{hdmOXm>+-Sl=G%lC!L;l0x7BbwzQ98P9Nh zM{4x;1;I?>1YI(%sBViLz6-XRPy}6MPia^q&iVZq>r2Myc0S!sK3%RgYcCh^8bYn@ zjE8+xgC!Y=f|qkl2Bi7B&E*(-UL7)4(ax|%c{|b_Z;4b-GnClz8^X}ibl+%+i(d1r z1kNUm(a&akPUm{AAs?e_r4B5gJ9ID&lFz1?RBZJecSD0`oeb-=;Di|uz0IDs&mdluNj@Y6 zm#1qgMfunWlS3UavM`}(#p*%aOqh}2T+2Eu6c*2&?i zt_MC2k_2Jz{|bz=_&-Xb#M*ew=h_3G(NF(Wh}P||cAn)5_nCHcu*v2A=SvQ>^6#AP z*7hH#>x!^Si>cQHG*q?1L3&T@Cy5OQ%TACf7?T-gd@6RmuA_{#vu@Sq$j zeSZ}n0W!8*NDp<|f*l7=lEScdMVd*#$A_IT6%bXxAR)|nix;wi4(mwix7CWabm>yF ze<^_2YTG6-k?W#MG7K)-i=!0!IyXG1uUHac7Hca40|NPN$WVAzDSd^< zmo+HLDJ@7$Gs;76z2M}}Mb;{D(K7h^Vm5J*$y)2+!>%|f{`U=4)2tKj=)fqbsbhJwSD67ROuaRZYEoHxSzWpOh0&` z^p^EUV|f8vxQL*tD zw_3gV?ME3V&Z#u86vOl;LlYa3F19&uSBu|Rc~nSaR~$Tf@09M)b=7tEe%G;1DOSD> zz0&S8S(6ehSwlNhmww!C0_yvfreg!BTm$c8>rM*Rt^c)u9hmDmFq@FA*LBD%)W+N% zB1f6ppJlE<8_9*C{a6_JjXE5opj-S{x~meAQhvCKecE``{Z{(ZP!(mVX$SRU)(oddlTfFNq+MK=w2}Ixeo^9yawQ#}+^& zfGF@My`Z=VYFp@%Y|cYBGGjUw*Ob8|nBRSOm&&uY>ulvx1dwRLd?#Ou#*O1c2 zY@=LtgD8kKGvoa}jwbVOO)06}&c7MAhZlStmjbVqofl!OxH*|>L-I1E{&$a-l5$+^ zlcS?i)Ucn5gLJD)GUbOo;rz!)o?lmO+AQf}z<^Ou_BWmICy+YR?3D&|jt~?F1@e2M z0yzw;WgfNGkuO=r$&Z?IDWNkwLv`KuwnHOcuKa>riu~-ugp|+eO9U3woB!}+aE#rX z9nTuv$%&u*-n#iKFH7y~R>ZWlMK8sq;)653E$`~sq*iwB3Ax73hM#}JZTaZ|#C_RS zBm^9lT1o>WxGAqEG%S+iPLCO$;e8!HNN`auC=>!Fgn|Tk<%fXn!9Ju00$6Ujr_c8tEjwYE<9o~Bup{Lq9eN}JH3Co(8D zsCCXoWSE#+JRcA^D)U{zU?VPK>m?14SMS1g&)#d{ix`jNgvHp`_Z+dPydq0nG62}H ze&|EMC&ZXpoA~5(cU<@b{y($b7gV4UnZH@?uiy56?t1(eYPC965UT$deO-&>=vUHV zuaJ=v@CT6)8{Ia+X&o#JWNv9U}e;Nbm$oEo?|8 zEue&HfyO=~E0}qmR)EBz>LQV0+AZ|&{6&MWk*}n4^=tOo_Wz7!tD&@}|2K}y-}e8r zsqtR{>B!1h0WqRYL@hFlNB`wz+iy3oi|CN>Ju{*^#W*PfANloo^ZnvrKtRVX7dE z`U+WZjVk|DTv-l1wIqBt*T8jcUy-9u zPZCb`9SNN@N(?Y~G>z>54bvngX})Tu!KmiNQTH%rT+w1WZ zHlN2QQ+V|S#X(Xr@y42H3u-Z8XWrS-C?7Yhi`T|JrzE|^x8u*X^5GY|4jH z%JF8vgHm^H5V2><$-|d!Y-l3|p;ziuAqrns0}UbPXQs|GQi2ZcF*o6#W0KMnmXbFa zcw&~ONR~A+ja4V9fzzp`qx5P_d?k?} z@Dxi9R-eqxzbBBABtsvQnD992PqBuJv-RIHi+HmL(0v-dPBeQGDRB^E#@<^JD(+EA zntLgUF{i852LPxQBL|RfaJ)c!z}*hUu>+arxoh zSNWjETM4C$(>VkPRQW?3Qcfp)Tv9?+6FPppf4JKDS_Ae25+DHVCh`B)F8+R0HjJi6 zu-mtVl^7$QTri+yUhVYxdGjO8v10i3WizzdCm4YZs0oNGglI<&=B;X9$wY$m!-t8u zZ#`j`*L=hv9AVKCp0liHA%ylWs7C^c8SMsALyMq5+ET-ahXUy-PA`FHBJN|%4v$34 z$WsCgfDq;IW7HxV)Y#i24ULpRyQBYdahn73Z{&dN zkZ@}HcfI^N(&|LT3Z*4Xp~-n>LwU!*2vceh$&p+TP0obl`e~gHYS{PyC}nLE{+7_k z06s#21K7ub5BA>XmeyD`TbYvXm&!j6zsc2EzF;1 z*KJOkdr^B>r|c=8jfR`%Agyik2ECV%L3L-lp+-&sFp+>Z3tCc4`J+zHJdJ@KdrD)j zenUgI>2s-yNJx}`ko-0al+V#jMcKsSYuh%xWFe3D`~jf0i2BJ zreVXVQiKbyJaRz6aW7I+g9U{K0A4?=*7436PN!k~Z`52|X~FDq(Sc)5~!#>A&w+1v*a3rD**Np}C=H4;|dkCR>namxJP<@=OU1iPwgvuuu@(pik~E2Z6R= z&7{dY_2?tSY_oZn)MDkg2>nP;nf$z4&!TE=jLu)W$NJ(33^(d>VYRKK(CWJ#%PB{x ze*S?I7Uq1?hbT73@hF~!Dy1Yh=I&d9fM|de+5;6=DWZzD&G++I7h=2k8-oX(rj9L- zg8uK_?M$#PPA}-ILmFkrX4x*eWl<~a!XMSY(0~UDydVA>^gpxD|Gm!OzbV2tCdL*9 z|Etgd@9I@ImlOb?>$m+kMfm^iXklYuX2M8kZ)+B;X(Eq3y#NQ|T8aV%(z>s?3EYP( zbtg}Ox49M3iAFKBMTwG%w7FG{lDhwX|M8vcZg*^KXX`3w=4zKC!HVi`9o71uIZz9b zrVtQ-Ag{Y+X;xnM578FZzzS5KhOjP_Lcv7qPqM%}O*suDz~Zn0Uj|Xn{ArB7w;6z6 z?@>=wovGx}-MZv4QRPX&nf}?nEmR;-QuUMp+;lBUb477+Gw0$@+6*K>o|#fy{NgV>J*gHPPNsjT2D7uT}u^@I9w z%Piab(>#4vNA@t3;aoXrHlsH!lE!;2Ct2Zwsbp@SYODk>|^AB5x6QwZ_Y5qBA(%-id0TLj|Z zxV*ewS%@oN;09b*Ha50>NFz#J}#r5em=a|gWBc{;>D~v-8 zohM4Av^W7~e3%q@7_pa4>#f>{II5?$NXYKj3-XK+rDOa^;;XV-n*8Coh_1vx8BAV# zBEJR!D$6?E4iC$xNIzR~H?`Sb1~2))?mcKrg+1YaII>}T{6WTBA4R#5RjeU*eF5tj zI>g6D!A0Cn`legEoO#|akEWt0{c9sfh%DtmavldUYweRRvdEw#MPZ2bK{b;DsrlZ- z%1PWP&Q4$h$z>sK$He79xhBw0}!P<6GIMtB#cQ7t76}%dQ95AG)Br zHLpKZp!GQU??K4y`pbCav*ic{&f(k!rDt{`gI`>F zKwtZn+ZK%gmZ->vbl}po8R3C2A=#Ih!j%y+zpt4f#$8 zuP%hHEviP+cZU1g`M$CGo>Mxt$ee%3j;(4l&*@7Us!Fy)g6K-u2tg0Zm>L*m7s$FD zuvY~nW%1}W8#y;Te?yE0I}empsa#kzNjdEZ!!6Uve+ui$<^e9xfB7D1!L*DvXriGq zg|cIfDl-8ODFbf-r3c!s#|{&N%{}-Lf=uu-aTqKkBWV!=W#7Ol2l=qcUbtX%@Xz&o+-Q6L< zEx5b826uONcemgK3lcPVa0%}2?*8peW=C@REEgKzr2KmY9#alNEMmGW*c72HcoV%60QKJ6mq%LKe#Whi<{8qtAOK4SB0n?A#u(jG}Rs(I5CK>`*_#xiXp z(n~q$g zlr(hGw%XT|I7oAOIz~oPmFkvqGD?x6Qlj4)qF?u74Bn*25%kcsTeWo%A9%)McaK$h zlY#mOvM?`~?LP19u*$}Txxj!k$;$>i7j52Xkk^`n>7qW|5YRY2Cn@b%l6~W7eQ>i; zL2?_|&fkvhCBP>)zlS?D0vfN=b$TyceaZmrGIAwkrki)@y56JApL5 z;GK}C(SGsLbqP*j8A3$;WmoOKN9Pc3sS9?^$3a%QjBm>-5cKveU21U0Cm!fF zQ3(n_ijZY47d`rk3QA|6o9@y!hKGhSuw8MLSgE)M6+P4vX;9%?%m8ec+oR6h-JP z(l#}rO*XRux0=#e&ncM`!gqS*OjXP`ZcmhaA702SR04FIc6WOzYFe31ON^OUOOiLv ze=50tFAcks;9SRkE@8lhH%wk4?{+@6+t@a7)5+=X;Du8>Yd5ayNj7W2QFL0x#yE)~ z2~_L#X0zLQDRfQd`{d-MuMT}N)6l}rN4wNlh8$PfXe{sx;u4;3P?z9(P{Qc^^WomF zObA_@oN+v3G%8rZFI9Y!sL!Ouj3;?CsG9Km#^Bo<=v7V$tMa+JN|cgPFWS=#S;SvC zfI{(vB6P!J?a7|OMIrh)hOW@#dB>+`J;!HNxhn?cJfJ_I7;5YGQmSv^Ao0PwE^uGa zcfd29J+09V}zU2GYkj?a_@B*_WJd8b51%c?@vzF^=NyCQqYHW ziKR5Tsv3(;bS`7K{D@oG)w^^`HR*D89S!mN7dteq<#YAhGPm~#B=+_s^e`3#JS$M)+5l_*;WU&CM#%lM+l{#?PG*S zb5v+{WfW$Sc`3C~jNS82j}`VikU)NLra&xIJxX8|mjU913vmVJL1*7b(|*eDyu&^w z)x?+zU0{)UnZB}NRjk5g`AatXvLArQ^j`U3-8o4txKKCSpCeS2P;6}T6;V=F7=(Jtk18DIj*u=M;u#xsCzdmLyL8EahJ>TbWW0|IN=Kd%A5jyZzusjX;I zSO$$qbF-6MGtgTg z5@}UBy$ZOV)P0v1im$$R{+x#pxxrTBY13q7jZt;*6SZKe&vxr%F^pm|*fvwmB* zxm=CA*jryBC2gSZ%)Q}T-=C~-))6tBwDGPZLk>)1O9c3GQ$p3uxA~jezQR^dwj*!% zA+O4Zi;))1lRL)OA``m-WlEo=oj^B`(wV#7#9>B%qe?f_B6|+O-htVs#i#SIjodQ@ z*^+i)3&pCkcYS<2AWT_94 zNuhSK9k%^o)+#|zTM6adRy_-I`0?UBdd0&nOGU6vqD3%$enM+{G*!MP$eTcrqxl8) zZhrUNzFNskfVVJ>8w}TfuLaF00^uSX>G8@5>ty9?t+hct#?(0)EBR1=Nd!m4&0*qB zPq+4*Iob!_LwA3P9XlZL)i7>;#kX&iyTF$4?5#FD27B{l_iZed)Z{weAxpyZ0xfFo zuEuFp4C;{WY!>8wes;%n6K&I9%YmVu6^$%^HBWdn^+?_in5$Cl@pe0TMD-qRsbGE^Lj`5M@)oJlW7ZV3wfcu)oSYem_J za)1_%Q&_t-rNHuq&zp|rvF8y0HO_uRU!kI*pFJrimXD*&h zZ>BHc)neP55vmuNu@Z0*Ha#KB<{46Ws0e(md8MF^)e<;MvjgfrNNtH9*(p2dtQ(^3 znJl`rr{0LhnuiRkOx{|LH;c_FbYqb?mZkJ#f&mlOdTk(WX8BEy4bn%Gql(^>m>uge zt?da~DWz`?2aunGYV>sBnnN*2UO;|4>wwU^P}2$cOihw6Lq1`khhHs0WS=a!Q<>X} zlFTyUrCe=^pZHWJoDg2Q;VGkbAQUWra*L#Ti=m{ucq0~8!+2ZX{|U9kx!+~u=)LC} z7_>NQj={}MssR6-539YH4;^!`Yj@FDN%1MZz3q|QEu7knGISnAnoQ{TNfB$~B%7~{7BAlEa^Jay{csibn4$WuTtEme z&2#U$&!R~tgH%SvRodsxe#pF#nJtGlLoO{+0>^ku@HjsIOxn#O#}GRLWKP_#=iD9I zXLz>FuagUwbz-Z}UyH0ogmEcU?oNM;uG~!#)cJ@LpP+0r;xtJ=yPn_kZ7aAe4C2u1 zN!ebwiK(@aWhd+WRDLM5RBS!8P(3fojFLx|a>4uw!ZA^ml~i_ITT2*KMCXj}1W_it z=){eqYtXyowkcB)`SGY|hoMHuBNML$>|2Zsp|KSeW2Toy`xJ?7qqMkkdAU2xTg?wO zfk}3@i_hIj5TIjF@bzIc8;r;I*OvKYAM7JZ?VhZD{p)QS?nKy>z{hwRCRET28&?wo@@$(}nFgNeNSwqHWvtpzjHw z8hbLN5FrK#$-Xi}MJ0{2oqF3r9`IH>b6qtuKYQhY^f$crD@uK*8P3ypJN87_Bu03( zT53uh$1cwY!s9(~)*Z|!!LmXCvm*l|O=o8iY8~ZuQD*@;M2?6&ThtkI{TXksfl~*` zEZh)w+O)9rBAia^()@6gyzZL~McCXRP0u9zAyU+qXt@<~B5}(HE}{E2ji`Mo;&wZ- z=e~=@;uQ1LR0zJ_UfJrm8*J492Gu2NJhJQ{)$dfx2#>JI2jsB3zQ3E|GPgs*?lMl9 z;<89H#-veQz($=~B7PTaS_vKerNn{rF~2NOQd+D) zyl_y&@Mq|-7rZIQt@?RF7&R4O+)TD$?>I0NqXno%3^G*2pF{`gzqAUdAPcDzcjNBW z^_f^V)^Ru|fuR~t&|$w-$#jr z5o<^dg$Ftr^5=2~YS#EAJD6|%d<(|z_~Hf~yk|=l1$5aT6s6je3c|CTPGGfqLr@%>s7HX(Q^G!f3*O-W8i%;bMq`UY(4rtNRN>!A zupGfI;N#q!FhIymL$v*lFEcibPooU9F*__yRN?`fKw=PT5ym-gwFl*~8~dG$Y+z`{{q5{3-_ zd`uKk-j}MweoxxCLjPJn=C}xC&O=SKTpL;_bD?hu@O#8E--eH};a*iYNsEbfgt!cK zn=)>DIZcW-Yf#AuXq^CVm)|d9g+HZ<;95$7SDcjZun!->m)6)8ang}(>I16NLBX?=bjTUfim0?o`U$|{UDHsit z%1EwVD5>^e2sMw(7%2nAK>fV@ToXx8N7CheVZkgrR!)Y!g-IFiS#iO`ft*fo-#75t zIWk$R9Y<8L3C%^+Ar9eFl{I;EDvs1SFYwCiXx%0|g|%%Ee9{B!eN9+`sKcfbc}U$; zV(nZSi20*QGly7p!3O8X48FiGY)@=`(u)sT$PA2fE?t^vHcUHTN ztXyvA{opE*I6G!r-?>&oTxABdWuoZ0D0GbBf8nDR{}TgL=Fqhb07s<5`6%nBkOc?X2)njMlZbY;#jK zJMnUa!?ZUSWK@S1ZhS#wQ;@_6w$oeT6VI@Avy&Br57Ng48hS*N#UGsEZUf4c$OIH_ zZ;x42{VIrCSKvO)>&8YsOvg6$zNpJ_jvC%3D;D>9S|nfa^-}An&te#oA?RXVWVHccYUEmZ_(CJe z14ugf&+Xdr!%%S6>ML9)v(7E}i}tajcJ0>sLhsx1Qxbjsv(oq_SVu}LRJsYk55w8v zN#F*Ygv3r(FyN-WHo56lh&a6vHMPUu9%?+xP{M>Ks`i0q|TO%(&iA;X^O1w`Sg)gb~MAJeCh=k_}3;}wLzoX##uP|W6XRReo+ z(Zf+UNtsE5>)38N(jQs|A9qbEi$L&X(QeGoCL3Ej=Vq;gid}B_l&(nNgh+ zO{R^@TrYag8S(@#NQS>TrWZ{HJFY}4SU&>6mGzpHlL>mY)JImeBkgEFuf{CsVYD%D@%2XEEd)9ejc*gbN$BagmX)F(hU^5Q)pBRYG=ab_ z!ItS1!Pr_nP;0|GCu{$}y}8RFwAU7Wq`u;|yiJX#cHWs#lp&v>ov~}y^g*OmTag5@ z*D${p2Qz!PCKjJjglxwCR1Ha2d_|}D*=4}XKO_jDxC<}1M-><~L$uT3K|&I}`ie%4 zHHA`(*A@eIUlrQG*GUC^`t-pL@gwSPr)YzaM+U0gUa+l{HO>2OR4$L*H*{kJ=XhNL z0RxqhA9-C)=^jv#S~aGU)3`7Sx=!!Va10qI*I6kf_*oc7^xyM9#u;9%&LR2%y?-|; ze+ZKWbd>LTg6S)ftu|+~safWv12@Sd_0fxuduPEM+JQN{=%bn#zN)=^EfoppjK4b$ z&s1#@K<9cKH0{hik^e5t@;OLmvmO6ty7`zLEo9k#scF9qoDfc9LRQC z(huDgjtTqm#L!9QeDYnK>c9J~XObohCvTwBh%LpayyngfbH=+M)RvoFj=$Q-}jU7JVoK40hoh zBGX6eco087Dl07@u8en%3W{ZDRYgw3QGt_TJ5`L>R;#r-okBOQ49329!kfkj>splK zyK40g#2~m7pQHTvR32j4M@uC?I$*Dt!j>f2Rccacsmu00lQ%)+>WormQYv_uqwT

Rc8P_l2$Mdgad^9aOvNBo|xEIJJoQmT=hkmf~CjtjT6L-w01Lq*0UCcX@) z1QlYY%x=hjg0L=iHk1u7SnH&~RUa_y&G5-e^W(V0$#GLe(!dt}CUXTJEl2iqU9;?> zzB2?I^{y2a3^_jQ*u@ntK7o8Yered+?T$u*hqozLHVe5|CZqgH(y3{wPwxyiwM~ji zPL-VYkL%>G8>h*^+dw~j3@D@S;l&ithAuK5?tU9oniv=9F3256Hi`|%!aL)NLF{Yxd0Y-g4q^r-81yw~^)#Uc#M&@tp z7TxXp`D+S;6_E?&KcOc2uSD46~Ogo!U%Mssvw!TNaV!n9)eJvausTb ztm{UgY-0=j{r;VamtS)oUtW=puQDAsk9n*0nZ19Qa4w`QPTqQ@!X}^*xw6wdq2`FS zza!v7eIRmDF~=nOJGD%U0)*Odpa};Hj_;EbR{O%<)LhKmiL9- zHrgFN9)tUzm$$itP(U%Ors(Y&_l@lw$zzsPx88ZGfy%LXdlkFJWibX|?!-m5fJ?GT zWPz_HCkJ4@50~a(f|+DKT&P!qRB2_}B!+}sJ9&kfdBU zXdrf}H5Ay`FNrwR$G_yD3Y?R%V0u*;Va`_QATirTu{DuJyTRZ1lB_wK(FzT#Hz_&U zeR`j1cnTMRs5{+s5QDXZA3&EiQ!L9WyvkH`Igwv{WV68Uj618brK_=dcX<;#1*8Tf ze-}Z09IX2FA&X5t*rH(q2S`CikXT!qR7(Eh)grs<0VK4X$Q$b3GPb%teuq}m^-T6x z3gQSodkEflnu@qC)6CPOlVzj5$~>E=C6;G;btggH=lor_3?Jy>1?Hk@DaI?{jE=h% zy>fPjt?u||4#o_RO`9BM5&BS65^}_AXlHT_tVCkOq%c3o&WB#b(Zi78ZmaMC2~Xwj zl|z;qGAGCLOX=o1b9))*$vrH-MT^qF{;E2F&w_)#q=Od7aWm#0<_{Mgp6cbO3GAJF zKt5TED1nAYmRYk&VDx*HS0w!+#c-G-v~UA)n|QNfNu(tv;TU34m4Sa-RL zs}w*>*;p?o;~t8LMRaZFeE3#alaP`tch%;8rrdnAqvrSyy<$Bg;&w9Y8o`6BEOfz( zbYrqcqua(n&gn_QQxAWD+&D{x#7n&|Pq{7?Nr3&du7;nArs&h43_QNQk;|NpkWjti zG>F*c+I){Nf}szxU1R%s3J5NOu8Gwh=uXjCvxcYPhqGtNQK#MGWT|Gt3Gwd0r|gCz z)rwWFGxL2l575l$}K_TEy;N}uARD1K9)7FFJbMT4o7l_?mEU!9x=w=i)AQ5tB_&bcAOm z#|PX&zWVw*=?=6qx%ny}Ysb>6C^rq`Sikzt3`~Ziiez1^2qJm)YC)f!Dt|w!rDTuKUFdH zRF~i2ZK0@NY=(>qaLgP_T^Q4te(xpyHu}oL5=Jd{a5GGQn}V)m$J9xq;wZiNRfBsu zGy==$5CWI5$8Ps#!^7}kF761bhvDUEDA@PC335*8>4yP)C^I7gp2r0>8n#tEQ``-M z?M@5rcOdJMu4;nPtt|*F*I|$^r6zgauAZSs~&<6^$zJKC?r#2rzBS2hhto znBV%7l^1yy$}W+OBc2@M*pWl{1BpTf=_i0ZVOaj-pSF1M^HR+9(u=1g;P3qL0> zQoMOLk9NdIFYr}g zR434rf)O>@a^PUYxmM27i_@=eJss?0<5ReJ`zV^e4mukm;B!dpWvZBX2%%gX67>Jv-c^p){8&z95?9c?_@!1DmtQL{qPfy9-bDQ4R!DJ7i6;&>IbGmBi|?^ps&CuZ zJD$ys;{vB+O^Kk;Vo#1b^u6-&u3MGmZ8*!GGThEYDR`S$?_%vNFD&Ci;!jvGGEK8wrKCWTQp4WMj5?u?aTtrWC`v!>r=sLnl#aoX4POwpDc!8=k9v8ouX(j#xL zddt%JYZBLztWV(=<2bYnOo?<;@Ecz9oz{seG;z_oO(ZtILW(bYIO75nftONgGLH&9 z_0MT*YoA~}LU0&8L>FgdIECEq#X{pE6bhoPAK#UEEElMWAeWyKXP9jGI_hDbe;SEa zZbhrz1F_zv)=&&?%e;dDbA3W5`-VshlbXXrj>mHShoV2QXRc)x01+WDO zVZ|t<4l&q`vH`y3-3E2nw_V_i790+~_in{ELCQ7O$oOYs>lLn_!A4F|cEO-jnIJmd z+_sp(4ij2yRL7+viJ-og^bah=`1N+4`4!ZRwv zVz7zO`BMvqhPaPW74@q<*0=3rizqb0UzVT_+{0B<6v5u-gey| z-6&~1oW~m|ZEdXL2vgi&Y&fr0Rd?B#81{{M=`FWgrsbipl0*g~4E9}UAl@&;ZpL~Y zI7UN;y&;-4<%@}y>qZB?I9s-FQg9>ZpgS&3?!E+L36)bt(bA`IgneX=X;J#{QH zcunr43MmXt;3PcN1bdt|E`IPDNna1y26ky#H<^mt)(>*+l<%U}E%(z2#@5tVWqesD zC*(eaO%zt-u!lAvfoHsaNV2uD*0a4 zZ4J%sUSxd%6B6S6NU~l90RsAw9`uX?>fuS^h2m%&OLq|yKVTd->s z&NoHP<-Usv(A1d18BB0fvkJZgsVeiQd5+rhNqfADuQA&pD7Izf!^!M=;GYOEOt~RS zePL}=jU2d#j+4ZM!(U+(ybeKSNJvMVk3C?M(RHC7xz%KVsO7{naeq+Yv^O{l9OOjo zc`IyxnI(7^{jR|!6MhIS7TaTR>yPFu|C~hk2Cz%Nn)UqCp4#)gbN$h>haAww2KOIk z|EqD&AKM%-@--BM0ru5O(+WrYLdLN3o0wf^Rn+E?hLz9uj7;68@~Px^SE$ld)CUYu zw@>+tJRN06$+PmzqY5nK;gPO*!k|3c$CIeYVG%7E6uCZRj0a7dxm>H}1=Ob-NTs=g ztn?xI8B+(Ou!&S+=mQ4X*k$pIQS7QtpNaMyG_CBPEO@VVO9ZU&@$O!IzfBQ4duE06 zbGmtdgi7C!hcLIOLax!_J{aH7#~MZcs#(XmKDA^4=8M^7uh$~X?}_djiDZN=|A%$| zk?H=|x<7Q%1J>=9bF5>poqk0x7BV4@vB4??(}F21Dxp81B4)bm`LPi76^9uAG962h zTk<3vlUwL3Rz*1Iyu78}vG&`G%PP=rJ$)E2xpWv%^_UYRq!}?vSfQODNbYcX|@47xaP+`v`KcZ;NX6v z0nU3s$XV>*Uq#$HmIw(mKM&SxhY2(`Q%`W?tB>%!|Md9ZCy=Iq~n`c>Txzd{&gS@}q}sk)HG7ZHxk1`~r{SnnHTX?l4|KkqjR}OwKTI zcWfMiQWRJ%?piCm=Az)c5On^iLNn5BP?0y8Z0(j& zw8il`W!^BY6z|i)OUQ<7fHHr^ltZ&|52Q2UnawlfIC-1Ii%UQ7yc}*{( zuiAwPB}#L7NYqE_!<%%@^UU=T@A-k!lfn>9g>SkRKiGjjvfOun)9o3G5Y52POh>L# zHqd6qbtC##$c}8TPhW?5N$c5mgwFEe-Vwecf?Tzncw<@?*bDyax9`4xtMgE zbwj_Ai^T2nYSgI=J=b({a!3|tdvV&hoUHHFU z?%&Sl{}0P$`cZ=N|BQCaTWm~P0ERpP^|NA1T>wyNV`yowt>9v9Xs7vOtu2X?((CkZ z0s&2j@d&kL*E__h{8MdJRvN5##55wfOv^8m4k$*w+ScQRiUgSn;>Gjb2k)EDU9nvp zFZCo(!5B=BDIJxhRDq>j3l^*OywK|7V3dfFrJ&Yv6wE5#>2T{|2inBi?QP%Op zCZ&@#f>6org1&W?zc&FNx6nAl-{7eN^W@HWS{vs83ql&iH0N##R4ao+Wuv=r-uLfU zJ$1X+6jGG%*QrGo5pwYy;Mn(7Kbka6YrJ)FdJh(NCAO5CnLf8~d^RU8nh=puJ5G?% z>iQ**K2J$zAuQO-pJZF30?GAW2W}ejiu*2lxIc>Hp#AR46k>dmnfPi#xyh7YFlM0Z z+h8u4<`=EU|3K@PJAFy( zWlzUnwB)k?F4w;#dP(4AdE_qwB8@Kz{2|6m0xuga{vyDW^OC@?wu>*RysT{eMFsiG zKT`RdEdOkX0O$4R_)FV>xabc70QZ*Pm5U8e$!`L1crJjO%U_d!DwhmE;$JXbYwI7r z?+#h38XTaWKg0GJnG@{jt|ALA$72=wpp zKbm^};{VT!2GmIYIex4o0qoC6FGT z#h@=Ky^NTCQ7Yg6jnd2b>AxqG4k(lTTUh*)(0@Kk|5>82!+#+3>zV&jBD6AGyFPj# zpixuc7Y4y(^(UdfZ_i8k%VO7GI|JMFC;Ye4*O&M`H&TmjfH9QhEYYcn{{g0B5X)s*=Kej^(DT}xdICi5LYHJ5d06`fbr8MH2md$?Cf344gUuI zZ}v^X + com.fr.plugin.jh.export + + yes + 1.0.2 + 10.0 + 2018-07-31 + fr.open + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/JHHandlerProvider.java b/src/main/java/com/fr/plugin/JHHandlerProvider.java new file mode 100644 index 0000000..f72e0d2 --- /dev/null +++ b/src/main/java/com/fr/plugin/JHHandlerProvider.java @@ -0,0 +1,23 @@ +package com.fr.plugin; + +import com.fr.decision.fun.HttpHandler; +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.plugin.api.DataTableExport; +import com.fr.plugin.api.SQLQueryApi; +import com.fr.plugin.api.SQLUpdateApi; +import com.fr.plugin.transform.ExecuteFunctionRecord; +import com.fr.plugin.transform.FunctionRecorder; + +@FunctionRecorder +public class JHHandlerProvider extends AbstractHttpHandlerProvider { + @Override + @ExecuteFunctionRecord + public HttpHandler[] registerHandlers() { + return new HttpHandler[]{ + new DataTableExport(), + new SQLQueryApi(), + new SQLUpdateApi() + }; + } + +} diff --git a/src/main/java/com/fr/plugin/JHURLAliasBridge.java b/src/main/java/com/fr/plugin/JHURLAliasBridge.java new file mode 100644 index 0000000..78dc82b --- /dev/null +++ b/src/main/java/com/fr/plugin/JHURLAliasBridge.java @@ -0,0 +1,29 @@ +package com.fr.plugin; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; +import com.fr.general.IOUtils; +import com.fr.stable.StringUtils; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Scanner; +import java.util.Set; + +public class JHURLAliasBridge extends AbstractURLAliasProvider { + + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/dynamic/dataresource/api/update", "/update", false), + URLAliasFactory.createPluginAlias("/dynamic/dataresource/api/query", "/query", false), + URLAliasFactory.createPluginAlias("/dynamic/dataresource/api/output", "/output", false), + }; + } + + +} diff --git a/src/main/java/com/fr/plugin/api/DataTableExport.java b/src/main/java/com/fr/plugin/api/DataTableExport.java new file mode 100644 index 0000000..cfff48e --- /dev/null +++ b/src/main/java/com/fr/plugin/api/DataTableExport.java @@ -0,0 +1,165 @@ +package com.fr.plugin.api; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.utils.AesUtils; +import com.fr.plugin.utils.DbUtils; +import com.fr.plugin.utils.RespUtils; +import com.fr.third.org.apache.commons.lang3.time.DateFormatUtils; +import com.fr.third.springframework.util.StringUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.util.*; + + +public class DataTableExport extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/output"; + } + + + @Override + public boolean isPublic() { + return false; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception { + //获取参数 + List keys = new ArrayList<>(); + keys.add("table_name"); + keys.add("where"); + keys.add("field_break"); + keys.add("fields"); + keys.add("need_title"); + keys.add("line_break"); + keys.add("m_flag"); + + Map params = new HashMap<>(); + FineLoggerFactory.getLogger().info("加密fine_user为:{}", AesUtils.encryptPassword("find_user")); + FineLoggerFactory.getLogger().info("加密后在解密测试:{}", AesUtils.decryptPassword(AesUtils.encryptPassword("find_user"))); + for (String key : keys) { + String value = WebUtils.getHTTPRequestParameter(request, key); + if (StringUtils.isEmpty(value)) { + FineLoggerFactory.getLogger().info("导出接口:传入的{}为空", key); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-100, "未提供" + key + "参数")); + return; + } + try { + FineLoggerFactory.getLogger().info("导出接口:待解密{}:{}", key, value); + String temp = AesUtils.decryptPassword(value); + if (temp == null) { + temp = ""; + } + FineLoggerFactory.getLogger().info("导出接口:解密{} 之后为:{}", key, temp); + params.put(key, temp); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("导出接口:解密SQL异常 ", e); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-102, "解密query参数失败")); + return; + } + } + + + try { + String tableName = params.get("table_name"); + DbUtils dbUtils = new DbUtils(); + if (StringUtils.isEmpty(tableName) || !dbUtils.checkTableExit(tableName)) { + FineLoggerFactory.getLogger().error("导出接口:传过来的表不存在{} ", tableName); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "表不存在:" + tableName)); + return; + } + String where = params.get("where"); + String countSql = String.format("select count(1) from %s %s", tableName, where); + int rowCount = dbUtils.countRows(countSql); + int pageSize = 2000; + int totalPage = rowCount % pageSize == 0 ? rowCount / pageSize : (rowCount / pageSize) + 1; + String fields = params.get("fields"); + String m_flag = params.get("m_flag"); + //获取一个写出的流 + String date = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"); + httpServletResponse.setHeader("file_name", String.format("{%s}__%s__%s__%d.dat", m_flag, tableName, date, rowCount)); + ServletOutputStream outputStream = httpServletResponse.getOutputStream(); + BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); + String line_break = params.get("line_break"); + if (StringUtils.isEmpty(line_break)) { + line_break = "\n"; + } + String field_break = params.get("field_break"); + if (StringUtils.isEmpty(field_break)) { + field_break = "|@|"; + } + String need_title = params.get("need_title"); + boolean needTitle = com.fr.stable.StringUtils.equals(need_title, "true"); + //如果需要标题,先做一次预查寻,把表头查出来 + + if (needTitle) { + String preSql = String.format("select %s from %s %s limit 1",fields,tableName,where); + List lists = dbUtils.getQueryFields(preSql); + StringBuilder builder = new StringBuilder(); + boolean isFirst = true; + for (String name : lists) { + String temp = StringUtils.trimAllWhitespace(name); + if (isFirst) { + isFirst = false; + }else{ + builder.append(field_break); + } + builder.append(temp); + } + builder.append(line_break); + bufferedWriter.write(builder.toString()); + } + + for (int i = 0; i < totalPage; i++) { + List dataByPage = getDataByPage(tableName, fields, where, i, pageSize, dbUtils, line_break, field_break); + for (String line : dataByPage) { + bufferedWriter.write(line); + } + } + bufferedWriter.flush(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("导出接口:执行SQL异常 ", e); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "SQL执行失败:" + RespUtils.Exception2String(e))); + } + } + + private List getDataByPage(String tableName, String fields, String where, int page, int pageSize, DbUtils dbUtils, String line_break, String field_break) throws Exception { + String sql = String.format("select %s from %s %s limit %d,%d", fields, tableName, where, page, pageSize); + return dbUtils.query(sql, line_break, field_break); + } + + public static void main(String[] args) { +// String table_name = AesUtils.encryptPassword("fine_user"); +// String where = AesUtils.encryptPassword("where id>100"); +// String fields = AesUtils.encryptPassword("id,name,xxxxx,xxx"); +// String field_break = AesUtils.encryptPassword("xxx"); +// //以及剩下的 +// StringBuilder builder = new StringBuilder(); +// builder.append("table_name=").append(table_name) +// .append("&where=").append(where) +// .append("&fields=").append(fields) +// .append("&field_break=").append(field_break); +// //以及剩下的,按照这种格式弄 +// String params = builder.toString(); +// HttpUtils.doPostToFile("/output", params, null, "xxx地址"); + } + +} diff --git a/src/main/java/com/fr/plugin/api/SQLQueryApi.java b/src/main/java/com/fr/plugin/api/SQLQueryApi.java new file mode 100644 index 0000000..209cece --- /dev/null +++ b/src/main/java/com/fr/plugin/api/SQLQueryApi.java @@ -0,0 +1,67 @@ +package com.fr.plugin.api; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.json.JSONArray; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.utils.AesUtils; +import com.fr.plugin.utils.DbUtils; +import com.fr.plugin.utils.RespUtils; +import com.fr.stable.StringUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +public class SQLQueryApi extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/query"; + } + + @Override + public boolean isPublic() { + return false; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception { + //获取参数 + String query = WebUtils.getHTTPRequestParameter(request, "query"); + if (StringUtils.isBlank(query)) { + FineLoggerFactory.getLogger().info("查询接口:传入的sql为空"); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-100, "未提供query参数")); + return; + } + String sql = ""; + try { + FineLoggerFactory.getLogger().info("查询接口:待解密query:{}", query); + sql = AesUtils.decryptPassword(query); + FineLoggerFactory.getLogger().info("查询接口:解密之后为:{}", sql); + if (StringUtils.isBlank(sql)) { + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-101, "解密之后的SQL为空")); + return; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("查询接口:解密SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-102, "解密query参数失败")); + return; + } + try { + DbUtils dbUtils = new DbUtils(); + JSONArray jsonArray = dbUtils.exQuery(sql); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildSuccess(jsonArray)); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("查询接口:执行SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "SQL执行失败:" + RespUtils.Exception2String(e))); + return; + } + } +} diff --git a/src/main/java/com/fr/plugin/api/SQLUpdateApi.java b/src/main/java/com/fr/plugin/api/SQLUpdateApi.java new file mode 100644 index 0000000..378d4cb --- /dev/null +++ b/src/main/java/com/fr/plugin/api/SQLUpdateApi.java @@ -0,0 +1,71 @@ +package com.fr.plugin.api; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.utils.AesUtils; +import com.fr.plugin.utils.DbUtils; +import com.fr.plugin.utils.RespUtils; +import com.fr.stable.StringUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +public class SQLUpdateApi extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/update"; + } + + + @Override + public boolean isPublic() { + return false; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception { + //获取参数 + String query = WebUtils.getHTTPRequestParameter(request, "query"); + if (StringUtils.isBlank(query)) { + FineLoggerFactory.getLogger().info("更新接口:传入的sql为空"); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-100, "未提供query参数")); + return; + } + String sql = ""; + try { + FineLoggerFactory.getLogger().info("更新接口:待解密query:{}", query); + sql = AesUtils.decryptPassword(query); + FineLoggerFactory.getLogger().info("更新接口:解密之后为:{}", sql); + if (StringUtils.isBlank(sql)) { + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-101, "解密之后的SQL为空")); + return; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("更新接口:解密SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-102, "解密query参数失败")); + return; + } + try { + DbUtils dbUtils = new DbUtils(); + int rows = dbUtils.exSqlUpdate(sql); + JSONObject resp=new JSONObject(); + resp.put("rows", rows); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildSuccess(resp)); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("更新接口:执行SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "SQL执行失败:" + RespUtils.Exception2String(e))); + return; + } + } +} diff --git a/src/main/java/com/fr/plugin/utils/AesUtils.java b/src/main/java/com/fr/plugin/utils/AesUtils.java new file mode 100644 index 0000000..c35761b --- /dev/null +++ b/src/main/java/com/fr/plugin/utils/AesUtils.java @@ -0,0 +1,89 @@ +package com.fr.plugin.utils; + + +import com.fr.log.FineLoggerFactory; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class AesUtils { + public static String encrypt(byte[] byteContent, String keyPass) { + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.ENCRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(byteContent); + return Base64.getUrlEncoder().encodeToString(result); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String encrypt(String keyPass, String content) { + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + byte[] byteContent = content.getBytes(Charset.forName("UTF-8")); + cipher.init(Cipher.ENCRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(byteContent); + return Base64.getUrlEncoder().encodeToString(result); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String decrypt(byte[] content, String keyPass) { + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.DECRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(content); + return new String(result, StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String decrypt(String keyPass, String source) { + byte[] content = Base64.getUrlDecoder().decode(source); + + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.DECRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(content); + + return new String(result, StandardCharsets.UTF_8); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("解密数据出错,"); + printException2Frlog(e); + } + return null; + } + + public static void printException2Frlog(Exception e) { + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + String s = writer.toString(); + FineLoggerFactory.getLogger().error("错误:{}", s); + } + public static String decryptPassword(String source) { + return decrypt("xxxxx", source); + } + + public static String encryptPassword(String source) { + return encrypt("xxxxx", source); + } + + public static void main(String[] args) { + System.out.println(encryptPassword("fine_user")); + System.out.println(decryptPassword(encryptPassword("fine_user"))); + } + +} diff --git a/src/main/java/com/fr/plugin/utils/DbUtils.java b/src/main/java/com/fr/plugin/utils/DbUtils.java new file mode 100644 index 0000000..38516b7 --- /dev/null +++ b/src/main/java/com/fr/plugin/utils/DbUtils.java @@ -0,0 +1,212 @@ +package com.fr.plugin.utils; + +import com.fr.file.ConnectionConfig; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.log.FineLoggerProvider; +import com.fr.third.springframework.util.StringUtils; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class DbUtils { + String db_name = "finedb"; + + FineLoggerProvider logger = FineLoggerFactory.getLogger(); + + + public com.fr.data.impl.Connection getDbConnect() { + return ConnectionConfig.getInstance().getConnection(db_name); + } + + public JSONArray select(String sql, Object... params) { + logger.info("query data by sql:" + sql + Arrays.toString(params)); + try { + com.fr.data.impl.Connection dbConnect = getDbConnect(); + + Connection con = dbConnect.createConnection(); + PreparedStatement preparedStatement = con.prepareStatement(sql); + setParams(preparedStatement, params); + ResultSet rs = preparedStatement.executeQuery(sql); + // 获得记录的详细信息,然后获得总列数 + ResultSetMetaData resMetaData = rs.getMetaData(); + int colNum = resMetaData.getColumnCount(); + // 用对象保存数据 + String name = ""; + String value = ""; + JSONArray list = new JSONArray(); + while (rs.next()) { + JSONObject cells = new JSONObject(); + for (int i = 0; i < colNum; i++) { + name = resMetaData.getColumnLabel(i); + if (cells.get(name) != null) { + name = resMetaData.getColumnLabel(i); + } + if (rs.getObject(i) != null && resMetaData.getColumnTypeName(i).equals("DATETIME") || resMetaData.getColumnTypeName(i).equals("TIMESTAMP")) { + value = rs.getObject(i).toString(); + cells.put(name, value.substring(0, value.length() - 2)); + } else { + cells.put(name, rs.getString(i)); + } + } + list.add(cells); + } + // 释放数据库资源 + rs.close(); + preparedStatement.close(); + con.close(); + return list; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public JSONObject findOneRow(String sql, Object... params) { + JSONArray select = select(sql, params); + if (select != null) { + if (!select.isEmpty()) { + return select.getJSONObject(0); + } + } + return null; + } + + public int countRows(String sql, Object... params) throws Exception { + PreparedStatement pstmt = getDbConnect().createConnection().prepareStatement(sql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + if (resultSet.next()) { + return resultSet.getInt(1); + } + return 0; + } + + public boolean checkExist(String sql, Object... params) throws Exception { + PreparedStatement pstmt = getDbConnect().createConnection().prepareStatement(sql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + if (resultSet.next()) { + return resultSet.getInt(1) > 0; + } + return false; + } + + public boolean checkTableExit(String tableName) throws Exception { + String sql = "SELECT\n" + + "\tcount(1) \n" + + "FROM\n" + + "\t" + tableName + " \n"; + return checkExist(sql); + } + + private void setParams(PreparedStatement pstmt, Object... params) throws SQLException { + if (params.length > 0) { + int length = params.length; + for (int i = 1; i <= length; i++) { + pstmt.setObject(i, params[i - 1]); + } + } + } + + public int exSqlUpdate(String sql, Object... params) throws Exception { + logger.info("update data by sql:" + sql + " params " + Arrays.toString(params)); + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(sql); + setParams(pstmt, params); + int i = pstmt.executeUpdate(); + pstmt.close(); + connection.close(); + return i; + } + + /** + * 取查询结果集字段 + * + * @param sql + * @param params + * @return + * @throws Exception + */ + public JSONArray exQuery(String sql, Object... params) throws Exception { + logger.info("query data by sql:" + sql + " params " + Arrays.toString(params)); + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(sql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + ResultSetMetaData resMetaData = resultSet.getMetaData(); + int columnCount = resMetaData.getColumnCount(); + JSONArray arrs = new JSONArray(); + while (resultSet.next()) { + String name; + String value; + JSONObject one = new JSONObject(); + for (int i = 1; i <= columnCount; i++) { + name = resMetaData.getColumnLabel(i); + if (one.get(name) != null) { + name = resMetaData.getColumnLabel(i); + } + if (resultSet.getObject(i) != null && resMetaData.getColumnTypeName(i).equals("DATETIME") || resMetaData.getColumnTypeName(i).equals("TIMESTAMP")) { + value = resultSet.getObject(i).toString(); + one.put(name, value.substring(0, value.length() - 2)); + } else { + one.put(name, resultSet.getString(i)); + } + } + arrs.add(one); + } + + pstmt.close(); + connection.close(); + logger.info("查询结果:" + arrs); + return arrs; + } + + public List query(String sql,String line_break,String field_break) throws Exception { + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(sql); + ResultSet resultSet = pstmt.executeQuery(); + ResultSetMetaData resMetaData = resultSet.getMetaData(); + int columnCount = resMetaData.getColumnCount(); + List arrs = new ArrayList<>(); + while (resultSet.next()) { + StringBuilder builder = new StringBuilder(); + for (int i = 1; i <= columnCount; i++) { + if(i !=1 ){ + builder.append(field_break); + } + String data = resultSet.getString(i); + builder.append(StringUtils.trimAllWhitespace(data)); + } + builder.append(line_break); + arrs.add(builder.toString()); + } + pstmt.close(); + connection.close(); + return arrs; + } + + public List getQueryFields(String preSql, Object... params) throws Exception { + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(preSql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + ResultSetMetaData resMetaData = resultSet.getMetaData(); + int columnCount = resMetaData.getColumnCount(); + List arrs = new ArrayList<>(); + for (int i = 0; i < columnCount; i++) { + String columnName = resMetaData.getColumnName(i + 1); + arrs.add(columnName); + } + pstmt.close(); + connection.close(); + return arrs; + } +} diff --git a/src/main/java/com/fr/plugin/utils/RespUtils.java b/src/main/java/com/fr/plugin/utils/RespUtils.java new file mode 100644 index 0000000..f479337 --- /dev/null +++ b/src/main/java/com/fr/plugin/utils/RespUtils.java @@ -0,0 +1,34 @@ +package com.fr.plugin.utils; + + +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class RespUtils { + public static JSONObject buildResp(int code, String msg, Object data) { + JSONObject res = new JSONObject(); + res.put("code", code); + res.put("msg", msg); + res.put("data", data); + return res; + } + public static String Exception2String(Throwable e) { + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + return writer.toString(); + } + public static JSONObject buildError(int code, String msg) { + return buildResp(code, msg, ""); + } + + public static JSONObject buildNormalError(String msg) { + return buildResp(-1, msg, ""); + } + + public static JSONObject buildSuccess(Object data) { + return buildResp(0, "success", data); + } +} diff --git a/src/main/resources/com/fr/plugin/alert.html b/src/main/resources/com/fr/plugin/alert.html new file mode 100644 index 0000000..bfb2ea2 --- /dev/null +++ b/src/main/resources/com/fr/plugin/alert.html @@ -0,0 +1,35 @@ + + + + + alert + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/demo.properties b/src/main/resources/com/fr/plugin/demo.properties new file mode 100644 index 0000000..9bc5f29 --- /dev/null +++ b/src/main/resources/com/fr/plugin/demo.properties @@ -0,0 +1 @@ +Plugin-Test_Function_Abs=Test ABS \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/demo_zh_CN.properties b/src/main/resources/com/fr/plugin/demo_zh_CN.properties new file mode 100644 index 0000000..aa910e8 --- /dev/null +++ b/src/main/resources/com/fr/plugin/demo_zh_CN.properties @@ -0,0 +1 @@ +Plugin-Test_Function_Abs=测试ABS函数 \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/js/print.js b/src/main/resources/com/fr/plugin/js/print.js new file mode 100644 index 0000000..e5965af --- /dev/null +++ b/src/main/resources/com/fr/plugin/js/print.js @@ -0,0 +1,476 @@ +!function (e, t) { + "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.printJS = t() : e.printJS = t() +}(window, function () { + return function (n) { + var r = {}; + + function o(e) { + if (r[e]) return r[e].exports; + var t = r[e] = {i: e, l: !1, exports: {}}; + return n[e].call(t.exports, t, t.exports, o), t.l = !0, t.exports + } + + return o.m = n, o.c = r, o.d = function (e, t, n) { + o.o(e, t) || Object.defineProperty(e, t, {enumerable: !0, get: n}) + }, o.r = function (e) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(e, "__esModule", {value: !0}) + }, o.t = function (t, e) { + if (1 & e && (t = o(t)), 8 & e) return t; + if (4 & e && "object" == typeof t && t && t.__esModule) return t; + var n = Object.create(null); + if (o.r(n), Object.defineProperty(n, "default", { + enumerable: !0, + value: t + }), 2 & e && "string" != typeof t) for (var r in t) o.d(n, r, function (e) { + return t[e] + }.bind(null, r)); + return n + }, o.n = function (e) { + var t = e && e.__esModule ? function () { + return e.default + } : function () { + return e + }; + return o.d(t, "a", t), t + }, o.o = function (e, t) { + return Object.prototype.hasOwnProperty.call(e, t) + }, o.p = "", o(o.s = 4) + }([function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(2), i = (r = o) && r.__esModule ? r : {default: r}, a = n(1); + var l = { + send: function (r, e) { + document.getElementsByTagName("body")[0].appendChild(e); + var o = document.getElementById(r.frameId); + o.onload = function () { + if ("pdf" !== r.type) { + var e = o.contentWindow || o.contentDocument; + if (e.document && (e = e.document), e.body.appendChild(r.printableElement), "pdf" !== r.type && r.style) { + var t = document.createElement("style"); + t.innerHTML = r.style, e.head.appendChild(t) + } + var n = e.getElementsByTagName("img"); + 0 < n.length ? function (e) { + var t = [], n = !0, r = !1, o = void 0; + try { + for (var i, a = e[Symbol.iterator](); !(n = (i = a.next()).done); n = !0) { + var l = i.value; + t.push(u(l)) + } + } catch (e) { + r = !0, o = e + } finally { + try { + !n && a.return && a.return() + } finally { + if (r) throw o + } + } + return Promise.all(t) + }(n).then(function () { + return d(o, r) + }) : d(o, r) + } else d(o, r) + } + } + }; + + function d(t, n) { + try { + if (t.focus(), i.default.isEdge() || i.default.isIE()) try { + t.contentWindow.document.execCommand("print", !1, null) + } catch (e) { + t.contentWindow.print() + } else t.contentWindow.print() + } catch (e) { + n.onError(e) + } finally { + (0, a.cleanUp)(n) + } + } + + function u(n) { + return new Promise(function (t) { + !function e() { + n && void 0 !== n.naturalWidth && 0 !== n.naturalWidth && n.complete ? t() : setTimeout(e, 500) + }() + }) + } + + t.default = l + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }; + t.addWrapper = function (e, t) { + return '

' + e + "
" + }, t.capitalizePrint = function (e) { + return e.charAt(0).toUpperCase() + e.slice(1) + }, t.collectStyles = f, t.loopNodesCollectStyles = function e(t, n) { + for (var r = 0; r < t.length; r++) { + var o = t[r]; + if (-1 === n.ignoreElements.indexOf(o.getAttribute("id"))) { + var i = o.tagName; + if ("INPUT" === i || "TEXTAREA" === i || "SELECT" === i) { + var a = f(o, n), l = o.parentNode, + d = "SELECT" === i ? document.createTextNode(o.options[o.selectedIndex].text) : document.createTextNode(o.value), + u = document.createElement("div"); + u.appendChild(d), u.setAttribute("style", a), l.appendChild(u), l.removeChild(o) + } else o.setAttribute("style", f(o, n)); + var c = o.children; + c && c.length && e(c, n) + } else o.parentNode.removeChild(o) + } + }, t.addHeader = function (e, t) { + var n = document.createElement("div"); + if (l(t.header)) n.innerHTML = t.header; else { + var r = document.createElement("h1"), o = document.createTextNode(t.header); + r.appendChild(o), r.setAttribute("style", t.headerStyle), n.appendChild(r) + } + e.insertBefore(n, e.childNodes[0]) + }, t.cleanUp = function (t) { + t.showModal && r.default.close(); + t.onLoadingEnd && t.onLoadingEnd(); + (t.showModal || t.onLoadingStart) && window.URL.revokeObjectURL(t.printable); + if (t.onPrintDialogClose) { + var n = "mouseover"; + (o.default.isChrome() || o.default.isFirefox()) && (n = "focus"); + window.addEventListener(n, function e() { + window.removeEventListener(n, e), t.onPrintDialogClose() + }) + } + }, t.isRawHTML = l; + var r = a(n(3)), o = a(n(2)); + + function a(e) { + return e && e.__esModule ? e : {default: e} + } + + function f(e, t) { + var n = document.defaultView || window, r = "", o = n.getComputedStyle(e, ""); + return Object.keys(o).map(function (e) { + (-1 !== t.targetStyles.indexOf("*") || -1 !== t.targetStyle.indexOf(o[e]) || function (e, t) { + for (var n = 0; n < e.length; n++) if ("object" === (void 0 === t ? "undefined" : i(t)) && -1 !== t.indexOf(e[n])) return !0; + return !1 + }(t.targetStyles, o[e])) && o.getPropertyValue(o[e]) && (r += o[e] + ":" + o.getPropertyValue(o[e]) + ";") + }), r += "max-width: " + t.maxWidth + "px !important;" + t.font_size + " !important;" + } + + function l(e) { + return new RegExp("<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>(.*?)").test(e) + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r = { + isFirefox: function () { + return "undefined" != typeof InstallTrigger + }, isIE: function () { + return -1 !== navigator.userAgent.indexOf("MSIE") || !!document.documentMode + }, isEdge: function () { + return !r.isIE() && !!window.StyleMedia + }, isChrome: function () { + return !!(0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : window).chrome + }, isSafari: function () { + return 0 < Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor") || -1 !== navigator.userAgent.toLowerCase().indexOf("safari") + } + }; + t.default = r + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var a = { + show: function (e) { + var t = document.createElement("div"); + t.setAttribute("style", "font-family:sans-serif; display:table; text-align:center; font-weight:300; font-size:30px; left:0; top:0;position:fixed; z-index: 9990;color: #0460B5; width: 100%; height: 100%; background-color:rgba(255,255,255,.9);transition: opacity .3s ease;"), t.setAttribute("id", "printJS-Modal"); + var n = document.createElement("div"); + n.setAttribute("style", "display:table-cell; vertical-align:middle; padding-bottom:100px;"); + var r = document.createElement("div"); + r.setAttribute("class", "printClose"), r.setAttribute("id", "printClose"), n.appendChild(r); + var o = document.createElement("span"); + o.setAttribute("class", "printSpinner"), n.appendChild(o); + var i = document.createTextNode(e.modalMessage); + n.appendChild(i), t.appendChild(n), document.getElementsByTagName("body")[0].appendChild(t), document.getElementById("printClose").addEventListener("click", function () { + a.close() + }) + }, close: function () { + var e = document.getElementById("printJS-Modal"); + e.parentNode.removeChild(e) + } + }; + t.default = a + }, function (e, t, n) { + e.exports = n(5) + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}), n(6); + var r, o = n(7); + var i = ((r = o) && r.__esModule ? r : {default: r}).default.init; + "undefined" != typeof window && (window.printJS = i), t.default = i + }, function (e, t, n) { + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }, a = r(n(2)), l = r(n(3)), d = r(n(8)), u = r(n(9)), c = r(n(10)), f = r(n(11)), s = r(n(12)); + + function r(e) { + return e && e.__esModule ? e : {default: e} + } + + var p = ["pdf", "html", "image", "json", "raw-html"]; + t.default = { + init: function () { + var t = { + printable: null, + fallbackPrintable: null, + type: "pdf", + header: null, + headerStyle: "font-weight: 300;", + maxWidth: 800, + font: "TimesNewRoman", + font_size: "12pt", + honorMarginPadding: !0, + honorColor: !1, + properties: null, + gridHeaderStyle: "font-weight: bold; padding: 5px; border: 1px solid #dddddd;", + gridStyle: "border: 1px solid lightgray; margin-bottom: -1px;", + showModal: !1, + onError: function (e) { + throw e + }, + onLoadingStart: null, + onLoadingEnd: null, + onPrintDialogClose: null, + onPdfOpen: null, + onBrowserIncompatible: function () { + return !0 + }, + modalMessage: "Retrieving Document...", + frameId: "printJS", + printableElement: null, + documentTitle: "Document", + targetStyle: ["clear", "display", "width", "min-width", "height", "min-height", "max-height"], + targetStyles: ["border", "box", "break", "text-decoration"], + ignoreElements: [], + imageStyle: "max-width: 100%;", + repeatTableHeader: !0, + css: null, + style: null, + scanStyles: !0, + base64: !1 + }, e = arguments[0]; + if (void 0 === e) throw new Error("printJS expects at least 1 attribute."); + switch (void 0 === e ? "undefined" : i(e)) { + case"string": + t.printable = encodeURI(e), t.fallbackPrintable = t.printable, t.type = arguments[1] || t.type; + break; + case"object": + for (var n in t.printable = e.printable, t.base64 = void 0 !== e.base64, t.fallbackPrintable = void 0 !== e.fallbackPrintable ? e.fallbackPrintable : t.printable, t.fallbackPrintable = t.base64 ? "data:application/pdf;base64," + t.fallbackPrintable : t.fallbackPrintable, t) "printable" !== n && "fallbackPrintable" !== n && "base64" !== n && (t[n] = void 0 !== e[n] ? e[n] : t[n]); + break; + default: + throw new Error('Unexpected argument type! Expected "string" or "object", got ' + (void 0 === e ? "undefined" : i(e))) + } + if (!t.printable) throw new Error("Missing printable information."); + if (!t.type || "string" != typeof t.type || -1 === p.indexOf(t.type.toLowerCase())) throw new Error("Invalid print type. Available types are: pdf, html, image and json."); + t.showModal && l.default.show(t), t.onLoadingStart && t.onLoadingStart(); + var r = document.getElementById(t.frameId); + r && r.parentNode.removeChild(r); + var o = void 0; + switch ((o = document.createElement("iframe")).setAttribute("style", "visibility: hidden; height: 0; width: 0; position: absolute;"), o.setAttribute("id", t.frameId), "pdf" !== t.type && (o.srcdoc = "" + t.documentTitle + "", null !== t.css && (Array.isArray(t.css) || (t.css = [t.css]), t.css.forEach(function (e) { + o.srcdoc += '' + })), o.srcdoc += ""), t.type) { + case"pdf": + if (a.default.isFirefox() || a.default.isEdge() || a.default.isIE()) try { + if (console.info("PrintJS currently doesn't support PDF printing in Firefox, Internet Explorer and Edge."), !0 === t.onBrowserIncompatible()) window.open(t.fallbackPrintable, "_blank").focus(), t.onPdfOpen && t.onPdfOpen() + } catch (e) { + t.onError(e) + } finally { + t.showModal && l.default.close(), t.onLoadingEnd && t.onLoadingEnd() + } else d.default.print(t, o); + break; + case"image": + f.default.print(t, o); + break; + case"html": + u.default.print(t, o); + break; + case"raw-html": + c.default.print(t, o); + break; + case"json": + s.default.print(t, o) + } + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(0), i = (r = o) && r.__esModule ? r : {default: r}, a = n(1); + + function l(e, t, n) { + var r = new window.Blob([n], {type: "application/pdf"}); + r = window.URL.createObjectURL(r), t.setAttribute("src", r), i.default.send(e, t) + } + + t.default = { + print: function (e, t) { + if (e.base64) { + var n = Uint8Array.from(atob(e.printable), function (e) { + return e.charCodeAt(0) + }); + l(e, t, n) + } else { + e.printable = /^(blob|http)/i.test(e.printable) ? e.printable : window.location.origin + ("/" !== e.printable.charAt(0) ? "/" + e.printable : e.printable); + var r = new window.XMLHttpRequest; + r.responseType = "arraybuffer", r.addEventListener("load", function () { + if (-1 === [200, 201].indexOf(r.status)) return (0, a.cleanUp)(e), void e.onError(r.statusText); + l(e, t, r.response) + }), r.open("GET", e.printable, !0), r.send() + } + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(1), i = n(0), a = (r = i) && r.__esModule ? r : {default: r}; + t.default = { + print: function (e, t) { + var n = document.getElementById(e.printable); + n ? (e.printableElement = function e(t, n) { + var r = t.cloneNode(); + var o = !0; + var i = !1; + var a = void 0; + try { + for (var l, d = t.childNodes[Symbol.iterator](); !(o = (l = d.next()).done); o = !0) { + var u = l.value; + if (-1 === n.ignoreElements.indexOf(u.id)) { + var c = e(u, n); + r.appendChild(c) + } + } + } catch (e) { + i = !0, a = e + } finally { + try { + !o && d.return && d.return() + } finally { + if (i) throw a + } + } + switch (t.tagName) { + case"SELECT": + r.value = t.value; + break; + case"CANVAS": + r.getContext("2d").drawImage(t, 0, 0) + } + return r + }(n, e), e.header && (0, o.addHeader)(e.printableElement, e), a.default.send(e, t)) : window.console.error("Invalid HTML element id: " + e.printable) + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(0), i = (r = o) && r.__esModule ? r : {default: r}; + t.default = { + print: function (e, t) { + e.printableElement = document.createElement("div"), e.printableElement.setAttribute("style", "width:100%"), e.printableElement.innerHTML = e.printable, i.default.send(e, t) + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(1), i = n(0), a = (r = i) && r.__esModule ? r : {default: r}; + t.default = { + print: function (r, e) { + r.printable.constructor !== Array && (r.printable = [r.printable]), r.printableElement = document.createElement("div"), r.printable.forEach(function (e) { + var t = document.createElement("img"); + t.setAttribute("style", r.imageStyle), t.src = e; + var n = document.createElement("div"); + n.appendChild(t), r.printableElement.appendChild(n) + }), r.header && (0, o.addHeader)(r.printableElement, r), a.default.send(r, e) + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }, c = n(1), i = n(0), a = (r = i) && r.__esModule ? r : {default: r}; + t.default = { + print: function (t, e) { + if ("object" !== o(t.printable)) throw new Error("Invalid javascript data object (JSON)."); + if ("boolean" != typeof t.repeatTableHeader) throw new Error("Invalid value for repeatTableHeader attribute (JSON)."); + if (!t.properties || !Array.isArray(t.properties)) throw new Error("Invalid properties array for your JSON data."); + t.properties = t.properties.map(function (e) { + return { + field: "object" === (void 0 === e ? "undefined" : o(e)) ? e.field : e, + displayName: "object" === (void 0 === e ? "undefined" : o(e)) ? e.displayName : e, + columnSize: "object" === (void 0 === e ? "undefined" : o(e)) && e.columnSize ? e.columnSize + ";" : 100 / t.properties.length + "%;" + } + }), t.printableElement = document.createElement("div"), t.header && (0, c.addHeader)(t.printableElement, t), t.printableElement.innerHTML += function (e) { + var t = e.printable, n = e.properties, + r = ''; + e.repeatTableHeader && (r += ""); + r += ""; + for (var o = 0; o < n.length; o++) r += '"; + r += "", e.repeatTableHeader && (r += ""); + r += ""; + for (var i = 0; i < t.length; i++) { + r += ""; + for (var a = 0; a < n.length; a++) { + var l = t[i], d = n[a].field.split("."); + if (1 < d.length) for (var u = 0; u < d.length; u++) l = l[d[u]]; else l = l[n[a].field]; + r += '" + } + r += "" + } + return r += "
' + (0, c.capitalizePrint)(n[o].displayName) + "
' + l + "
" + }(t), a.default.send(t, e) + } + } + }]).default +}); + +/** + * 打印图片,传入要打印的图片,相对路径或者绝对路径都可以 + * @param url + */ +function printImage(url) { + printJS(url, 'image') +} + +window.printImage=printImage; +/** + * PDF文件必须与使用的程序在相同的域中。在打印文件之前会使用iframe加载文件,因此受到Same Origin Policy的限制。 + */ +function printPdf(url) { + printJS(url, 'pdf') +} +window.printPdf=printPdf; +/** + * 使用base64封装的pdfdata对象。 + */ +function printPdfBase64(data) { + printJS({printable: data, type: 'pdf', base64: true}) +} +window.printPdfBase64=printPdfBase64; +/** + * 打印dom对象, 传递要打印dom的id 不带#号 + */ +function printDom(nodeId) { + printJS({printable: nodeId, type: 'html'}) +} +window.printDom=printDom; \ No newline at end of file