From 2620a30a4e8c6f6bd48f63da374e864d163c5b65 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Tue, 4 Nov 2025 09:14:17 +0800 Subject: [PATCH] feat(web): support download button for some packers --- web/bun.lockb | Bin 208812 -> 209452 bytes web/package.json | 44 ++++++------ .../memshell/results/multi-packer.tsx | 67 ++++++++++++++++-- .../memshell/results/result-component.tsx | 1 + .../components/probeshell/shell-result.tsx | 1 + web/src/lib/utils.ts | 33 ++++++--- 6 files changed, 107 insertions(+), 39 deletions(-) diff --git a/web/bun.lockb b/web/bun.lockb index 9ad30ac2277a5a97ffba396d67a0a1fb31745050..9b05fd0796b52294f5ffd212c2164beed0c39b15 100755 GIT binary patch delta 45724 zcmeFaXIK==);2snFv_S1NEQ)Lkt9eSa!^ndR4@T1L_|bE5Db9gfH|jD8*_G>Gb)%f z=B$`=&S9%ydha#ejU!vnInVQc?{$4Y&RpERYTZ?}YE`bDnI6{OuCew(jj2v{eqYxH zRqw1-_Pp7GRmI0!$PzccOLLohYu27E5u523q9LKz!)ehL(sQ>rWd$*8x`v6o zKO>RUkVx{Lvili}YCCI6BnHrW>#)z5y2>lMe59M6L?Q>B54{>>Mq+%z0LSFaE#S4G zr-Mf@Z*(n*1i`$F_@2pGjsue?m`Efx&=VmW5>NTy#5ZG!#0vT@NK43WkQR{oW)ca4 zc_)k{k~$KJGH;%cU@%YQEi{x!Y9m1eye5aD^m%_%!J9(w4d=-~dqFosJpS^2z%YEv zi$EfBFbED=L)L|?2YCaT$e~AWsW^H-Jv{kqh#IP`@Hb>WI;h)bPH7tPV-_ye_oYA)!Oo338Som4ftxG?Mg? zrlt)@PV0wG!ib=uXye8YS#wAls&?RMe6w#f zO_NJ_(Y|>@1idFD z^;&Cz_k|<_HbT51B;{uW{ka#PzZ8ZGo&0 zISsNNWCo;#5`lIUfb@W*gr<-*&B}v${uU(Z2O(+rZG)uVUFyL*9@>guQ0hTa0Y4&m zc@wf8^j(lvkaGn&1d<%=45_4m9|Gh+T}X1EOBCN^UXV1A>>za@%^_<*hCxzON`&A85ztcW=+P)D}o`d>$lqrMVzCx05JU1q_H!kMEI^DEZ!jpP4IQfC>^b zI$&^;o)W`%MSDmS=-!ZIxDF(B&DUtYW_KW|#g0N!SFMJm_$iQ-ejp@uX}4&s1I7rn z15usrs%56^!0>gQ)0H1aYcUsSI1Wg~(7%sCgMH2^KD=QNo{5Z zNv`V%GButru?HkALNSmuuiE!eNr$||%!K%q_@0RgDaiwqB@&5d0zWaELsEvRkktFP z6WH4Fy0vHaf;)$ZE+It25Jaj5m^rn*A71bNmmtTX0>e=UsZf}4g@{dd59hfM{x~aUs znXFYc8)d6Bz8GIfnv)S|baJOEB(-AI{``=B0i8P16O!Dt6r?^Rx!Dl;4I$rRF~qKr zw-1u4J!Swu73>G{Bi#g&%BcYf`^vneLA=3EkYuPCqyeN4Bsn0qS9W|#N^<4^NoHc| zpu`M`q&E!H6cQaglEsfeJ@C{W&X6=UEFpCv`(&b@(I4Uz;im*vBflZM=VFb;nu;}( z3I?e|<5Myv?VwXlgCVIVA20}M6HH3%mzmu!LDDBPt)B-9nhBnU{0X!Koj$}C5gk|Q z9T3qovByC4l|*zvtbyo2uROj$u_j`HmD7p&KV-7CYXm6KII13)F_Ldc_^4`-4Wsym zngK~YDrOVSiN%P;i+&G9dK0A29Lx7`6eKNn*TzXCu8QqX`sypGWYEw=Pgr>Eg9R)DpPY43VgEO9Li0f zcje>-3+cUXQLkR5cib_dim$_pGquv%7M>qnD{ISHlSNWC%gjWpr{9krktPYumZ@gF z87O;v{TvJ%#ovXhG1bVo=E0d?yFixxbt(vJI4n z)Wo`n7>3QaP{^~OHHD_b=Eo`IccCeunX*hhh15icEw&4g4%A`G?ESA8Dwz9hnSG$#50eOo&^%2xI9?$gq{rqs1Tg#9 zB8NbEIii}Vq8KZM)UOun(Z#6v*6R%NhmByP%uJh|v^O#qH3#s5DAxk3mEpGi>lkFUE{5b_$T|VI`vUC=-sP z)nR=a2QY`(?8bp|V;o%g7Dr}jTXVL&ae%bIob_=IkUc?M1nb|}SMH7_EmAZf9|-Z7dE%CuQaS4TkIAfTU-xa#_o3Wl~<`RW{00jTQ2B(1bx5uaG~1#`g>L zw^>8B*fT)du_0UT86YogD3JuJs>^sNm=A2WB2eaHgZ@@Ioo&OGD+1&pwqgrWn@ok~ zswyhqK_Nc?jc-}%$|`o^Pzi3Nkhg}`R+W-LzE#j@*fH#WJB9o{H0pFXY^jiWV`mCr z{Tuj72isHsGpE^XpFpXp16%A9AWL^ZT2pELqmn~sav()tS4r)7XNUBTwG43KX|1Nb41pXy%~YDzX;LA_FJ{TB@ie2=VD3 zA;jBog4cY89E5o8074if$coDIkzEkti(i5epX?bzyg4WI1C+9-$7ZkPSviXVyQ=PZNQ5 zD(VtKT~#61W@2axLJ2DF9YR>aV6Gi{I$0Ikg%F>^G)y8%QgL|*C8|OX5sFiVLNH?Z z&{Bl>95n2Cr(zM}V|P?=df^gDv?_0JgnZfE*1qzk2%);dc=4Zu5E$Vr6NuzQeEo{ty4wZVQ4fd`11Nk@sk4Ulchqt7+Mp= zN${$MtyDEdo>S`9h#ueQRQFj zE1wOPnp(>4M~7X3hB?VMymmtvai%!5P?d@k}8i^kTE)0_98KFxDp&f}@V~MjTrn7a(umUECt* zJTt93o6|i&eg!0Tk)djdHbGMbsq(=jGm`a=50qa6NA7FUQB7`w>EH*gifRY#CTKF! zq;q<(K0N~D=RsoUKnB`mwb7#F3YP15FD)o!3x0J|$mc_A0u2pgr;t5`=Ev@??<=?N z$u|nDS}Wuo1Wk+0hq(pNuyfFQkF)N1Xk=V92IVyp`O%NKcm>m*E$bO5Uk45ol}fbt zViMV$!~mINFWi2z{?5KkEL)Zss67KZ)k%g2Y%krQ#Vg2KMk zo}z~N3I(&7ElLe!?AWr@K-rZ3Sm4-islL+3{n?y;0gMM*)GtuRWvE6{sxNba^-il( z-Q7(xGq2{D$x9aMv5PECnEGsXS|GE5Ey8srTb33m3mb^lo6Sx0Wmd4+>4DN01KHyA z0D0~pvC~l#<{InWKaeqJvvKXm7WEI57Y^oo0(C$yy@o~$qN?6<*DP`P02<8=-p$g{ZiOInAv#*2vL)1P{%V%+3W#<@^|2{ zy`dZPV-&KeA+*0^IgoJ(`LN$?d}Zelicwjz8%iw!OR_|Sg4l1U;d0h{P@w!KbiVUw zCf3j82cN1drD?frxlI7Gj`bcKDF1*czSr_yy)=i>DR_6D9|ihR5z=SFSf8u_rXHJ} z6(}37MAx&qS-wm$Tb6}(RI)zV0kVd9R5)na5QN|m5^QJ7vIAur`KqcSCKRCnRhkh9 z1+o6%4kF~I3jILHM-}oOPU#TK3}%al1j8KzO3&Snn_q?@#1fin3RRX1e&%32`Qg#Cul1cdxlp`!?SsX{*x z!WNA7ojaDzNehr^kE5YO$!m<4NJguAcRE6YRG~o=B$6Ce=nX=uj*)enNMm|;hOcZF zLi}hmnuHS!p93LP0rC=rXd?0pPuI!(iAOc!d%;{!{q#j|OdIvOUn+vb*hk znZ|6{h(LMP)QS=1gji_k#2&u#?*d;%bvGL_jb9I|vioBdjFR;p6(~Cd&YhMBnQS^W zia+j)nj=K3FP56_3i%LdG`09;=mRvG0a&ao6tb2qEimvyJ`^G1Rm-GIGJ|SOd?$n= z`1Ba-E1)%pMkgvPd^7pem}&=;b%*AqTEq$vqE_M8`#aERB&l{PdA(T@)y*sx(m~jt zpwV)NIEt-`Uz;{xPy9Nz@h*!{R=nFEc6B}Ne{dLJ4; zEom1}6!0rH|EA0kXp|Do-$)@nT)-BO574eUn_sxARt&`S;c_jI?U7Qo(#y6&!>wLj zUupSlws=B-yyYCxP;did zAPxurNxriB^XLRlp`i$MP=(GR#K$(8FQMCD#3~W$stVmeC|MN>T|oB*6uT0kcvVQg zP>jt$h|h5bp(ItT=OVf%5Ya`Ix9vE^)ld^^n49)tGi(&bKtiK2Bvlmb1k(0^~D6Iw3L6dN6(xnlChTMtz0+#0vgQ%xew) z;#U`5%Z5g~BCnM|3$M`hS4t#N6i}|W6F@JL=9*}|;$r`{LfcW=-9QX>59R^<1g4Bm3dxnrzAk82t-jcp8QXK&YNF&H# zNJ`igvMOXtNXifiSrf7wBo!1d$exh&BB{YnT4k(i&}3+2rLPc6l7cC?P_gvQ8nT`R zN$ok5A}dKMMJdFO5aLNv`Z171jm3q$XCcYn90m+jK~g$%NE!%^kW{c2q&{RgB-x9VCh!qGLFjNcH4)-Ngm`sH1%?VdNvdd+p#PM7AN(c)sehZ{f6kMm z?NBf|)Lw9aB+bGY)fl7z2x_`+LIQP3Es`kkzmpWzTZmVeRA92et4pF%a3Lv6!xT@pWA;7L+zFA{W;w8Sijq;xAFseqM2 zyt<_LRYLq4A^ln*-CB)ye8%-4XieJX;D!JIS!~7t`0B@WD1x zky~dW$^9#kl<^uaRLX5q1WD=c3h@sFo+R;)1f3*R=P@Kv&jg+%rF$XhkZk8odMY1Y z2^>jE^9GV?`U8?`q=5_RwIIp1J|v|xge0Hq2)sEYy-1Sp^&lx-14v5e07>~93A~dg z`j!$n3lT1YbcLiBNy^|RNOwVc2+~uK3P^g9tOpq@=p-rF6&ETe4w4+{1xXI})kOWN zfD{l^!y%9~it{0SpbPY$vj*r{Q^NQf~11~qDVnf zaE($(uuhO0gaqo63~d5W1#K4MNs_)rkXr>_U6P}_g!tWp+yhBT56}fKB?ZXPK_TL( z5b--njvN!>)g`sq8SoT;PLLObbR^0CML}K?c#=r3lw1)AlGNna1pRkXH6euf+mLjo zc?(GezlWrPK0wl5S&b6^TZ#Vv&l3JWN=NhWcMecZstYwBNqP-ICrP@tp#LjLW57^I z_d98h_&+DulE0$qfA3NF@%7((6dEeO+^f)Z{qH@>fA3LL14D+<@ZWnBRa2zRDdv|+G+*)Xb=!hE4K#*sziIgPLJ2yP9dIeM~;Q*lEGr zmDj(OcD?GYJ5ym%d+_2T`GL5#VKoyu*|y`kons_pdyO3;*E!yxS;JQK z3fu;@$w(OYpnUV3>Q|djSI#lNH!R$=YT4AgPaYl79o43D%#Z_(dv{)b#_sZxFPesI z*Mla?ZM`m!Sib%8#p+pgy9~%{J?=nLYlA@!9xtMIPIoAsG_-K)!_B5jvnjecL)=c* zv#@%+FzDcAr#CleFIgCzI(?U|T+KT>(KSfTtn1%96?V3N8F%YrsdeDnZC2S^EWPWz zt5NtPEPu*ld+kP@*6xc8e`cESwbzTsrkUk)hVD|1eI1(jbU|3Pti5x4d}Fl_nM5>9 z>9amP_DP%gPDvlG`JGyLzSqr`n{(_oPpEP5`Gtf-DbvkXg`N2p-u{biL?i7NXQQuX z9nf1BZZ#~#%|GGlp7l@EymMfa4@R>khqT#K2g6%As{6Xo+HdUAzV+vhur3*J=61ou z{tmZCe>f0PFl9h;`IYN^>ZHy(=@MppBXV!^^Euqo^Ln?xWGAr4EwyhS&9rFOAUBRp zJ!}$D=>2tQ@f+EMq>N7C50_qX_!88;*5!`nRo%MW%+1kr->y|=_R{sZX=vQgtg=p> zv#rdBulKY#`+Vl!&zC}@?m0)Rx!RaLb|{*)J)+Gz9u9AXPq8arnupW-Y>FShZn96W z6=P~nnH@EDVq2|Un;$tnYTh?IRnzRilE#HmO&mf}N*|RqchDYxYC^~A$I5##cbCd% z89N5XRAo;cF=1~W4rkn0yCc!;*rVF)q$A<@zRp!>UM1SB|Iu(p!Hzo`%|3zl5}G&b zT@uX}9IMGLC~3*~vQMFf9oJ@C9Sdjt+1baU+0W3vK?`JC9FJyKp3r939S>)M*)nJ` zC$-tGC&HPg?5Y#dtkx-QR{LZ)6UxS(jAnO0+YPNbD?b&@_CBr6rk)CCTChdXOwMSt z=BLA%a5nigx((VXXsuY&Gtq3;S#37=OgPhqJqFG89NOt@I1|NYpN(cqq1}Ymj=NpCF`Vhj z&c2BHLHhN4tAiuzp%$M@S}ub_U=c0)^I z<)x_KRn)IEoJnSjpqX4l{jP>Hec9xzs2{Xb&{A2`YpCCK)bCn2lg1u{W_ttmyB^N; zXS1)Pe$Z}0%Vh0tpnf+|zZ>DqK=vv$uUn|!&2W4nXWUKH586v;*{t_1)bBRxcPpG3 z!aju-b_eyl9nR#kvu~q*(7r)avMuhQes@v7JK;<|TLvxW9_n{DoEgEcx{LbVNB!=F zGo#qpd#E3@-O$Fc^82XY1Jv(+I5Undf@bm%^?MNBYC^@>#i9^;I^@-uZSe~}Dt?^5 zDLZni=*sY=eIr6PyjikIVle3Zx>1fLxp^5+&Q5>VW76WJ)UT-vn;rejXmnr)-zJv( zx74rB?tW+zQKzKHytba)$LY)9>$fa=N9-DBQm1)t+L(FgJRhAk_W8U2*9mW&Gqz^d zEonY_TVm_AV={~{E!?r~)JOj#jL)jt@6{&SB-ZpHn){J<#KL(iXFPXrrOAW_ht1g< zx8+B1-1xyw$NfDp*na!lvbSA^c=wxT{P;;sSi@G4cddGaxn!<)KmVc6^f6Z*b8?j3 z=#y7*k)FaHgHhYZ+U%%D;mkDl+#~ebV{K)gdCDx$`Wd6II+&bESvKc(RQope-$Ned z56b_(zrorM-T@`fD_qa8(>w+THar*F_Q1=vL)J83V{`s>X!6PFSI=pv6~U@Es&r7> zMqP`WpWw=`&He6hb3>I&1Cmw@2zqo$J9p*jRU4cZcrTc%H?~0eDsl0t0e^RQ)rmM~ z*ndIK?mv<``MA{BF;;!$!B=uBUYe;poZO8yjvVSW;p*d=J^GJ&bGc71#jGS(iPen( zFS~3oe!ru*^~j79TbpQqPoJAoJ>k)ItG1dNSGF2TRu(EZH?miA7+>4z_|tG=%E-5) z4s~17cU`^LJ*u4xEY2x?anG^e+xpW=P2)3tzN{K5@9XrpUbycMW2?<4nlBkNR?}_B z(soY`%(}d)Tcy0MU>K)3$t-r@nRf2z%fJ`HDPv(uhNGjrJNx6#a8_8hMB zSi5)8%zQQ<*9GiVTo^NK(vv+Y_!g_y*##j5M;kt}{itBPV`0r?Z5pg!I zf3a_IUCFli7|pC=7vs8`EyHyU8}%ugS<9}%bsfumj%L=gvAAwvH{rUGm6t^`o7i|< z@qI~Lx3GHU(ReB&8P`H~Kd#$Y(=XBZ7G8f`cd$?4c@Z1@EE-?jn~m#E_ARcv*cQ*D znceJST=%eLxb9`6USO(z(q;=^gyZ{}%*$xz02_!YFQ7x= zJ+khdMcoGMn%BOd+5B}juZ$8i7PYB8<;2#BEj#;VW>0A|r)N^P^D>_*ZqtwIPHp|F z_sBu2zLKgwL-T?#kHPpnI(t|FPNc?Dnb*YfAE9^sKt!Q_89D4lS!4FviZ{ zr1g*~yB_Pj9bD>lbH~Z4Q30LZ(sNt=wX2_bR>y_M7aF-bP3rR6BE5OLmpKy+-wdBU z=zQZ19~c~O8GI%}UrRWrZrI{f`z}Xzk1XgoYLP+z^>f>$G<;|fy5erhoL$DU@H45S zzu)pvluqeTzgp|KmA$q!KT}Y1;k9WqxrV2oE%#g2&Ek~cFxfq?Znx&xO(n-z_m{aF zG}{bXbFZ~>Q{lRaPmk0nXc(uLU;QQ{b35eNZqe30ThAxAd!rv^Fg|arPtmh82a|4f zZZ`dG{k}g`h9z2gFnU4V@LaB`!A#8@&%-N!%;?(Laqy_U2ZjdS=~lSr(8|V7SGTbb z8{G3_ueqC+9Bey$V!dh^Pp>~3w%*}pJ7tjl^3U~jb`7s07$%P|svGukOl4MVU3XyN z#V7u5t_v(LXF6}WKE~|PtD+~5zrG6WP%x)p^tnw{*W}d+4I6#EThX^fx4ouDchgI& z9W{;JdLl{9F1?E`zBGHrpFQLos;r*&ym<1kx|i&_s~5TD;iInAE^FI5tSIyA zv$T6j?a$FBSEL3D3SANwEWW98) zsQi#Rb>wRL$q*V7wBlS*H(Wi(^u&CxYu`qBN%!}<>~8J+*yKvv=QR%=+WTbChrdpA zJ005MTFAPNnhtkvI9`&6Lp zxyhn?9sOLs`n1`s=G}F5?-uWDU%*^&^-jEhyUpjopqp#EHHeKL)6>-8MX^G$TG_fVeN|KZ#sPWRfD;6rMLZ>SqSz2Vx4*KzK{TWl?u zefZ+zu8vy+V!L!d{K>1;c0C)fIvcJJoUlFpVL?Z;nxkT`NVZ@6{%l-*(=vDco1X$2 zm)Sg_uYHNzJHCr1yopQg88b;^;6fL}hId@u2X5?KO;Sr)o&BrXjtdu-M5j()aA?|^ zn)ff9;+n?4P25~n+NIIL@)M&U$~=dBE$lRD=GRB7994!TTJ*8pEp>-m)wlB>AL*1f zr+F8nN1NBTz3WhP=81Riffu<<>rCarg@t>wPWpAeujg8@dD+qiUAZ?FC++=4wp=lH z_TtCwww8X}CK#p>dt2S`9-oIlI+%UBm)>qsn{!VWji0u3X^qmJCD&stpY7A0eecbj z&*^QKeQ*4<)%<}^Zqz+)y=h{4<2j#G-uLd4+~I=mO((L;EtWC{5wc-Dk{zrUUEg4P z?wlgqGj!kjh%iYDAKzDfEINlj%F4D_>oI3hq-@u@r?sm0JNIn!an5zDsYYk_iH8c3 zZ^#TY)!Otfrzc~gxfl&bn;R%&!kPQrej>CqL0DG-@sR6Z1;h>_E)nsVv#JWBw+zIn zsvw?n=ZG+=0>VR!30FQ>uXgd37ca`ocFfzn%SC^DX`?>NHcxE$aplFJZO>+8_mDXF zrg)F(BC+{se^xI(%X7KI-RZY?dz9Dqn0)()cg}+Q^{rISqA?*~sN2<4rs!Q5-p63k zoX~j9?K55s_Sa6DeX&{jzKhCY?G5#Y|Lx4YY_v*$%)s;3yIc9J8MwJ?RL$<5Imd%y zn`B++*T?I#$}m3wUaA|;>~-|H!E9zn zOKxV>Z%)0|OYN>F6dt`D<*#l3&VH0-%q^4LY8Hi!Y{tBA9`$iUcomoJL#iB{JY+@o zm+Bk8&*4wH{Py@--R{Gf+yO~*XU%vUlhgWW$($l(SI-sWV{7g!aDHbw{)PXGd)Y;c zUNk;EZ^5!rTc%%~ntEqsj`1Uh>iH=rw>%zkY2x#Fs+QnS3UAa6XGbR=sp}knY-_-n zV^%Z!^|*I$Wv$xNbov?2Ub6iA1mm~orcCWVxB1*#OMcARoif+DB)oI_z89@JDF=6b z@2`1#kCnQ|Z`BP)t}lw2YPN59=dpUxf7QMoan_;m%a#RSgKTQ*UY)kQ-7%dkS0laL zt|M|DU;C8bA!4~kyxWK~J-3~_oVv{BP~fc_!kC~b_D2s5UL&Z)>OT8MUwaT5}XSzvn zj9@qqM&GL&Hk|!^_sTCPcmDVq`1hy8QHGK3&6sQZ##CKd`0dEUB~5OfIs2unL1?EV zOzwKOK&6#Y)!@t|cAe7Vvsr1_o@pUo^mR}CsZI(X)D1t<&dA*TwA`}6xLe7i_Sm*> z$J}4w@xog#=R@c1Z>_&exrVLlkGs9WFG|S_db_Z75ZhR%&pfwY+gr3WE34jY!xX_T zjkUi;yQ*zW{weEO)m~FNpDk~n)4||E@`dI*7ggV>y~@ravB!GZ0<$}^({8boLJB!a z=3|RMvr)c@-8rsEL)m54tzWHizl*O%jHBGzTY%zVJzR&!D6R#?+wo)19 z_s36M8N);?Kdakcc0c^#TDxS~=SH`>jsN~=vF&vK+Xox@9q&*p^Q}&s5#D(NZ${nE z^)=Pp){DER*w!njdE~m!vAr6MeB@od`KU>~)y$Wv+sz4EF0Vguie{SCj=Ceh59uB= zbd}^(n&kQ?1J@s`UyhIrI&3(zUi!GK~+;~2 zl`%Czr0Rgs;EIUQ(g9(v3qr;v>w?%p#3>@Ga;AD9dh3G7)dL~tjuBy^2g0!yi0WK+ zEf6I{+$2Jqv(pEWRSTg>`XF?;t3=r9gYY*1p~sCg08vWBOCt0+Z$l7c4M5B{1YyWM zCBn-PL@Of@#@uWp5KoBsMuaKX!Wcw>5r}ohOn58$GPn5BoZK}n$?f3yjOTwpbiA?f z<;!lP^3FN`t@T>-Q^uCSmbsFH_oL6Qbu75|Zt9?hGnTdgoSNPFlHOgXIYSRzEq0r6 zC!F&)W=tYWBbSwkNLM36m|Qm)@$b6DigT-*_hFeC@o#_vb591J-NQVJCzc+u{ zx#|4<1tY50+qLuVj^n3>EvX~l6+3!G!?3nt&E~F4$kw@aW!}=clhoX=uim(c0oj_a zmo7Mb2r=E3=~gf4!D_99ozk+&ZvFQjOo?y*_Iu&W+V)I>X@S|18N0h$JX?OPw2E)0 z;ks>~Cf3`$r@-bA_stZi$rEn++pmVC?cea)y~pCP!mHc;Utg~p}f!4JkcPQ9Nuv!-)>wCjDBxy}m!wXXs9YdHgLFzi=wl8@q{S*^f7$CVf7Z zws`FnvkxshC0x&1^?69^6`9@V@1FkHL!o6}Z1zsW)US{0-CDu-Q``(%`)HdrDl9DC zy7-CRj-aF5O-nTPax3`j&AqjPzXevPK!)@fI@?}iqVd;-)Gz&St()zy*4V+^CNdk-0Oc53qnxH(yfp|dYY>Nt2<7w| zg4jXCz=j~2bNh+t-4KMe4Tu(8e;W`cHXtq$5zblJf+!(klr4x>+&Ln$Y(aR~foQ|! z+kvpP1M!fED9*(mL@5z7?LoBT?h-N99z>`Ehz{H|2M}HkApRyInhS1(%M&7&Hv$pM zy(OZc5r__sAUbo49YKUSf{;0Z=*mSof%r^BArWyL(-_1`ClHB^LBw;Lh=^$n!q6E+ z0vGQLLdzM%VImSaJr@u=h#2SsB8l5iL~j=m)~+Cux&E#oOk6=+BBC#6>VxycGMz=Q zR`j&pIq5*HLc53F$sgwh4=%X6c|%T#bpKz>)@t!v!;i08(BjlLy%@*C1AFwncd|{% zr|E;jnWOzGap|O$ zB{xp4l+iv0u;a2a3}_y^XlLqi(6< z-N4I(JJ&GQFL>O);grZ1+$05-)ug~Vi9MIT+2nJ2V$(0R?~fT3H#L7({Q3#I$C<9a zq-(-noir}{wtbW22&2`LZ`F^;d9tWkcI|*Uks(tLEod?SE6r|k&7oN@zBFA!$KH1v z(qXInwkzu!UMd^iy~O?EwkM;u-CnV4#+iVnT|eJ9PHOWp#k9&NgE9LWoK!Rk&3C(0 z)cv&9nic*=nK2E!asFOt&6dMY?%m$m;_3a)9*?~zFRb6j+~9!smrs%99~BD^CC%U7 z?8VU*wX~*OKYag(;qv*Whjc#XKebAKyrTDC_pZ-gF@B|*d%0YcH(K+v7h1E>8>2zV zF+LzxdV@&x0g=ybA|l2IgrP5p5nQ}42rXX_hlv=)>G^@!LBv2m5M#LgMD+FpVeJoM z9M|6;go!_hOGHfItO7uk5HTtM#3b$<5qJt4<2De)6b>KXV%!FTcu2%F&Ls#$DG@V+ zK(O3hBE|-R2n_}?lbaR{!YdfW-$Za+a1#(uh*;hP#BA;@5d}>^bZ81o5?jxc*@vOu|5T&_=X|J4Qqa5socDtmCp2>VETfGB+kmb82dxMr9ZK41bW&DQLx^GpmQ4z8pB^?ULJ{ zZoNtfNbK(Q^7fFIu0|`jwU4-9QDozlXMf|z>lMs$wE?k(yGmxqhBGy}fN-WIQ^<{@ z711jK1;4}!%xvepBS1VMVtxdOBJL>>1+74|Y6W5^H@g*xu+|{H5wV+V(HiINJ=|gv zd$}?a`?#n!5c|1RBo1&)B*Z~37J}1?Le|}p$a3x_v$Dt9c(Tsd)i?zZGHxATqm zRo!^~sIT3~J=S%X-!po$xcTXsUn5p_UU4=$j&qF0CjAn2nJb)kGz!9}FKEGN6m(U+ zppGqW*88^5(js?D^|Om=7WGS8xVdjm|W}rj+##8dW;rt;GG#%%}B>uUEbH z;eFYIG>2+S8}43z_E6}E0%vYg3<|4LS(%Hpp`+{VqoT1Fz#3V*bmJy6+MYbCL4MV$y{4+TyRCKFftQa&M`Ox=v*+P6*~_G0#n)m|={sG$VL>z%b@GBV(5e zt+SnSSL>0SmYN8k4=&%nCyz1hihk=+P4^Bz0uMdp?%u>9vd%3g(y$r5cYxOn#8EUo z`w+q9-(vLrTMJQ~5JeBaCqfY`y>laz4H&N&*AbR~Jq|-xqDcAotqpw_q zDEjUiJ<3a|^nqnU@^wOT190@H6IEzEII6QD&{^QgI_9eyM=US;KU~*_Xu1aa9%<>{)0T#uZT*_ z1#TbGQ6=jF^w1f-j;PAOyGj;N7*6OaF*CJ^Z^THZU|%}AvO60At8NBD?{Ke3Y;yt z`{1a_X+@^=^nIxZ0{2u%XAh2^P^2b*29C;b0O)B%dW2a?k7g6u2%tw6smWgn9DS)t ze2(&sV9*I1J(EeVw*uD~;W&YNC**Yo7cX!hgmf<8&VZwC_!}I8O8SWk$#H}%A?e*~ zRDgbjLo$s5c+s03F-OW=YLz66e%QXd@t=m$(x9JQpO zz%@m9CTdJAX$%foBq0DjKuE1t8ytd?PNBGvL28b=Lgr=&Q^8boOK{{&b6_Gks-=~{ zg(2Jz9M!U(z`c1$sqq}oEAH8SrXgqWfElaQ#fqT=)B+3uJwP9*3DDDJw5Ub^VL%%o z5@-oD2WVAo1+)be0IjG&fFBSJGy%K-Z@?e$0epcFAQ)&t4}k_C5DEkWwEWV8oo>J! zct01I2h0bufNbCzYI7O52$TX>fJ*>9n@wwUM<5!YhsDoH@B2m+&kBw#eq2N(?G1BjN40WyHGKwn@efK5*_5f}#y2NHlhpf}JH$OI+>1;8v| z0FVM;QqpfHYqfP50KpWLp;0r)c1iuH~0v6~O zOMsqj%>`(Q90u3}jQ~erDL}i_3Sc>~1fT~z>HEjDv(QFD8wWjOJ_Hy_PkHAeKsyKh zoWo1t74RB(1H1*^0q=niz~8_};1lo}C1N@IjTHNXU@3FrXTff|4wU;xwt^Z`S_6sQfz0bRftkO6~$7@#u{3-|yYfC8Xx z&;qCnm;rTwhCqF)c>}-_umWgrv;?7!KLC1IA_y`7P}1H>dnN6Sqk)}3F;E2T0O--;mB4Bs3!t5c z1!%V!4)g~yfJ`6`=nf=*cBMW!#hp5OokZ1RMsA0kk>MW<;CMK43qv7oew_O8|Nt`Z7RICvOJU z0BZpajL(_KKMSBeWeh<3$T)!Zi4j0AAPLBW3t9AwE6E7-0h*$fn*g-=oI`>mFi4L* zZvi#}^o;ji@EkA=m<-U*C8PoAfIH%yfdvS^1I!Vw3oHWYc-IM_BV8BZCO}8I#WZdg zA@M+<6F}SWZb&*YJ%Oa(0T_<(cHk6n95?~cX=f8K5TFAM9bi&`en0{c2iyVf19WIv z0Xu&I%YoIvDqtm$N8>gGum$V@2cQvP57+>7pg0Yfz({T2IKmv{Bw!*y`~G;~Jn#&0 z&jCvF68H-46Yvp`p=-(@t3rN*{0@`@$}hOkk(U9afF_^?$brv@`vFuzm>vv&2Z%MP zEa?{~Mge_*WFQf^1Y7{ls)f%BI&I%GX!D{6YzhEsws@dBK+PxW6c!Cp=BWS~?+wtF zodWa|bP5xH1GuRs)oqDkz8tHci76u)C%KXiiFkdLO1bCv87n1yd`<7`(L0ayExo}2 z%_5pnoVZp_Xl32TLZK!kxm7P9O-n_BAw2GbdaQljYhnO zAnBAuhe20+{9a3CMZ18AG3 zt+@k0dv{lW&H>>-3xLiL%>dedXK$Y3*cw5qAo(bkPi2#NGD~KH0LqFiuNnOgqDt*ZXIxQI z5;086ml&orbXxdRG322?x9KfotW-Bg9*|emBGl|;j$V|eIZz#-Fr^du-=!1dM5*qk zx?3oxrplODWxl%R zC{Webj+BbG{ZH#O9>oSChj@QO(-9OM=#4P7i8wMTd1Z%abWwJ3AW^-ds5{JJiKgm` zO`u*!;>D&^=i|U90o?&At{XrDT)o-&$|=R{RAA669tf|%8il+ zE*0nlqyWhPr6D_g0pdkn2scqhlG0BtQZ%BTn7Un@$YNj8aVB zRRhJEjM7USD3p}?hgOf4fU1#HJ@4_mZluM9l2I2@QuVH*al|`dr9P+Cdz-qGoZ*|_ znhF=KQ4fhVqhwS&8l}8Nb8$S0$yI(LntD(ul&n=AW@0klH<~IgeEom6fVyST0a|}( z-6Ka}{cpz1v2wP`zKbRO^x09g{JZflCa3B3v*AodtD+;c5K~L^S9OW^@4Do7RsMaq zSc?vcV?!)OeYxcuv%(SeiSx5+cIq9h-gBZQO8T>FqR4N`B0BK9RYBbub^poKKbI=% zlNL0TXsr~dapi$sd9;e&{nH$cjDK{o=&d;BL=S&XJVPfCFZ6E}xmkh7?T{6*C`l9x#_P zFJp`iHzT+S*a&O@)&uLf{+}6N`6&cv0VlarpP4q=w-LMrlmb_{;4-GZl3cz4TnDZJ zH-W2wI!9>;6eotu5dI822c80Rfk(hy;304icmUiNK>8ElG4Krd1bn2E%HIfl0Nw-d zfVaRK;5G0HcnQ1!z5-u>YCvrUx4^&;guer|5S9WAK<_b8BhgC_;Tk}7fSwtkj|wya z4S=2x)uQjBRz;v1K;PCOk`mSwB-~?C$^#DtNI17Nj zrAvB!paIYjum`Fraj^xcARB<3a0DolcsoHhf^-0!fyRJ4;0Cw=u7C&76G#Apfgr#O zpwG%_booFA0s#Phjl>%uPU(k>ub_yDNcI4l094C(pcT*^hygkQaX@Dv3TOwk1-b!U zf!07%fbxU`&45rK1ZWAg0K$OgbWcisLxY(TMF3=w-YIAUkONd8apXuBK_>^OaIs(y zvYDFXc(eKCzvtOb#x_hgKCu@DMVd?qje7$nFnLFPbS2d)8Bz*V3W zxB^@T<^q?13&45c9Iy>QmwBqzI2yU4BZUZ4Q*H&wq0PW#U=lC_$OVRSF5mHq6Af&8 zU^u9JfEsfcAo^`0=oCl(=K<8}R6p{Q(o&q*IHXe^v7xEa#Wdo0r!oXP%6|-a@{xuM z4fIjKNPwIpjwXc|9*^)uU<@!?;He-oPLqb@1c1_w1I7ZC(+#7sD`pZCi3O<3Rme;| zund?7%mStYQvl)%0OFh9Wmn{G-^)wD@BfJBk z!M`1#Aw=70F(mDsw5{$$xCr34RU?XG05WlwXe2qq%-k$(ZE#VbDe3{j_W@3qk(yL< z){r6@#?lzhhmqQI-5F_P3vVZ^LKa}FV}ML++-Xw7LVs^9rkks~lZ&&HGq;|R8fm&Z zxk|VaM(V7A5ch=wE{JoIN{tl=@H;*k5dW7T3?RRgi>G7>Ok?lMTWFov$YE4s55#yl zc{{mrL#0wvsf#PeNu{ogD|cKft!?J1+KUa5+;PKdt0=#*fl^g+XD3hYhg6!V;fYd{ zG!Sq_;EaaU#S8(}dZ~j<;(sheCWVuyCugQ9HLLBeTIp&ax(nMe?^#^eQdKnS%|&WT zjWsCHM^l<;?oJiSrvJ%|*TG#+%#Zco*aT@^oD@zj+h1r(_i5mZpDyN7L+*f9^4Nt zX%fB>lO&hAIVQV!^-IheAZgS3YGC((7BzL5Gc|eB;y-Pl`ndF#>C{6rbeU4_s9fqR z?XAOUR+HK{_>OAVfe-1r{D1E}(X-5ITIl`RD9X*rjf%?G<=P@;^aP|ZMN0Ai%1f{G z&*Oq!9aK)K`p`{}FZ9XE@j90;S4o#L^}!(9@AIgdYYTUwn$)e%=vsWj6u-6W2fQ$N zC)Csv#~pnx-9&04wbSSPszdtg&+>1az$Jr2Q?F`Bk{)l~Z)J{ISA=e^*D`0v{{ynN#Os$Zvdyc=i{$$L)ENorcB;{Uv- zjygQ~ug@cR+tf1k4Y{-R;f1duw^kdny&>1#05a8(y92$B_#fk|42YT5s?nu8KXWcL zf))uh;xUFt#AQX{c6=JIqmf5L zwd}Ltl{?NQ#@rh{l$mSHokmLOJY&wep45c9V<6S!GzZ(p zy092zqI%mjuld=lwi{2adLd;nkDbW3M5M5Xr3oh70$pi0W-}LTC^fCN85x}5LWC)2 zNd=1YKpZHQx<)E=fK+G{d}ocSEEW7^c5#gEPp|kg#j@mLSrv(XG?uz?LHg2K@Ww)4 z>Q<5B8&?rk;i0}6w_0Bsf~2qYrKa*cbSLif@_ul725{hi=(pIQ(qCN^{18M%(c%aY z8$}qW;_AS88cUlY4>c$RYlMZ5&k|B$LRd&DC8bIWh5fGX72F>xDf%J$_iHays#}FC z{8(~THGBmrwqIqF!oU*;7}uqCMO7>EBF~%9iXruHoM!mdq4J!sJh19Cvf^i1Y`;V3lX~4C{itqX7-Lh>1e$O%;71PvQ*6kv;W}Hpvs3WvMo!&@+ z)hch-r{!hY*J4#04%Sn({X}$8bXgd@zxq_s8NXX(1V1@TYiXm3s?E3NI$BHf>P&CQ zA6{0qF+VqN`uUxz(*sU=IBGZKYBa>^Dav1GM167LJ8HvkribP_AO1XC%UV@OHz#a~ zxA5!;&L{7YKo?b1?5?_fXPq`jRVCnngtt^|Ib9oRNVS?+^Kb~r8*a;Wvypa_*0kmJ z*hnJ;X(?S~$2r+bL*!yQm0=@pnys{jOtoZk`)#D=;&S;PoD?c;0OErG>j1B4s>;jA zze)CoStKqxf5`o7>#CO>86vI2WmL!Z$e*di*(07Tgk{;4JF6>gB+UMb@$er_PX2Tz z+7)M|IQakLS;+6+e_Emcuo;V`Rq7IPFRqx=zn_9)*Hl_i#Ix8Rj0*kzFP7t9JE@{I ze_iAL&|sqL;xXn|Tk1Vahx32EGFF=W!pioiCjNB{{Tr|Uv{}{p^Z8R;g8on=wS7Zv z>#SVi%B?2$Ri&!_-*nE;8S~5SN9B?$l_;J||4k!T8giAJ(d^IX{ECxwXP=7Aq@t7l zqlx;TROdh6HGex_D;%mc)+?=Qm1ou;j?jM?DV5vs|8@*ijIlo~GE%XCf8(~Xs%R{}_oPDc|C_T=<#8mQ9V>OG=bvxX{_Okz&OEV*$>AJJQP^BQFI zs6IBX4t}Es487%L5)lwKb%*Oor6DP#K(?oHIsFl%geKLnL;5gw<|(gn~MyW*7g*iInu4~-*j-* z_uFv}#9MYAIBKS+We!Nl%#?JAKYjc~gjPOcyqrAf-5(84u5LI6Uky(#C0y!Sdq8Fu zj>hz##oyn{$@r7n(;nsGkl zOg~&aGY2NcXCQ6Ssf3GrWhLv85T4MnxANPu287=w}KWZ!Yiu6m}hO zQ61lUca~y7snQk%Ta1OWuq>!VKrB(gh++>2(s2bsQ7jaV3W+aKY{wQwG`whhF^N%Z zNw7SPF;U@fjU^WHG*MCiMqirxzPWREFBr)4r@vdiZ_b=KGjnF<%6F)GLfpK)B8y56y_n4ePl4zC8Pm)zQ{FqX<`jR{pR&R6V< zP>>Jto2eLRwhs*6Y;Uj5|M%vwrw0_q$$m5%48wIWxMt-RJJP4x_b*f!k7elr_C@1w z>>o2tLE84GjXbSqe-^2rQm=Vi$E{G1$o_PXYc^g^Yl!-8 z&*tS{%uyJ7BFHA11+XI#6dsLSu0@Ez!R{CL{@u>~+a4C^lzIa;22_6l;o-KJb&ZYT zm37Y*#BC70&(j7C!d^2NR{8bG##4_`tERMLf$+4udRWBy-&y3SAi0C+3etL1fYB9< zB}<=esOe_^i^AA7i0no|`gvLU|3vg?^CWWcQHAj<5Ug%X<4(LaWblY0)VC>L*GP)z zX+v;o0uhnY9;plC-@g0+t;)oh1cd9n_QbWC;!R(VP>@-Xv;%29R)OILMwoR>YHs<7 zWQFlbBwgpyPlDkN#)6TXrr+JxE=pni1cV1WZEx1;`u=tDF9lH#CSUY~l3O^}!NZ(E zp+T;Zcb0A83=!t!2L`!jr+z;7UyG`qyr&?YWhDK>@p~#pSLY~5C=hPvQ12e`L+?}t zDaaHc-asn$tvL97-Y{z!=?v#FSBA>(##Vn(9Tl!5T2BwgFy|6*4uZoCxVFQ1w?nT# zc2GE1f$)m!u8Z-FoVbTdzVTgi+0O7HMNV^%K*YCXT1q88PzHRe55Z;^Kd(qJMr?A9;K_y(A zw0H6*Anu<#)i?D0saxQ?U4}?$0 z4(V8dtll$nOPk=M*n@!{fOP%j!NBl27~ELt559OXMxT#86O3WH5JXlE1K}14@8q!U zX1|ryQpSP4dRQcuiZPHdeeCK9=tUc1MertJcvAbW?~MBaL~LB~I@%RW;c3jdvmSS1 zo8fo+lcGfKwO|# z@T82?N1J_pEzG4Y0Kz+KiN%<1zg3jiDacYFe3#>cV%4Cys>)0S**<~JOkkZ#V65XH zac^+Ks?VbKrKjN^O=i3fg!lDN{F08GE1#iKkiUTNzUSssKlY>j>-Q^&$3)TlebRec zPI}Msf`aq|!j&nid-1PXZ=Fu(NT{fnE{ne7nka3Mv;>qD>IZ?6tHr$@9uG zu_YHD!26X>)sw;|W3$Wvf<3fvxEgaj5gpO7skeL6V+sLBn7XzQaAr?{Jmdw?~{H zh!+dZ)K*sinNj^|PS?S_0dr3cWFo~)f%?mkluy>Cz197-@b8A0pKaAm z+GubX~i>SA7Sbdp8%F_QA%vLBm*c8%*F{JJiMeBWdvG6GdjX=1{%-RAuB7m?@m z5Q;px(49bdpLBC@FvfPXC}l0FTMvX=XXEzecbz-cF9H&RoY7udFf5!4NBlEI5r6w* zZu;SgD?emvH@tBPftVI5GFaGU94OdVFHN3wcd47c}-=}>drJ{D(HDsHWhnZwR8Ya9w)QJ;COPE*NCvp;n)&JssMCY)uSwW zIF-3(ypk=7TKfDe7yl0zJHujl!%I5=R|i}d4<9&k%dh3nL|T6w3yGE))fIM!7O3X& zwEzl>%2EA&u{9Z7KGU+Mw-TV9BOOY^If=>yW})@Y5mj%qd`PVQ!i(_5z2RE;9|L_2 zvNj3?-bXzvMr0*bu9&3|Bxz2RoyaWNy&Up3GAB!{8CBM#%VeG8TPedPOp&>hmDB~L z_nj;aaQ&+&E*+}Xl5Q4rqh;wVq3!KFVFQ^J43?z1i>F@oD=^+%hTSv{>3yh%yB5i& zdKIG|3n0jzHqXZS5xvTrBC?8Bf!jPI6xVnZiQ`E>D_s=!424ruM-bUVB67 z1t(0FA8TCy`^uR!&l?~}axo#QGzv_{8IxAlb#PKI>tKgZpsYw{T}pUOP`|M>;<3#ImH@V4?~Ld-i{wOBrEt~mhX|)vnmeked zJ{$~d%;#^SX+6KlJ}+41N2mF-=+XUxFXYEwgG;4|Dn^Tm*cH6vy4^gs`|?o# zE8CpRLr^0SMIYI6qU3TmW}j;woze?oeKAt8HcMz@A5p_b(VM?>>%pgb_Dn+r2L+GaBnlVODZlrx8oVs`IS?HuMBqUE$E9K#vn6w8!R+T#JV6K$;c6{SnG1t< z0fG0e^$#6CK5}Jk2N3uQ32TrKXekIm+d$y6cPt;;BBzH(i*hzx`0ihj7mPp-RQZf< zKps97_a_&7YPsm*b&HD%EC(Lvs};UvfJQ%(Ul9ZyTOkw+?YrRfr|y1bAV|v@f7Lnq ztO$Z`(@F5u!UXF36kW{HJX%;D@km4fUmnq!V$?$m3n0`2uZR{GU6Lu}wNon-d+01p z?A>VjIOfoH2#IyNJH?b>LUNYKSc0Le*BUB~L#(9rwbJf2RLPk`*3$kG_BswKYf714 zn}zE{8rxv14?`|cJMaadvS~!OtKR5>+dO8XbEgm*OcT#y)(`YaZ zL16Hum+fO(?KSXprNW2;!oyi#?sz@SV?xL#1xcxGP#7zK z@PT~)x)j%8D>IKM$S2iw4{6&~mN967UlNv4$Hij?eAN z1!;<|rfM+@SF->;HI%VaYF*8)a`uK=tta&k)}^NVyKGZia=631S1)0fbnj#4gdY?D z;=e243>voseLk4qze1HOm^D3E0ZtHEtYme)^uGCNbJFu?7=3cEAD7~jm!F%Fm6nk@ zd*Ex{0f<=o`r}4t@C~8bXUvndtI(4cEMr}1%qn(NZK!cs&9-&5!m15o==5HeW-IRF zb(nqy;xC2nV--;4k&C7aJ=n)GXz70TiG{TF8F7FmvVQ*LT?2t{oMko+eBR;b1FnmqP7$9kH1uC(MF>tRMc=>9nfkfb2(05i{lPSvvx zwEaBu5bu^=Vs5K1FmE%%kzy}EZ3E4|z}ApsFHLtcTts1S-2|!eB5OmX7nzf=sPy>N zMb^>$_zKxqvTj^+2O56Kq!BU+GG|~z7cMh> zI_pczSE4X@bR@qUO&*;o>pEK7nj2_$CdzR0oioMVWPQw!9muZ%{9CNM8E~YFxA2P|B^gA?j}4btIL&Qfo~VMg4eT{s5uoJR5qrqG*-P_~W*py#te2TH{vqqa^uBcCCX`wK5OXtK&7Ox0aTZ-o z&SR!yk_KC!uym#mq>fM7N_7Y&UIjU!y~c{derMJ-^-o!#25z8YIm};Tsp(cT{14XE z4t>r3xFEVTxo=PH%Fv9auSPG{wAUm#W@RVyuEsAurr$g5YOfi=O~fd9 zt3ASVQ)Xlo`s5a534Uryep0$mUP|uFlw7K}(M)e^X3$VCO>b;UOU~)F4w_MRH0&|+ zp@~|JmX>&G@G;#7>>_1%)~rMbi+hcMUO>*?N5971vv&9by&Z4$3B5HtZFBhg4_ZoB ppI{3Al69-G?W4J-X}?B?)jIxc&}sN5Xu4WdZ7_aBkFwRv{tw(s4S)au delta 45123 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 GEB*(H%$qy_ diff --git a/web/package.json b/web/package.json index cf8fa112..ca1f9282 100644 --- a/web/package.json +++ b/web/package.json @@ -15,42 +15,42 @@ }, "devDependencies": { "@biomejs/biome": "2.1.4", - "@react-router/dev": "^7.9.1", - "@types/node": "^24.5.2", - "@types/react": "^19.1.13", + "@react-router/dev": "^7.9.5", + "@types/node": "^24.10.0", + "@types/react": "^19.2.2", "@types/react-copy-to-clipboard": "^5.0.7", - "@types/react-dom": "^19.1.9", + "@types/react-dom": "^19.2.2", "@types/react-syntax-highlighter": "^15.5.13", - "@vitejs/plugin-react": "^5.0.3", - "rimraf": "^6.0.1", - "tailwindcss": "^4.1.13", - "typescript": "^5.9.2", - "vite": "^7.1.6", + "@vitejs/plugin-react": "^5.1.0", + "rimraf": "^6.1.0", + "tailwindcss": "^4.1.16", + "typescript": "^5.9.3", + "vite": "^7.1.12", "vite-bundle-visualizer": "^1.2.1" }, "dependencies": { "@hookform/resolvers": "^5.2.2", - "@tailwindcss/vite": "^4.1.13", - "@tanstack/react-query": "^5.89.0", + "@tailwindcss/vite": "^4.1.16", + "@tanstack/react-query": "^5.90.6", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "framer-motion": "^12.23.16", - "i18next": "^25.5.2", + "framer-motion": "^12.23.24", + "i18next": "^25.6.0", "lucide-react": "^0.539.0", - "motion": "^12.23.16", + "motion": "^12.23.24", "radix-ui": "^1.4.3", - "react": "^19.1.1", + "react": "^19.2.0", "react-copy-to-clipboard": "^5.1.0", - "react-dom": "^19.1.1", - "react-hook-form": "^7.62.0", - "react-i18next": "^15.7.3", - "react-router": "^7.9.1", - "react-router-dom": "^7.9.1", + "react-dom": "^19.2.0", + "react-hook-form": "^7.66.0", + "react-i18next": "^15.7.4", + "react-router": "^7.9.5", + "react-router-dom": "^7.9.5", "react-syntax-highlighter": "^15.6.6", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", - "tw-animate-css": "^1.3.8", - "yup": "^1.7.0" + "tw-animate-css": "^1.4.0", + "yup": "^1.7.1" }, "trustedDependencies": [ "@biomejs/biome" diff --git a/web/src/components/memshell/results/multi-packer.tsx b/web/src/components/memshell/results/multi-packer.tsx index 7500b8dc..fdcc2bfb 100644 --- a/web/src/components/memshell/results/multi-packer.tsx +++ b/web/src/components/memshell/results/multi-packer.tsx @@ -1,6 +1,8 @@ +import { DownloadIcon } from "lucide-react"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import CodeViewer from "@/components/code-viewer"; +import { Button } from "@/components/ui/button"; import { Select, SelectContent, @@ -8,32 +10,67 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { base64ToBytes, downloadBytes, downloadContent } from "@/lib/utils"; export function MultiPackResult({ allPackResults, packMethod, + shellClassName, height = 350, }: Readonly<{ allPackResults: object | undefined; packMethod: string; + shellClassName?: string; height?: number; }>) { const showCode = packMethod === "JSP"; const { t } = useTranslation(); const packMethods = Object.keys(allPackResults ?? {}); + const [selectedMethod, setSelectedMethod] = useState(packMethods[0]); const [packResult, setPackResult] = useState( allPackResults?.[selectedMethod as keyof typeof allPackResults] ?? "", ); useEffect(() => { - const methods = Object.keys(allPackResults ?? {}); - const firstMethod = methods[0]; - setSelectedMethod(firstMethod); - setPackResult( - allPackResults?.[firstMethod as keyof typeof allPackResults] ?? "", - ); - }, [allPackResults]); + const newPackMethods = Object.keys(allPackResults ?? {}); + if (!newPackMethods.includes(selectedMethod)) { + const newSelectedMethod = newPackMethods[0]; + setSelectedMethod(newSelectedMethod); + setPackResult( + allPackResults?.[newSelectedMethod as keyof typeof allPackResults] ?? + "", + ); + } else { + setPackResult( + allPackResults?.[selectedMethod as keyof typeof allPackResults] ?? "", + ); + } + }, [allPackResults, selectedMethod]); + + const handleDownload = () => { + const fileName = + shellClassName?.substring(shellClassName?.lastIndexOf(".") ?? 0) ?? ""; + if (packMethod === "JSP") { + const fileExtension = selectedMethod.includes("JSPX") ? ".jspx" : ".jsp"; + const content = new Blob([packResult], { type: "text/plain" }); + return downloadContent(content, fileName, fileExtension); + } else if ( + packMethod === "JavaDeserialize" || + packMethod.includes("Hessian") + ) { + const content = new Blob([base64ToBytes(packResult)], { + type: "application/octet-stream", + }); + return downloadContent(content, fileName, ".data"); + } else if (packMethod === "Base64") { + const base64Content = + allPackResults?.[ + Object.keys(allPackResults)[0] as keyof typeof allPackResults + ] ?? ""; + return downloadBytes(base64Content, shellClassName); + } + }; return ( ({packResult?.length}) } + button={ + packMethod === "JSP" || + packMethod === "Base64" || + packMethod === "JavaDeserialize" || + packMethod.includes("Hessian") ? ( + + ) : null + } wrapLongLines={!showCode} showLineNumbers={showCode} language={showCode ? "java" : "text"} diff --git a/web/src/components/memshell/results/result-component.tsx b/web/src/components/memshell/results/result-component.tsx index d957f3f5..bbdab73c 100644 --- a/web/src/components/memshell/results/result-component.tsx +++ b/web/src/components/memshell/results/result-component.tsx @@ -25,6 +25,7 @@ export function ResultComponent({ ); } diff --git a/web/src/components/probeshell/shell-result.tsx b/web/src/components/probeshell/shell-result.tsx index 72a30669..f91ffeaf 100644 --- a/web/src/components/probeshell/shell-result.tsx +++ b/web/src/components/probeshell/shell-result.tsx @@ -40,6 +40,7 @@ export default function ShellResult({ {allPackResults && ( diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index bc8b4687..ae962470 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -5,24 +5,38 @@ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } -export function downloadBytes( - base64String: string, - className?: string, - jarName?: string, +export function downloadContent( + content: Blob, + fileName: string, + fileExtension: string, ) { + const link = document.createElement("a"); + link.href = URL.createObjectURL(content); + link.download = `${fileName}${fileExtension}`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +} + +export function base64ToBytes(base64String: string) { const byteCharacters = atob(base64String); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } - const byteArray = new Uint8Array(byteNumbers); + return new Uint8Array(byteNumbers); +} - // Create a Blob from the byte array +export function downloadBytes( + base64String: string, + className?: string, + jarName?: string, +) { + const byteArray = base64ToBytes(base64String); const blob = new Blob([byteArray], { type: className ? "application/java-vm" : "application/java-archive", }); - // Create a download link const link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.download = className @@ -39,15 +53,14 @@ export function formatBytes(bytes: number) { if (Number.isNaN(bytes) || !Number.isFinite(bytes)) return "N/A"; const k = 1024; - const sizes = ["Bytes", "KB", "MB"]; // Add more units like GB, TB if needed + const sizes = ["Bytes", "KB", "MB"]; if (bytes < k) { - return `${bytes.toFixed(0)} ${sizes[0]}`; // Bytes, no decimal + return `${bytes.toFixed(0)} ${sizes[0]}`; } const i = Math.floor(Math.log(bytes) / Math.log(k)); - // Prefer MB if KB value is 1000 or more, or if it's already in MB (i >= 2) if (i >= 2 || bytes / k ** 1 >= 1000) { const mbValue = Number.parseFloat((bytes / k ** 2).toFixed(2)); return `${mbValue} ${sizes[2]}`;