apt-swarm-0.5.1/.cargo_vcs_info.json0000644000000001360000000000100127520ustar { "git": { "sha1": "9fc705abb5e0c8d9d4077d68037d6f5a0761894b" }, "path_in_vcs": "" }apt-swarm-0.5.1/.dockerignore000064400000000000000000000000771046102023000142220ustar 00000000000000/Dockerfile /.dockerignore /.git /.github /.gitignore /target/ apt-swarm-0.5.1/.github/FUNDING.yml000064400000000000000000000000211046102023000147100ustar 00000000000000github: [kpcyrd] apt-swarm-0.5.1/.github/keyring-screenshot.png000064400000000000000000006024641046102023000174470ustar 00000000000000PNG  IHDRktM_iCCPICC profile(}=H@_S"E;:dNvQqU(BP+`r4iHR\ׂUg]\AIEJ_Rhq?{ܽZiVGtLcb:*^!}Ƭ,cNh;]g?Q|"qMAv \f>I6л \\75e ٔ]OS3 0p ty5q pp){ͻZ{L+rɾsbKGDqqqO1 pHYs.#.#x?vtIME4v7tEXtCommentCreated with GIMPW IDATxw|UZzB!A, R{_u-S\umkYW {EAz)i73?&̈́|?ys;o{()    OK    ƤLM    p AAAAI    GHFAAA8B5    9xw׿[oꫯCAAA7),,$++4y 4UVg~CvŮ]   8'|tƎ=ԩS8q"}Uԩx7G#   oofii<3TWW[.쬳bҥqAz-BBB|rƌöm())O>!..0fdggt)//)((СCYnݺ?pUW58gڴi<Gu8رcٿ?3K.[an&9o&oAaa!yyy̘1pL~~>.w~>} **T0a8p×_~@R>l6mDyy9-K.>y׮]7o,[[nEX    0L_6lǍggg.K,={ԇ ;N=!!A_b~w~jJҿK}̙~e\s5UUcʔ) 0]QgqПy[ooѯJKzrr뺾tR=11QK.D/))[n/[L_dWVV걱w'|R'xB_j?'$$QQQ~O6'_|~e>Yҿwx/l_yy>o|8 .r~aw |'22KGDDGzj??e]Ɣ)S[A=3f ~-ӫW/:wLffenݺ;tRRRvevi<h׮a_g͚E||<6Ə?=zFzz:!!!̛7ϲVسgngvq!    (4H#F/gڴiX222ر##Fয়~⧟~ꫯ&'' OT9ǓJyyk)))h/7p\p3glRΚ:Ẏ$//[sf_AAAA8QK֤2`}!H\.QQQl޼N:$߻ۉ%::SKϞ=ٳ'`l*k!C(ܹosB<fܹ̟?@YX3{l++?~<%%%|ǼkkN?tg̘;靝ͦM?Ihh(IIIz-ZG   ‰_GGE4w1}tqӂO(--Gm4YgrJCUUwy7g}rcҥK)++cƍ|W~ɠL^/`Ǘ1ӿGddd ƍٲe ۷?&3o믿}dYlzj-[پ}{_r%W . >>Ν;s77    b }55j< /sAAAɚH1"33Y1 n&q    ML    p AAAAI    GHFAAA8B5    nAA1L7n~ש' 1vks¿}/6<8X|"#_?AAm?TXO W9hjC`b͟hKTмVcg*Zm1CqҪ֕Ack^6}mk':YA<-[uV}Vl5:{ilN?3:`t%t'Y~fחn(JMnIoHiNC߫|/@b=ىjyxWh^5ӯ9o̿᭍м:{id~י(`ۿo3߬`R!1*W+Wm vJj?k{xE =/+68n j_od<l|_qy#`ϸ%0|B! ZxǺƈsnCeߞj<+-Ws<ﳏs}>D-k0}&>{~ Hx;6 55\!vM9S݄D+xIYΞhv0gG:IQuVܦZ5L4=b]q 50ne9:{jmU2>o3]T7$py}0HAߋ~kI+#9wk}uM^-,ɃYg#Zfzߠ(HXiۤ|+_v0V >G`fmVKO3y<|9`]PT }r'ˏֱѐ_Xg8n];-6[%;6怤6ÃQ]qݗ,pB& n/qZW&uM䮩L1oxnW]SU'bYm YE!}ˏ05d*7v ap508%ߔ.M N'qλ-4 7^hix=h|02ɱW_V @y Go? w];BA1,Xr7;߬OK% lR<1Qd=?r3Ϭ`gsHםkWYmSS;%٘6rp'k:'1u?m${ͰET8<ǻ6 ƾ f<m⌙qUk2~5&NJ,B{@`6gFҠ߿I'8YiAʛ :aq %yp`cTfHlzɓ2G_-߁o~KmZUXntJ,`sA|+{-Wh2w7g0/v 8P /~n3n/߮+΁;*nN_wC3`򨖭߬o0  qpӡK2D߱O x6w„-|?-߂0zQgWamWoeV1-GmumÌ{v쫓O&޵&볎\;%0*EHlmxzjG'Ϭs2vK㍇ 44>T@+d}R㊬Nn:wJa^KAzȌ/TvS QЁ6b>;pY9 Z{ج}jY[o}ﵣ[f3ϊoAwN윯Zυm?Rݔo+ w\_ݝk<m8:30-\m<\_%cwH4flT1 |12 C{`x1p{C:tjg<9>=AXc;c Ozs@-fZ">毄J|cfGo%%fXSʱw_cش'tYf|>k0Lٰ , F:s%,Va ߀=#¦fR9~5ymtmgtjuu/سHm`0ОIl+yxfwAonOGk)N~ǒf+2Fr,ɃJhڬ}fYS5X񲗾1EUafQo3j[">~=k^33H73n^l-h]UkV7kRjquƘ0}yVߔҒ1G6ٶby+Is:vtciΌ`lc^^K_CCzK5o7cBPuڍi#ZxOl46_`$B;ҾVd̨Ѹ].XAdMdMbI?b:(w9cӵoA"T.79Oe1kfPb&?L3lkgsJo ]oE)ƞ2+^lA~Hj`B#Bh.FeNUro ruRm5h_3U7Y2~vf͊_u|%%4MB0Zkx HOiK_^1̵468% eeQ D7܇oX[E$P7+s'$KeiiSX[no|oT|f6c9}ߪ 7z=i -cb_؏fp;?,n|4xVE35Ogm? ~Ԇ1}5ҟ@DG74nL-(1U\j2F^a۞ߏ}~/3 Kau sZ63_ Z!˷ VhTT*Py ե:O،Z۟b,E+4]njsjg39@vzdzc05VuS8NJkѸnF2bb}+4Rme>r:Q7?Xys 7f7hggey0TzMӦ lNJR,o # OC.#t8Nmc-ɒt&ݜˎ0TszOr #6>PhLPks NDw8qC?nr}Z2׿9 ~/4,OxJyf7{'X2t4`|3îh㸡-|+Z">No,Gc`v`c/ǚ_7?o}́H6(>:jlUϙ;,><8N+7Ai?ј!pMFSvяri~/9V{gmw.d6^2f\? ~Xb%Vq&%Q#4nIc*_ uRGgMu3>Jvya]U_|K^Lvr]3X 6Efl@c%yHBh*qҎ9qW_;w u6%o`=/6h~K yu b uruc-9C.UoVLG%(%% t(٣c+ox}j$06@mfc_(ڦ߬#af+7(>3L+aYkI^^o?6 cƛ0>)ᑛ!:˜1wy鵙;_׸9yo.2{/kʸ={ح L~1tng\]^2fӵf[)_ou b%5fAXe>(2Q-0u,w_߽h ޛeͥ=dCe,?(.0η~l|cf|ۆ^x#LLxc V6{lCr(+-(ۍYu$3 n+ɧ%f>fr48Pd~}pڇ _d>^(ߑ6U+ş7n aI<;hC9䐣Eџ+ V_>rZwڸnGl:-mߘ({EY/x=Krq<)`AASv7)0oLe?~wZ?cӜe/벤_ *eZ{ܭpc2[C bA!XN]jpV~?ۼo q<ߩc1ci_A ?SOK    ƤL,AAAA8d    q$kAAAA#$Y#   p!AAAAI Lp3\sJAqݟO:o q hFyv4>9aUZ5ػXe IDATg*<$Z!R;=4/V[{ꬠuemXM_=ډNVPl9;tKVz_`U'je[>LNXyDh$w6;j*[sXe^հeî&1ZߞoV}ܥm7N9'K'h%yblEVxl޻YpS{V@.z46Jrr~7;`7s7HEM%Vȿ2<]),;lHRJ|Tk\)Ư~c o~IolܽE uRۿo3߬`jv>?E۲;(BzNp\~q٣Q%}- A8Q5ILQ׭ᤛKh*̙&$Za#Nru,6~_a]szpSt[gxnˮZʴM1;S_i(ٽPcj/! CvPwfIh6[%sI ꆄTPV7oyٿR9{կ{-o`V;nTwv)˾e%y7߶l_`L/4;+}oqZcn]稖?l|,oi&=N#9.NeMq~T+w)Ѯ ߾|dhƌ_ "$tlܳQPfƏ/r| v ˲ʘq6vi>9`[^6aSlinr2aWQXVKʭXe~6 ?@R\2Cθ.^wΟk2m!¸6oW}iI+#W|kbwƤbލ,~%`;mEQĴ gE?3y\HvN&_&:*w-`f7%E#G6pVɈfu+qǷmcK퍖EEN~VY𘇂̆#\[ NQ]q. ;54/+d3Ժ2lP%w 3%:[u+Q* n599T> .*/Ȉ-ϻ؈Xt9ˆ]?؉onsb:\< 6 aLxnw';hĭc :*)pYjʭxg)pa+9Чc?JJ۩!GTUrXG0wls24#p?7Y:e+CBtGFRVUT$&k9EޮQSaG6ZƓܪ=,2a[k@ 04 e-&;'US^Y[fUVci"4Mֱf~+D<}~qq6؆:o^U9Lq=λAiݺ8܊zz:.ldMT)8gq=?P,qݟq==3p|KC۵Np=Ωvpw㓛g땂s꽸y״gp\}vJN8} uF/zct_6uq_Χ_\OOַ/ /aBX5Yf,r,ǸV~Ym ‰QNidژPYN6V%m`+.꬐=wD¢xc ^2Q I=UgRJ}od5xdMԎ7LLD+TMP!Zӿs:_Ⱥ'3! cHm߇vɬپZJBtBx_;9wDFZ7Fbl; - aXLp7WNyz3)Lg+9c-<$InY+#om#*,V?P.$#[盵ϊ~V ȸ@7k6?y]Jd$ZvVrW~9TW]!b?oJx_yn`=so襥D [=чuF(me_t F2@Ilk|3CĴ}=vw6<} w_o/w}5g0Q@?履.܏<.N}n<>}m _ Ͻ@Ts}1w߅u5BX?U, Za-J1n*A8!p4otAW:J"_U﷼dN~;m/%7}/vº_옧1l,xԃCΊ#>ڎk_Q {8fr݋4SKDJT؁3(:pCfU܊SXHů0k~Vߔ+Kumg| }.tfY_-M߬Vo?GKVN՞j)Xm˷.i0 ĊK}3se/.5u7u=z/3}ks^[2~й'Xɀ.طH$f?ࠡv5cMƱ(c!E%gKr9xKdXsHyu_9g#}nϚ+ Du$upv|S4v'[nwC뎜;Bj*ٰ{q^ʧiqP㩱tܘ8Nvoge+܊ FB).(?To+̯F.L?+oʿ%TTrrSYs1OX_-M߬Vo?A%kht!jh+V`0*PUG`KO3i_-Ԙ}_}0@IJBIJ3vx_o?@ֻ7JTO*ԟ磴MK(R)7FֻچYk۶(;N{<?c8R|7>[Ү]ZgP@YYw~q},99h2G$Y! ]h*(;F:s%,Va ߀=#>!{;tGY2݃Zc]wL=T y4Fx˜gv$1;p@ʹvNy,oVr+neܔ˱$VfWYke/}/cB+5m͊_-f4~+D|=kv;IkϨc b,'=ʪnʫq9\8NS餸dPZyjOݍ'לuc:EAug0H۠(66;jvW+q:\| w!*,o΄'Q\^?BTX4ND+ۖԞ ::6m,{1Wy%_Bc?8糫Uѽ]O`=/z%_Y`q=ߞ-Vq9\ M=ɧ_{ ߶Yʭ>1[U\4k7})NY f3ϊ|w65aaPHGEa0i%vEi a=zQQ"o^Q5kE!!y(G鋾qJ(mQL˷e3:scBYߡ-[jO z>q"J$cݎ2D]V޽ Wx (G׭1&#\A%kJtLriA,:B L׾tRI`>ƬgZ;A{0ΰrey(ݧ[ֿ fcO/y}e?FҠ f}#5kFב !SR~4mn@HotM}y7Se: 6{4ӯ?ҿJ,^ĭd;3f:Uw}ڒ/ǪmXx[=c¢FOo} c0s_pfﳘ_;kP!^yMET6ZKp{DQ^]M1p>IH:\tK5RU,ZPe 0UɣMn&?L M=|CoԞfy >>Ys  iwZ߬`GI),6-aɚ ܦoi\}}G_`>Z;d͊_u|׿Z%Ũ66G` %&+ gyaH<?ƛO:#f6~Jd9hoXW/-[yz~%3ɮ"cGl7QQv~^Xm@P^e%U8 %&iNJnͶ %2_خ 8p+BGYSj݌Ͻ]h^ػDe|՗p^>kG׌=)ֽm}? y{DnkI"; g翴cνn&]fB͟z[?[NAռlڳ;W|';g:wo-?g6Gތ(lƼz $`DH4MK;^UJNeԀmvJ+`\fb{VYRٖﻥ(,+GYS[+>oVۘĠl߿+%y|c+{x/3zUD,ef~]h־@Y vm۝ǫz_#af+Jf7J|aNߏ^Ug/cY˱J *8D/6{gp{V5֟aeeY8n׏ՓN]=JxzM5ڪUhk=ʘ(^QG@U_a=+Xf)[ч8n Jh(Zv6ҥ({hY^w;FaRF߿>Hi㖿DixOqϽ(eh?}%-3n {SOK |edԢ3kAscǡt۰3l| ԙo A~LMB׶IN"A~=9QZbKIc Xc?L? Ǡo͖D `8 '6qQ\yuTjg*FAz<ء}E(h+WΟ, A8d  NQY!BA8AY%   p!AAAAI    GHFAAA8B5    A82ZG'4)?g๜,1   hlgGSa?3\u ]U6nC.SABZ-h I ZWfկy}cdKPC$oYvZu]:>N$O_=-tR[g+^?__ [c*5%Vȿ! 9Qk urt~NHRmg']+_yL16fCY^gl 6o~K #镔ᢢeًٴg -J|Tk\)CSD5f߹};c`ueF~4A6_yѥm7N9'K'h%eî&1z[~$.zB@u=w+߬>MLV7X]ʸimOPƤC.hƦ=ɟM֜,lW5pS{ϗ.zK3+LnfIMbxh۪{7`{jGo?gVf2<]),;ljMA~dMvmdkuk8&R s V񈓲\=WqW!p'FYu?t>k֨2ml ΆTkh(uy!vv/XKHл]Y?$V@vQPݐj 板-/Wj8 :}/uTH IDATu%܊ݍ6zٷL$f۶k%@t#1c}V3oU`-rVk|MX[+`Rۿo3ŷY-?0i$%ש .2yE8~(B)Ѯ ߾Ꮝ -!24K]E~I675LuMY4 b,k2m!¸6oW}I^q}o|S%6f5ǬfwʅddŊOaҩrWjrw:%tp}F3~|pMqzFC?b2),^l$SB"Yu ?o&7YuǺk "Đ>f#PY3O0j>+:,W|kbwƤbލ' 6~wf,xCAfImd|⭆٨.8^w3 ;54/+d3Ժ2lP%w 3%:[u+Q* n599T> .*/7P}@l\?n?.&|>.cNCn3!Ƥqwr)=`,NvI:v2\ M=eYDToVʭxg)va_^TMP!'&202Ob ?nMvN&fnY.fxjؑVq$ fM#z4Y*q,ZiT`<:%&k9Eޮv^ɩ,<>QZUJNu8B-ڏT+ KFFRVUz3+Ln?2oAuʫW6-+1V/P 54>+7uY|[?C nϰÏ $kT1Sc6f TDStzl[7Fp;:+$EaY㊂lجYߴ o8xŒ8 vQѷC?_3~|ňQ_}=De;i"QaQ1wyh @nq*3)n׾7[s7/61tN5֧)JtMNblٹ~?{Gq=;&K-ɖ ۀm-! !$?L!@PM1`c^eےN:ەOcΛ{;3;6 )N؎¹۸ܻ=b£7= or 7[ޫSoTUc^ OQ&˝*k*IN or:{rwX6i)Ap 1׽Obt;1+v}^HJH&K:'a0ĝ3sncdѭ~!I )*/lp-鎿֎`ˉ׷%.2H$ۢو{1= U(0 * , [zNx¶|Tf^Xl`q]U>Ų`:X϶1ihnYc:ӫ<*hWeOu<$KDJs,OYL!> 08dñvZľ i׎ ^濮h%럝|Nߒ}+NXxJ-R8 BKt#㫭%ImNtٝM>ֲf&AD0]埙z .u9o_nZ&{ oro}? w羼9*k*Xwۿ`u 9Կ = |HpwDmT ײ7t6)^XBQY}0m e>EGcY璗,)s|]:2ǥ8Xu H4dXl:&g)v.i2W\qʚJ>Mg+% >JJ50W5\XxΠsYSEDE'Nj8Qr&:"E[_نxkھG\BUM%[ovd_+wj`Ӑ}F\<ݑ:i?~`BNLJ_Ki9׶prU'7D"HdMw9a =Ɖ懾1HPhfM:0':(% kqDy07YyV=Mc^{NerdAj@0lϋa*?)hnH̱{za>[cԝ.בvZľ^Q2/3MUűu&Vi6o;Z꿓?{>q'؅f-_8NjU/(.ǭqi.:vjoAu3|S6E,vfb:vDQT4UCήmE#T~>06#!*CfDE2&c e5쓓l|_K蓜NIe1M"H$*9kM* ,* -"fjeF>TZtb.#U-0jZWi~s5RhrVbGbB1"q|I)S9kM:de>2ƨZ{5uEMi4vo8.ENALUTT$+7|cB^/$4|j8PwNoGJMTX?A~q&%%d( #"[㬾c؝P~A=U|~fԧ6Xfl>?&2,l>ޝ蓜Wڽ)M51I}FƑ->y}<{BL4ƭw,dMyc4U#@N$£IO7W!]kݲXm׵(*9;ޱ'apL$;g;ʋ(,&&"1ˀ<>뚉(u7fRXZ%g(BJb dWNG;]~`XHFoPP;>vihvog; uv|4ovoH+n>>\$D"oϹH0z=Q G,6־Z)K_ѕ;7$B9:q],SIm2q{]1Z\C:Ul@b=4j0l<I}AUžF`5?o5Xj [ l|C.,28 Z- l{' o~\7%+͠ U6dR]yw]FAZ9`7iʰu /3f7>~KIo;GCܡѡ'nWo `'ztŔӈ D vN.pنyLʜJ;C`|rΦeFjRf 9.;eUu7c'9ȰH*+tp}kf (_cF3,dg]敜Œ!3qn]VPPϧ?BUT.y )]4o5{rwlfƨ1zЫSoEa>o[IdW~HJiXIީ<m2، $wUo7a:߉|2kE NJίC:U՚1tݤٰ-ۏl%δҳc*c,ݱؿHRB221#eq-1kEtM(,aݾ =ٝ߮<~'2,͸41/} UcZ'?m1Z3>Iv` w*(gM6@f?D"HmH$9$;g{gH$D"H$o9J5H$^z!PD"H$D*H$71f T{} ӐJH$D"H`dF"HKEH$D"H$#ePD"H$D"H$g2Y#H$D"H$Dr!5D"H$D"H$g2Y#H$D"H$Dr!5D"H$D"H$g2Y#H$_^m 3' 8?W7D"H$ 4LP{FƅfW<+]>C2 `9uF 6|jv(0.[{=]]Ũ8d]G:[#:IWmtXis]5\o6FKLU1}G2lcv[2a.{(XF![M6k-1S EUOy9ur7G]N־4L 1R} 550j "re}oGKZE#:B$G~~%<<2{TNCɗ[$ Vm#y0{"8㯝%j~w+%c-sٷ*~<>,?1_TOئu}?NNNu~'\1z d ]rwp`ZpT?\WD^"H$" ܷ`^Nj7,N2U*S"nc4Gp8u[ۦ}' S`rI@UT-- ZvZjRAeEcax wI>2.@":*o`PqbFM^S4,r"2.AF,y;7[L";(LJڕa_vӏqjڷ ǫ\lo V5j,Y/ 7_0tJy ;éR<ɇׇ![̞bEv0n0SgCᙷJR Uo]<\0 dŒ^g1Q ^O;0(2Rgܟi}Cs3bKwon.\},xqo@_v'w_<{.<;p΂E_}{۵>plxd_tH>^k~] Lv o]=DhͶ=+x㱦`[#BL~(+'ŵ ^{#w?Ϟ/_W)/YYࣧ` _i׾Y~{X+ D"5GpJ +2.9Y7S@9b:iK>;)ĠD )#Tz*XlINCCE&wI0UkLP(/h>1)K/oX?)jNAUkn5h":elu E>; ~HMQpE”?*w $Q9t<>׮Uӏiӟ}*x[_'ؿ-XEI[_7>&  X!QP#`7O+gE= d݇Dޢn%g< 3':cLI_!3w]+>𬸮-]1IՋc@~sX?-f-ͺnٍ`;5DܯEJ"H$P[mM*hWeOu<a୲@gPQ`vVLcCo WbMw"_b/4ǢEt\='{憜5t^|˱~S+R)H=G /f-4$u%f˙opY g_/w>u.T+bF|}R,#O7q<1nD&,4^Pg7>~GZjߩ&|T@{>+ 4$DɚH+rɑ^nRSzBq"H:ID>t ,=#"AaOt\Q? }'%Sl0IPsC >Z4Ox1j6c? uv31",kyFn -3h4hCe MgJ({o0cC+zuou4>׮NNEmؿ5kHbΡvoKNjK=k"EP_Ϳw/7z$ϘR%'k~>^ ?*urîCb9Sʫ2J bمS&>{V| C] b1cDX>h N3z[MV?& BE]6۟'bO5LO,k MK$ _u &lebWKcn|=Pg7>iܾS,f&e C"H$b1b E uV< *Zabi¦<`AUYWh->oM)bOu9Kl`ztǫXҜnAq5]Gk- TXD}Ɖ2N8~IkDɚWY(fݸ*FZ_ Zfkbxl7#jF~'q?N߸};Hp](0E7K̀iۧ9t liUbDur:>Q`Z"{..0Ti?EkΈ))o^0 f :;=}* L?]" &`e_f/SX,fDtIDpXU;F&'TEĆ5ԬgPV!ˎb]ӌ8ѭN۷'kΫ_W}gR'69QŊm[]#tb5^|B(_[N9DnUxĨ81o zOgbVΩRq:F ־u""nM%D/yxC@bB1įi i3eK4PNhCW]6KcF@($4|x2L,!i-&;D5plɀ4p?}ve5emƉ:o;vq?No#w'x^}O@%ZBt$;~|OƉ{siZg@D`2yD$xsD=&Vnn[~lw(/3fͼ%5)O~l̚Gv=pYIOSjzbIDڍf oR\KbREWs޾oI">DSG `-vDEg{7:mپi_cN?`>w`ݏ}& ϗ^5xwX@8tL,Osbҹc8sEB5*B[f8Kܻ枀Q^FucC}=) ucÉ:>ϗ+śD"3kzz8&?W&UpAUŎ|ov?1i1}pt%^-XstgkXbk;h?Xy0-VUeyX Z?,FfU}ʠu4x+-6 L,(>bo \;e YB>6sx|v@-)Rɿwb)bsŲ|_ Mje-Q &~ljoN?TBza7޳ff7Ku{بƜ=RcQmKu<(Y<-]/["3׉bϏ",\-?n#DBN7`4Vl Ei ~q1x38gTy6}~!uǿߒ[x7џ moņq"3bյŬ?Q,{~օveω7|Wɦl\)ve~C'ˡ*pτDEbR'śЮ5oۦ%\/wI̴gZb˿hX~?EH\k1b2<=IJ('r Il\ |Q6]e?Ƨ]Ng^PH$QgzRD"HfMoVO#fu_e8+K,:'}vLwD">H$D"c013\,p/_lIJ.p=㻕ߙ?D"!5D"H _!1Vep/a߽3[ϊr%[W"H$?L2(D"H$D"H$39J5H$D"H$D"9dD"H$D"H$LH$D"H$D"AdD"H$D"H$LH$D"H$D"AdD"9^vhTD"Ho1څ}yW]- .H~8_tqi?xzOȸPl'pE kugX&]a},gbhWA&Cm߮Eau/oW?B5⻫5GW(^gkD')-rV0m F^ksͦB*r]Xmݮ@c[9;/gxԛíqt=pFqYsT~O'x=1@wl>ٶCοB_|> |=_0I+sbRT>]#׮Nve'~Sk?^g 3[mPOUT|6 ~򝵭$;u+\jF?Y$ KrrWCXBUQeCU?0UEhpꠉOpMNHjMZ&T[R-8ԤhB#_=$ChYQ70 8a}n[X@)9TCο~jl oia ox`Id_r;N`q?NRvQx 7XthӞST>.*/Ty?HJ?w]9uƩf ӇecFSs1}~]:N4&f#uNHg3 >wμvԿu{W%phʪJ@T XWCn(*%@G0aU*pڤ}'clrѻsVo/ul'eQ^]FN:vo>£AIe K w3>ͲKo"Q$D'jrLӤKw,&3,usg_ma&h4u,;7[Á}7v/;lj8K@Bt"{ aloO?WP'N;vD7cП^{/]]00ҟ )X(;or:{rwX6i)_c:ST^lbWRoٓ˱~?1Eƣ(j5$D'6[WިΓ!g_/N؎¹۸ܻ=b£?*,,x|]ykiɿN?N5oNvp ׬I}'?\Mdh=o1>NZi\ҥ (f{/xVi?38u Ͻè]_2G6/S'qK/G(JR's7sx u;ns}{{v{=wc>_#OoAO@9۱~0w@MK7u{BY6*.*hWeOu<a୲@gPQ`vVLcCo WbMw"_b/4ǢEt\='{憜5t^|˱~S+R)H=G /f-4$u%&ȼL%?48P;K!+T)X@\Wx,p5>s?t-hap|avvw_-oNגt#45IF9uR;7jo5c3&0:}eޕM`ݻ?3g\XsjZ&{ oro}? w羼9*k*Xwۿ`u 9??= |~yg>㭡knq U5l=+֔3\g/Tyaq8MtD |IyuYD. K (*eRT\axko>pi.vyCgeَ%:Oc(*k*,6\O\d<ݢ-ɦs9y%B(TPeYtKK^Ʋ, 9gw.!:}4 v avvw_-oSNגduidO素רI};IJ:~eN1`kעtz I8TWK*-[ЦJr2Jr2޹ǃpsx-<~PbbP*tJO9rWzXfpw}'dmU p;/;nsTߟ6}FΊ7vxنy$D%0c,£Yԑ~]U5XGkes8hJ*Kul'qMuHd}IY=SBώP`ax 78?݌͘W;+ӿjI~;8'oGdX$c29uZ!U{L YZ2W/.]*c/ripCQXaa2qJLm[QR{tJBi N0wzh_13իUdq 7 m,ba[1Z^bm=T~EoeTqrW-E쉲9.g L2xRB-8nƠh`a`ʓc+V8TԩGW/5i4Y* ŬWQ;[ExsQk贈CLzM3X "v{:ǩ8#yJxٿwǣ,y09m漾 NJrXo #uu{? m&@|yw_G\̄~YR;k?O F1L61 <^O;2ryu2DFL(,;騾[wԇg?)ZU޽)۾R2p8Y]cm7`fL?+xIA}?Uq96`aOr:%Ŕ#r8,_>1s Olt=GRi3;/گpWxr*j:ѿa MLm ;=nX~'q?N߸};HK :< V_ꢗ{5]ww\;vH4B훆ငH@tއ~-h^޻~dDLjL]£}; *15- sNTu(ڲbsnݻQzbpsIkCޒ|~O}Hx7+5yln|OhJBbcun{̆j~\.lB"|?hբ I h䮫݈* ,* -"fj4yԢH EvRgIv剩" ~|I)S-12T\:E#|s} r ")tQ|ș~őbvE,mꂞ4i` 2L,!i-G:D5plɀ4p?}ve5emƉ:o;vq?No#w'x^}O@%ZzOd_W{/gRRYBZJݎM1("ܑ0;ݹSgѯkI}D2[cL|MdX$)o|p#;'9_)[w( )]6]9;Ω"J*eLƸe{|*5EQpnuͤdoWޥ]ZRv{ǞoXHFoPP(VP׿sldݲȫ}]p2 `LW7׽GtFf,V&nTx4)x`}߉|AB𒝳ݸu7e_ojduɲ'Ŀ_vlj8Dz;1߼SPy$ZZ_i?*I z XGlj@aտ< 5k3FpQbbg\ZVQe(=zbܽ5kVn^FIu$`/=6k6\(qhZɮCxXBt:=N%W3 BԡCAQP:%J ѯ%vZL Jjj@u5V)J$~1zz8&?W&UpAUŎ|ov?1i1}pt%^-XstgkXbk;h?Xy0-VUeyX Z?,FhU}ʠu4x+-6 L,(>bo \;e YB>6sx|v@-)RɿwbasŲ|_ Mje-Q &~ljoN?S1}y]ax5<~?`L0Grk_eY۷'wm_5Vyu_lCKNYU)_l1jDERQ]9VP/QQWf.91Cf݄"[((z7-%f%,ݱ}K6\nq'cl:XT`ͻLʜ،š|SVJK+K(,;I}~dkaQLʚi\31pK_>C=1chN=Y a?@Aq>0`^z3kE NJn=r7 Q>; ~ ޖ49k 7N)?kǗbsŲLNovtϚy{dUUD)?Xv_9YsVUj4忄UR__w=? hW\抷 m܀̜|*+ڽ '7zrܽ7DFaTc_iSC_= b~ rL^Bj})ݻŒ0'xyQ1\ %)psn8nz|SkeWM=1/?G1RWǎކ+fӺ-Vi Ο~(Xe_#s׮>%}}֮w,5!H$?挾m>F"H$fҳ'矓/ҳz1_ D?OvH$:Cl$Da,\.ц@Xk6~?(hӦc#5 ]@"H$ƴ 7Pb޺1LC*E"Hm|>=*ƨ͹%* s:%P:0>/A""5D=?}\*B"H$;|o! HePD"H$D"H$g2Y#H$D"H$Dr!5D"H$D"H$g2Y#H$D"H$Dr!5D"H$D"H$g2Y#H$g_뿟Owv[K8ǒWZ_C*a&}t9u~CH$= 4LP6^=,&^uF 6|=Md{Qb,,7e:+;Q*ֈNRU[?{Gu5wʮze˒\$[ `$@$|>G $Zb WWYŶzݙqVݙ 0}G{v{Ι;s-SdXwtX&Xco'/$+}؅$NWSdq}MN?ٝ?#T.H`zɦ}>{]tW8_#9[AQac^*[Ut+bPAs;xLg?a+>*ZĦ(LWEFӑî1 XvdrQSlq|Hn_XSSyήX;~vv>\eԍ:t@r/ş +w?݇AcKMLSt*Zw'@߾SUƪdJ`x #OE_cG; aY_IV"wѩ)8t?8nƖ}kvP߁m+;K MM0aۢSZ[F/뫻a ́F"Vuf_}Z_Ry/˿_ep| 7?BiYD͍aضx- DuDeͫ«qCE CN/xﻦ+iAjQQʟ|s6:/.W»@D"5?2A(,Jw>+V*$tSؿTtםohZf:eU-:덩:dQYs/F0Wܢ$kL[o |]Q AgW?;HcR⭭k;!I]C\?KcFD=VhIZ?M)wAZD~RkҢErOűm6@Nޓ4Ƨ߉+7AR|2h8Ob~xe{BuqOMzR<?Ƀ^3hZG>zxBqWk|3dyPQtɣ'cmϱpZsj쮟 !N,?;t N?) ;i_|&kfmW:<.#  Ғ,_*ڀZngO6(% 6Gu]폝ggp7TGk=[:|YFϻLh;ۮ۸ ~yh{H$ѣdar;{ǠtԾ U)^!:F1j9jH8ە>1}혅#Q_fCt(7=#vr'EkKWD]?'9X{1[ xu3랯jP#R)l56줂7 CV kʩY.ɝֿNڇp)|wU?+t̟,~.[ᕭ_? /, ~S+p祳Ek.; pe"$f/!\#zb1k`}_6[tfnXNԖ=;D9PS knyzx wjhGDG1=<].:* 5o\S2J$vXN:Ÿ;ʢ;]6mWvwBJH?*<( {Cm{fwˆD9 d,IpFa:µo_4N."2Vΰe. Zdc5&d/\?z N(: <)v~6 |G"r՝߉~v w4~ w]'f/,QbV;Aӝ__mm))8O H$a%I''k>"[:>o3:^y̢ŘuF^sdAc]՝T[P]Cae:4NnWA&}ԖXc`#ٷĠ#So{ZqG_?'9JT;]Ħ(X@J/Uqrol#+3/WzТxI\W\뱽'%=mMtbEqcYp## NJ'C8DΠyd))^0y# 4YdEv巰[  nЉMQػ~OZcN;I\LTh۞Tzj~NpR?;CW/:$O]6~{_j0 }U6=q?@X. ƚ2GXgN4<& /F߲g5&?z*~_(I?*#/cGUzTѹcT n]~>7mF}>Q/F#{B|ɣ5{xb8LnPoDG8vsRCd3(Ӓ6%gD]bچvl-  Fy.PW/:X~u]4xPqw_vV犍bKNO[+ p$ĵAJد .վft׏6nrFkHWt#LXb+tmU'\?.MӲO:4xD[[: s3jKdol+Iք,(F,=7XPnq`+5gGZ;kC/8]ʆ;)gu, 7$kBTi{Κ`AJ/"ˑ<":TX4[Qׯ3 6@MEFJmIvS_&f"FZșqb]:K{m|i'֙tpo\䑢gܬ|aX(LU]1/Յ5&g:_DmYc?vG8Db1UZd -ɞFgz"?a䁫71my{( L?ss'Fn_SagoC0$>\Z3o[o3Q{zD ]V)Fb[33v\sNNp?<(#\+!!>㓚$~܃*No_;^غI|z}b7|ϭF?I$Ba'Tr]?Ѳ@{TT$B}qD".¤YcfZ3??l諆6hBNH3"\Q-\i ~p_8x\ byf.mo?WN/" o%I6 yڢy*6+yJMq ^4k8ەzq]zMԨ<4R24 [7O;g+/ l 8ρ /6TEE$e)hM_ -:Z:&Y!{X9BS{L*,*[2T\P['%;pxl3qwfN)2疎bwLZ6-FBo>XCeoDax{ޜ(#onT_ރRg4/'Zl4>B2mLH8^,/N ۫BC IDAToNh۰4x-:#:cHڗ?*{8cg:!P3Yp/{.qO~BϢ0aca)=)6vY09r {o~IZdF"lni= 3.`'} \'we©&3}^(?hBgt4xž!;fS&[+xLjku>GWV@?[Al a!jgX`ϑ.v#:3BQ^ }(R ̢KFIRM Ӏ? \'$vοv#–/ 5 pb{Zr1+sDظSl8$ԻS} ~{xPܺW$+zk>|+)Eb_-+F3zuj-yZvh)8Aco]o*h$P0Pqd>L.~ 1/-R*Lx1[*Fʼn&{w oejֿv$>߉vuP 4Ucz,g5ֲ~vosiXɋ jdls*>; !6 ϡW}ڳ!;%>Yե'i|V ˲=19HKaω|kcc\u!}2aZ&o8Nn_4MMyw5XEYi6_ǁ}V?;gw~;tIQRQĿ64lvЯ{DFrPT~̴,|M. cY#n{;%k?Tߌallg̴,Ix}vɪ+2;ۖy9qw|H]SI|?/H$9|F(3MsO̠hx`}^8N9RNMOyKW-s +ܰG-bS&ݫSuܢpHaW,CLŒ_)8t$/Z,݇^gWS?;gw~;t2F_QDQ OԄ;TFޠ%& "ʮJk_6Nr\ 9 6HnW,E$&r(,p#g i<$sPV}Ƿ;} |7Bܺ'vvJ9c8TrEQ= QNn?30E,Kc&"%E<Ο}G38;ϟ p_Yx /}2x|a"V#_Vs]w8`ַ[W ,bưټ_kvPwD"|U܉~d^= GLLx+V*$tSؿ4Ş7 zOT8ʤ2q]Tƨik'iN־-(bR𖏼5Pgri_jPU0!I] 1B?Kr3RŤI戎z LU9ˆ;^˄J=;M3kN'OD? $u2*j{.4GUS(#KOn}+?na.y/[AS5aި}]:N挜Kzeq;蚔 ŭoӁ}?sP\~4h4PRY@jB*iiRYW+{#]Ja ӠSUħ:]S5gz <&NuC5}F8;/Zm˾޳)CwJgW?;39o*a^ gf=;Cf|G/ڋi @C"!;Y@QIԡ̴tF͖6:e{reQXCaq29ֿ-M&$M{ԿvNIĿvD"|#:0g;~5R*dWIpx٩*X#M5 Gr'&n]'/PnzGbN־)aE~Nsj'c ©˳ŏ+\0.=f-:1m=_EՠtG@1"YS$klIoxt"ՖZN*vg_ &wZ;i'R 10FgUF~cy'pnf Q)Cf-o?s`E$%HMfR4+bPVnkDZ :* t5{?eTdes(=Ҳ-EQFIKLw$+}b2Ӳ_ב) N^;7AzbGr'Ek*9HR\sj'qndr`Fn?1X2s~JD_r_}' 9#7'+ "gƑ ]^Gv0&q*飶r qξ%udA8So{ZqG_?'9JT;]Ħ(X@J/UbY0*hl|*GV{ _B qOL$n4Fs547nL uF^Z mr## >>?Nڇpg.*iL̝p`mND86X矙~.po}/7-Q2(k0/Sxnٓ7:.Ov} Ûonm,0==+bNW1IKbmWWA}S=϶#IOe 粓ە…c=eה9ߥi5sF.ೂTԖ#NTh۞8uRU]~vO;.NObl"e-%|˲5bsF w(ovxsk;\|eg8UUJuC53&C aG`Z&cpT?o\='v-' F/bިpi.bSH7X6ƧI?_"H$4Yp{jNmKSW¡&n,Nn2":mvr[ Q7Ħ(]bJS-1 }$.MeNTh5UOcp{2{|XIjkkqn\?!+=nTWmepEQ,}' ?n(j;}SnO.?~dXwDz,uf&RU_ޓ{HOە{[ޖ%%1"b` z\}GV2;So{c9yM~vOK")O<;]((XXCp:܍iY,O #9>,9b@ vI|LM{/6=Τ` ~'>f3BgJby. ~ 6?KQ6-'j+k?'w' |pNZ>PD)%Ό pŹgY&|~d+z f`/ZGQܺ!)nMyEtFK~a#]0 s3{YiJ⒙7ſNE+Ù;h {pu>cbuAS5tMkRcy^ w3{<ܺf ,gBl"CzxsDҫ=LMC55 )MnqŲd/o7(,%wssgGisӞPGS5x oD`r8ǩ%D" Y_,c0.*[l}1r)oT~OBA V>STFޠ[oQЙl'H-ωcĵ:srcZ+[+w_Tmf`Aq- 6AxŲ!jgX`ϑ.v#:3BQ^ }(R ̢KFIRM Ӏ? \'.G_Wj>.rrmG6s0$&PYWQҳ?z!nM+oϺ}xsȟ伩üdW, |'xm?i3+N|}G2EhNEXݮ3~OCxg[ڽp;1L`ۑNܮ{s@ie l~+`hg]&keCfe) vl6g}EQ8TrQp̱ ;gq8p3*j0Ǡ1 6 4vzҝg?|ܿ4,-YcY&żM$v?ėK$De^~H$.xԙ5D"H$9yˠ$Drnӿ23$D"H$ɹ.M H$ޤ'ui7i`ɦ70LCE"H$D"9D"7?4D"H$D5A.H$D"H$D"9D"H$D"H$sH$D"H$D"9D"H$D"H$sH$D"H$D"9D"9stM)pb) %H$o6%7_}tD"i}J MEj_hdɖ|$+ R La`6UsTLLm`vL_Ezo`9#隧bpbpNh0aF8]MŁ J>7N;gw~;dP@#酊&av-_e|lEuy8lWaݮA2Ŧ}A/:Ui0|6_j_!jQ1,N78ۖox~/4U[?'Ngg18+װ-somgutM%Dz,2Ӳ>t&S{y}b'v>p#- ='vɮe& !6 ϡW}ڳs$+)דMrl~˱90x2]3|T0Nbux /eQVs qx_'MòL^훪r1L_o?INW,F]H~ɮkW~J|*%KO ``eEdP/No_$Cŧu\?ƛܳ/&ͼ{&Vc#o-珏G:<0Mk2s+}_} 6g.J,| 뚬|F(3MsO̠hx`}^8N9RNљ IDATMOyKW-s +ܰG-bS&ݫSuܢpHaW,CLŒ_)8t$/Z,݇^gWS?;gw~;t2F_QDQ OԄ;TFޠ%& "ʮc+T^L4/7#*E[L*dJgʑF~HX&4VZH8ֿ-(iD_ 'w\v;"Y%+EE7P^[FEms~j.=y»Y4Ć捾oMMp+y.wq;3r>.MVꑖmkRw.v\!;Y@QIcsƳЦD{reQXCaq2Ja ӠSUħS`Ώ_k; P\~4h4PRYXnWvOΛ}k_4>ΐ;y /NzJ ~Ӂ}?s, w4[ݩ#~18;ջW51p3Q٩ %ngIe]v`X'}?v/'~N9yuLO> 2W:x|>2Qtm9먣`&46NUQ6qُ^w=]ٺ!CpA~=tڪzZ:~p?7.qx:&.KoKl,ȣ\?ѺlX۸zSϠ֎qc)/O뾟p?ෝҧ_oϏh^؜s~Q2Z+u관z3GPqOuP8ȣXv;x830?]:cJ$_d,wA}ǫS8B܌Uyf<@SEBwőܮÄxCt(7=#vr'EkKWD]?'9Q{1[ xu3랯jP#R)l56줂7 >CV kʩY.ɝֿNڇpgÁ} 5ǢkYk8Xw ܺfy!3܍ֿY`"gx~S$&3)oETW1(+su]AY/˾ JMfZk:>3͉X2s~?nO,iYJz8L[J&K;S*9HR\C5̜c?*~_$$]2(FEʾN ;/ N3TSr5=P1 EQ CsDCWGuT|,J)\EKPzKu||7U]Ox1_?ګ7ebh߼mH(ݱoۮN'7 s!gV <݃/ϡ͜1F??瞻(=%q;;nx=s7ޟ IIh^sݘDp#yx-\>ݨsCD"ZHL|Kge 28jK,G1m@[bPWjNlM;/eW|s?D%NOlRYk/ïqƧ:N ϙrda9xJ/@UZ4VX +b$pIH5*pCdJ(Gݨ3:bnCo3O?duQF&Mcb6Ȇk#`u9 WևO2,/;] 1 1=I}S=㢱dl=-fa떝TU) 6W Mަ;< KsĮ/!L/wFD?;82/,YӶ~Jm)ɚLSBxq{Mlm VC( b#L&F}!h \mZvYb@Bx/\?!2Vq1!(IIAC'+;-ɚ0;3ܹCb؎UXݻCb91c.-jj0?߆ңGƇGPQ7t3GdbbP҂&s$$Yp{jNmKSW¡&n,Nn2":mvr[ Q7Ħ(]bJS-1 }$.MeNTh>Uؿ`e%THicƪwQ!sʉu&$Hcþkʀkbgӿe=rkLŧUPr!"4;}cޓ#IJ il}@mŭqi.qVz6ݨ2B}v8(XžLϟEFr7EES5>nHO j 9ȿC 葖Œ7='ꚗj-KxoҘ?z |V  ;?oX~v؅.?~dXw;)KG:O㴲hN-$6TCSml3)o*|B?N ?vk݌;GaJ-_^g9?h"UU=G緳~N˸"H?B\4|}WdPRR0^(11gQz2輻U^FUW Mm8!&bbJQ@sJ(]`ؖsn^veK\)).S F[GXi6},N訿/WUQe9+'{ɿk&dA1byrK ];{'->Yz֎w8[[:;eQD- YJ EKt< Rz)YIRƢ܊~_mb<ڒ⧾L*r%(ͳE7u3[ĺ0Kuŗ"oӞ rO3:X%6E߸#EϸY PXcc^ c?kM3t%r`ˉʳ:(ڏpB6b j=c⒃t (ߙ<8wY,_ʴ!3Y+XEU}% 8j 1*T&'s O,}T$Yo Fer#M&jз[Kw;S00+Jm۫kcy֭m" ?^3^X,5aT?'.Ba5ʔ!yS螒IYN8]}W??8vٷ"~v7i3}|WkGO(6a,ӧ06n@0Q̢UE<ҫVqQd] q+JUU(I"9ӒEI,JOG<sTWSUr8s>}Puj1w?Zؽf%OQo> f0[RzW,k00*b\"ЀD"zi}hyJ{RSڙRTIS]oF 5WTZgy?θ. &jT<>{dO!- *(Zqmui~mVmZZEQA@P}! &$̽d 3d=>s3s3gs`jyFeMUM\F4aSG o]=`fT }v~h=͠:GAR:=ppŠ <~MIXTTSsuPbM+ RfM~ׁ /6X-ߤ{Բߺu?ש}ܶ$CBLBCP%;+ºg5#UGE4'u@2;8_<>O !{_͇ާׁ[7aLzQ,xڇntΦofvֵ{>JEQo{Ǟ rBl"9YYgUAt37x5dk89>RX#3L2LJcdsUC=Th-qT盃_nQ9c٩7n1pvAaԴzAk4 oC1_^/ZJ;qdX(D }Ԩ.SK4KKчMC딁~Y_UzAK핔ֻwѲLF5!#Z:_ƄY_?lXt3.sm=1q0iΈ=8b ct\Bʦpd0y E,V? 0V,5[ؘ?l "ҷI mV? 6Epjur5O`jt'ZWxMWnw=ǫ˛ ?sNz;dRB[-ZYP &I+ ,tgޯ+=kl,V _7D8ɿܴ$dgʐycj{hO0qds6_;ҿKcƶmVZq#>i:VSk?`갋yyTT0:g,Wx*k*Yw+<|+?eg沫0t֣UG((o~ =sd_`|LNIJ,>/tìO6PˠC:b CmY|`j0p"?x3h o2~DeᣵNw*?@OTlbKf>[&IStJnSˋ]n>}SMoVJp;ٿxwX_֒Ej ܽە> :ڶq =Zw(!-Q?`kVͬA"ǘz!ZϞ_D3}oW;:?UFӞBnAЫSғfi s\v99")D: 2e-- c8ۿU`!A AٴOJq7PocZ"p  <{qh UX+Wb.\h8 | ` 7<#" #ګ" _Kd    ikAAAAN#$X#   p!AAAA     FHF! F򯏽3#:AAAG;; 9KC?(c\07^ ,~0wziC6C4=ژ K ,34/@ב:7H/ v)` zh72:^}rt}b*s+ lv~dRroxa5:Xb6s*sN_'p?u^hY @YgXs4/~NRf3Aڪ6W> rgX5Q}1o)*@k4-!n Vn^ TAAk: rL[XhZL}&-@ɶ柬Yec~'9ҠD=-wJw*-$R4P`Qsئh;?f׳"Z_4~n?kNj=Cb[R4MHkw2] 7 IDAT: | <HN H\;|>}|O63K]$|w)8gggqG&QbP4Ԁ`_d9 Dh:=W'ƖOnin@wk_KH354U+}["0O˞26)ύF#\'RiyF׭/RNm t ե#t[m3 " Ħh@JWEmgmtt䯰|\F l{n\ny-9V:=5ثg&{$ f;-}p4"\`x W?O m`oRYlK<579GKD-斈T?':Ys_8oK-:oSSfswQih޷?5΂G_ _W#Ȅ~_Gà~ЭwMc>@q1DVo+_lIzHdGþhH[RT9cXU]JZ.{ w0 zՌع?deDJaP+vcpx ix#8|T*@9h5T-[RfT_ϻ Ҫ]aд6镥DFsJ]} |=_.)  V~*U "4[:dĦhi8fkL{GbFөZ[lK**/7I{O28ImDs[~:U%6ՇmG}-tșaA!FE}Jljj(I=[_[Gk5Ί,?l{$s&U75U;,o ܒWZ-njvǽNUiPQ [.;|S3w>^ƺ&CB<%n5j ҵ-Kpؘ/ћ%*QvuW3k 8տ~6RɣBRAss%*8sJŵaz^5ʒAA$Xc2Ī_]h4}[bM+ RfM&K@mNEݰI84],3.M(Q5B-Ai ܔt {8e!j=hسGs;?4ɞf 2V᤟yhEuMu:%*=WÕ}6ڠ`{叆}mܲrTL _> ԦW]V7-ZN8E;o ㆫ=Mܒ_ yKԌ.0'Cޜ 3m{{ao>wԱک`PZR5C]MYo?W'&|#jqF< )z;S'Kߪ4AABZWxMWtnwssĶOĩ7AA-moQAhC>6ݞY9} s8;YBxyGAA;M8@T, M/lrnx1@] %;,6ӤhcNtr/5м]G: 1C#Xcb&M˯h烴1`xaM~lҝ%jL~ԋY̭(I:˵!x萫c[p`٠ϩMz8}Íd {ARg +ey+ b#ύp9?LzK>i\L6ȝa`׬K PgG%$$Gǿo/ qp0fr3< Wͼ[xq4kɢ(o"ûl To$GShgNNc`w^j^ucQ0jtm2[_sᔞ3`ǜ zVDxT'e{,2Ģ hT>Qזdɻ[t='x'0v:|(;Tl, g.>V=ISp x09ukuWWLxr*,ͨap.g=k¬{ᣧçrqӻ {ֵooT^"ٱ ~}Vy ^tOfl&&,5YAA鍇, o_7~0M5xVX~OQ. ~8 j>Pu!0sxc(> W_ lX_ހ{ 1^;Q]ts8p~|?]_wt3/U7M}8]Y{~t u?菷æ0gu?<wvAZ;xp%j7k}< 5Ħh@JWEmgz6Z-_a1= 8bܦp C:VXQ^=[5̯']h5 K_ Õ_O Yp@ _a&6ScpMBlnHs?65e6g|σ7NBV W/rՐƠ=ŠJHF 9ƍ[l $8V^6G ~x65vS}S11X1,xkuUy}>~L wj\|9 n 1pǣ-uNp;*5?P_ZnW_CU0(U?_ߟ>ﶽlHKQ#홥 տށG߫}OV¯Dz`"زKͰyuyAkAl'YKԎ9&cQ3|I=`ɣ6{xb {ZR5tyM~`i .z|&-? 0'6N=c 6sTmb~'`]ʖ6w{8Rp9B'>Mcj჌!:_d/L: C5'?EEʀjƠ7=|D0Z5ۣ|_-1 zՌع?deOeu{E0u145G{*ӲU0'-E@u]7? :ˬAq`0 !n:붻oj2=4mпD\LӠމ*@;NGէ< x  |]ix*U "4[:dĦhi8fkL{GbFөZ[lK**/7I{O28ImDs[~:U%6ՇmG}-tșaA!FE}Jljj(I=[_[Gk5Ί,?l{$s&U75U;,o ܒWZ *ojvǽNU`+*!}e`yjKZ^rrH#]RVS\{qlݾ!߄`JQ]ͬ*0kjOŒ7o|kfS@ iK,;}=mթ[}شKOHu"吒3dup]ƴ쿿~w3,]߫f`YrЛ  ߄`Y WX ~wpm*7|&H>7,UF:v^&tu,a..M(=$kdPKP7{(FÞ#N:>djyHexƥjdO3,ik"\Mt ԆW]V7-ZN E;o ㆫ=9ܒ_ yKl.sO~xs:Jz۞oFoRz :Q+9H񨍌@@t.:ET{?SesB7\mYj7$ BWc}j͏fKys|GmܡZnw<,~fHFAo!7d&HIR٘9Ĝdx_j}|wY 5ߥ})8^]{ǣޖ > >*9q"lͨ;`!\}  ~hZ >Z=:cj]>epo̘S'.$Ouӝx3>6{«#UZ4jS#JoD:3]w"<w\ ? W_N?ۆ6HݞY9} sG$u9r*"AӓSh! 7#2 4-#e4w.G#𧿉7B}Z>6cB  |ݐ` iNjJ/N·3π[T˼V ߞ/ EA    &\~    p AAAA     FHFAAA4B5    A8 }ڝtHNo10 "   | F:}$gih:|e{ktƋ?N/zh&~(a&Gw{e:Re6nZ~=E,V?]?VF oc[T/Qc^ZenEΏLY W?o< C\ۂK}N}nn'cN :kX(˳XL+~n`^٬|&H[gA f]X<;*#/&9: npހdg9ƲKش7 gޜo4hΛK_u=GVW>{XE @>oʆkzgqض`@A }&i~g7[~= w2{ջdfsg1<F<wz8&E[d5[gz7 .M~iyMAYm~`0.?1祢f8w3z^ RB \?7#?'jO :XDL2k}pVߑd _iش2d_20u[1v`Y7i5߀sm[ r IDATp8V1M~~Һ42<0²cr55s5 6e5M yopadg6 .M> A3@>Lz>6ַL4˶xHoh ?%9;N3r|CvD4:t ~nGNY{QʝXeaq?ATM;`&k,,S E 5ٻ +P -GC,}m͏HYec~'9ҠD=-wJw*-$R4P`Qsئh;?f׳"Z_4~n?kNj=C$ hT>hז iI((+J);vaK!5!!=1׆օM]sb-oʰ޹31t1 [/[C5lΩd tHJiw\ol8۰,%ucw [Vm=Ehw+w./d_y]C~LH)&%I׈g8;T~g`,޲1k-aY,޼3 hQt|sJo~ScY} ; aZ&A3zV)'蘭[)8|>Ym;6'זOAڊ5xHćxb5J[lx=tKa:6[!(+t9Sc'7h4@G7xOxi*ە-Ak'uVeOy?Z_s.)4ּxrO/RNm t ե#t[m3XICkwۿ_f,7G˖ڤ6Ø7|jX;F5$eA6Ħh@JWEmgb6Z-_a1= 8bܦpjny-9V:=5ثg&{$ -faNϊnF+A7 牁@  M*m|>7F?'h)ݛ`7Bdϭ~}/hMMSoK@59fc6?R"a{Vj5;Q9cXkw. YfĊ_6Yc `e[ 5~W- 1 ܏=MUmw~#.MfJϼ+16۶阒 Ƕm&7m0m53};g7[΅æ3ex /{wr򦟿rKO xBWOx - =2٬ݳٶ w7NSαXjjMC.䋭);vSbp %"ɿNw!h9tG?p1jQҵC7.92kذo]TGj_4  ׂ5hsLޣf {Gl@%#o ZR5tyM~`i .z|&-?z(Olx}W{ <1=ƨAlqZ3>͝N8GK*5-0"dqߥ~?sN|ƔղCt|iEqP6_tkN64F}_eW{j߅ICļW4.8Vs LJ6JlEzrGV&иaQB:^7MimV0h*U44lllKz 0:w,o|987wݵ~WOjB*SM'!6/.jHwڳ =#S3y[mĺ6 SUx=>5$%7;k-s8GK8_<ˏTݳI\Sw OF?6~5<6[GB5'?E -XSUfx4r5 Nn鐭qwMiX&3`آD׸D6T_nuqCI4 Thn6CNOa@p dg͞Umo, btXm^J_7bk&ʎHU9IqɌӰgI[ҿrгSo cx萔U?s.i]>PQ}lL=F6Gvf.>Mj߅-km叆}mA9{kA\a^4]mй߭e~ۆFgu /l Z`xutts<;;0>|!=96X~^] 0V,5[h9/8#A|T wIp9BhrsuMEB--fz uo)ZoMHEBNV 74|nM>gѯXc)4llfew=q8᳍6{c5|HEQ>^sr눏{Wqp~HIMUc& ȏ&ތi.łk=Glۢxѿg1u4|8~8&ˋ`{hh 1.0<jQu-O=sd_pwT> @qyW}OܓcwNfzE2y2vL+ȦXwGjSSz^Lc]B*m%3 1RWs\vn}%܏M7D d2iT hmϮq?R" pr.E Ao[7jf   BAԇY   xDAo6Ҹz yۘ)  ikA(!AAk,AAAA8`    ikAAAAN#$X#   p!AAAA  >N:$~K{JAs1f|_ksLipA='qNߩY_9@;݀qba񃁆ϽK JvXlI^j`yuAbF&M_OiCcϽؖå;KԘV[Q`#uk}C!WǶASap:BV,V> Fs4}6+ Vl;:Y<<ώJHIG7`"ٙ9x=>*kl6m{Ijb-6٦0Z2R;cٍmp'W$= pd7|BemDt]ӺaZ&; hfh?iBwd?@;۶x峗h;/#%-A3HQYx 299?jt7x{v9F鼹u p>N7O]~iCts/#5Θ@v l>E?NiݔIxc2"IJ-6_ߪFp9F?"Dnr3m۔V|_p{Z 0ylʽ\5CLFI忉75Xiΐ 6fR²@Ӛf3lr߂\iፃ7xpd )aѾwI=6<&6Ec_p_AYM|x?cu2G eKwS>_1uZ^aSlek}[+=X&̻OLy(ٿ:%9;N úWo4Ha#MHI?7SCz'5 l}l>nGb_4_$w$Y}b6|>=RXV@bl"W"ov`\]=?pzUS 'O|ԕ}6v,iȟ>{z|`cu?rзs6%Jld.ډitL0LIde,޲{eaЋcv,ts)S8Vtso`Aۻ[IQV4C?QpGھMƲ-)b(=Z]>N9Կ"YWF ;8piHF#7RRNVq[kvzk3S<kqA&krglzäpM`Ġ~BGcuosbj(hmt5l$cNM?*9&I45`ۦ;;釂ބ /voK3YMFH-sJo~SztsBvVD[N:-R{jd U۵Am6ؒqxk&$esCZR )pXi@ JYeCzˍ.\z;Pi~S]LJ|;ZOL$۹mp; 7~J 95s~TCR:3ϻ~f'r H)&%PeO.v:=ݘIB|ޘ|9Y~p+S3ӹ[ljUpܹ>of e%(Vb9XzsC?K)S8؞=Ŗоpso^ t?])Dʏ} ;+?} >8$X'}sߩE?3[2y hy0_yIxQRi)hiNk!`ߟ$ܳ]^.)QǸJ~`\;mX+V`-2{9Au,ߑyGq]^A@ @tc)$v8/Ns/b%|.`\ Q@)?FZi3 >Lyꔥߴʢ0vB{ILBtrPƍl'ge\{-Rd0 / 4͚Qo!%$~ ^c|.'_`:iɛ: ex]>h/[О~c^@]U#1us7Ǒ}_A>]$kK1Y㊄4 W$ 5\`+PFܤPݽ;RG˜kQlX'$:M68w@.wھM.7ID6=$ &1)V@q w]9د\ ۞?dA t|FcDضdMwpE@"Cs>ֻ~(; J =zgjOo>Wּk,lӇm$d N^_ PW>kI9|ϧVPPlߓ>C8PR(Qsv`دWR|ʠװHpu`ƈYW@JBooxݯl5 dNL@ޖxW\2oYu2Ɣ!ә{ ,Ʀ[IE+.nGt'7ַWÚuڷ+_g$'P9ݡWCo\TPA9x'W?*UEAo- Kr">}cmK$ y7fC7DvsZ;yGHaaw݃tbW_,-EےկrW!%زő|ʤHqx~ IK9trH~+A+}駆 FܬRT}a8]-`7DsN'@4U +š]7~_x`˾39;_(mbr4&fOal:3;lٸM_0 F ,^%_%*,)yvhhn`Ӂ | y?-Y6;? Jk,$;meUaWsE 5湣0{<\#;ɯ~RNUdޘDGİr'5'˩iah6;VN`;`{xͤq;4Mz%g1M#fs9Mvq"XAA^d~~g3~\C2Ůo?B?PR4z\ aA}v4BѿϦ-pNs1c`Cycvn ˗ "_@mm1q/Y>fI !%$t_d F.3w d-PX$p`Ӻ &?x7h QInS ط-۳ D|LSb4㭛NOk_saS }a?*̖~(: ~g/PO+Cb֓7$9H?O =BK֜kh_wP9zGO!-3G!&"oy]PZvWT[uR\Yi$oyTTuʻ:C$LӤDW )$ GO[֥$D%0g£Y[q=kܪ9X<^^G/[De)b"b"@VZq|w$b``2NebWH=}tS$$LL>۽7cu<Gc'?2,I9Sym?ܾ7h{7.@?Pi1 Eۈ0kI>Ngg@+j@DD@c򴿿;R$nCCoŀH}@E4t[`tu4LuOJ}9ębĸAіdmN) PF#x~3,wӆ\ɪY3 kSƈUf=zUcCm]v+5\bVgG v_:Vlj RZ kl~XFNñ}P_(d akpx9ro 2c,.8S5ش=C%lL$Fnv;NݟvzZ>>sFUSXgRT16""og-8SW £w~3'!1ib&sg09g*iRT~ UPMEi fϱ];ijbsFǭ wEP^U{5u^ASL'>*4/˧-r9rPP+9XL1W3$I*;gGNc'/"â>lapKW `U5{܏nh9G8vi4le7Bտ]ʫX.78?d͉ȃe-5Sz\ ;pyꭷ}Op#?-*m+Z9eeY[Y[wu|x(OEN(&-[0oo{ӟCB5Hp?f}>򍛬*1 %aNz^ 1ذ)c!?u-h-o_'n@y5|2n?{BHlZC¬F{/>h| e|~Y[9ώ9C0 R}oQXB X}V=O\3TO Ύ>|ye~@ ?~)1LC39`{:aЛjKL|S{KU ׏ϐrB|?Fwt0־][l#1.ˠ`=сd\,5o4v~v ?> k,߻:jWdg@sbP\`mcW #oQ#cp|_;ۍO;vi_{~ݯ4ט!Wo${CS3&9v\,9dMz| <h70k.<:l_6i$ܺ2R'Oog;O]<}c7Gg~ c/AU@ 󝬑`ܽ*%[ (1;*z8rO==Lf*{57@t*;^(e InF#nRÊap.2g` .)x}')]caFXԖ`ؗ;ENH"1U&uK׮\q4L$&=R}̤x~trdpКοv UPgSH%szAbtvÊ=JL/&9o8gQw~UasZB7T47ÄoBd8|ҹ`<2{&c?35Yͯ͂򊎉#߂?w,àVl_a_^\6JF¸\LW?\߇aWg~ޮ{_c%@ )Kb֓S&o ◬yVWFε ś 0!{uJcbp(c`hѠꨉ+MnXę]vwvWTeRq$<N?0C!펲;*LD/TD7UfRW*ʔl5H/~p ՆVBfd֗_?'صNp﬙'?)6X ;~Go?Y@ $̫dĤH ^Z^HpEK~uFQ&cTyʑtڎʟy{v3pBɲ8KAq̍˝5kpq{2gYe>޾NGߡ2 7cRN]~$kIW벛I`-)6)n3[̾3}y&)񡆁 FܬRT/+O3v|cnL- 3-Oc"  Iwe < wQ+q\Vej:|*6zв01&%/ZOq=-+™jkf@03K YIeeZXzRRk͸\mÄھV@q&n6amxMLS67?߷.O#L35>7r0|J"46JH@sP] E֬z,[ ZnxPY Al~R# i09gѣUSZc$<@cR+7YFDĘo$_@i7>ckuz9pT2g)ܱ̋;տ=7{[#!T໤uZm$QI[;_(q@uK.I+Cb݀JHo=Q+T0)V, "AB; uT=k0^0~_ۭB7Tz[VAZ/6 nGYUb] r3}@*VP:&ec=N ﭶq?'Ge[3[f~|MO[5{i_+Qvoh߁w.{$Zo7cigWYkk%"#k6~fQ[Ү p)V3L+#jB˯jPؖima+#՚Q35VVn7@ 5'L?l]pؔQ2 MXԖ$ԕu ~0kix3&>ved5WT ⥦c{oOLX*ԅ}b%[OoIonkP3K&<@ 2~F$ e>AaHkvC r|5_PYĤZIM5&}+Hg2mW1$ 3%NR(3Ϝ5OavN@+6Z]7P$[=V[6L!>QșBOex|yOY6^v2L' +M+%]. "٦[M*L"$m>mi'?ZW[b&j?¿ s'[h>R(YҚM#5@ '?h{썽[E™ a|VLhq2g+D&I:lkJ|*q'yM:ػTzX6V\ͺT?,Fbc. ̳VI\?\o. ?XKC3$6>uH]$[OȔQ\m[v?I)35[K`r +=J &?">ò[+e >WO`-MR%PaRudsƇ+OPCu1Mg럁sviBUWu_B$+8xL+pyiI moK Xm-̳X+(mK~ySoZ'}n%2"!ZJkCVU`1xV@պgp?뻛n쯬}dWh` IDATPb5uPY šcWUp|+Ѱm)sVpfOf{qgoЙy9|HK|b<6eoG`펶/~|e֌Y iZHͻ; V;?{ay|TxWVB߫,}[/@a'U{HVVc%VG ?ًO@ [ÐLx/no y _'.z ì}~ZɊm@ t?ًDf|Gb]֗Aq{<׉' J!:YBk2)h6|j)0.t zɹV;Ʈ+Fޢ3G4:ϿvvӾ\_i1C?@ȝAVj6.M}Scϱ]".2gڣ4M£w^LӤo@iALȚLhFYe Uï&G_tC@I!?Cӭ1nL2h@e%RbOy{|7~lp[INH0,IqP%K!2,*}?pd^FBt<|J_B zŝKС3>ʪJo 9O(w19git]0W8G]Cc;ki'?˽㧏r'7ׇ<~տ@ 'k$wJV'=D$JhZSzyʞp⍆/uʎ4wHĦ[yqs;}4 Yi9}SXCn: f$aw_@ O5 ߓZ][L"%"{HaW.B|D8?k;9Tw1hT!u妣s/v{z 27rYf$(f8_kB;:m2J֔l1H–Iv>|c/I~|D|I+!Ft'3`;eN5 % McQd5/'ŭ>l-, N^ ߓ幣+OˤiVPPvpd $D'vYPAb"bǭ]n0Tr %%!/Y cʐ?<1g™ G碿xp{,+*?Ⱦ+€$'tcGi ;sS_d4{}B?T^פG\T/ #'#2F^$F 3`;!2,9)?t^υ@ _DQScy‘U:Q=%^vўֽ(\`wQuԤɘ;U%vTvF1XoxL5oY 7ʝ5׷}.xWg:h{ۓ9S*tf_w^&cx!2ӱCOI֒#;f$XKjM*M~M_b+o |jxM`*KuM2]t*?nWy (apry?¿RXR@9Ә=-7A~ 6q:u>ڶWnepj~/ b``]7t`.=p#-{NŠ9jWU}% \6rB\d|-@:P$2X PwT=k0^0~_ۭB\8zGO!-3G!&";?΂ڦe$uMuU7.{ꞚFRl/jimnen$ 4).x::dr~2CS/5G2mHkx˲?쏾h;3F;TI^_/y #]?(5*jkh6SQ{^;=֭L뭤Uc  1j. 1iCr@l/i;p<{Qbg`++/CF{#:<;gˏ㮣w| ?Z3R/zW=ڂNToW9#uMȒ̔!W|LJKt] VÎ#HML]BW  d@+OP~ǧήHkvC|5_PYĤZO54՘ f}Ԗc7I$fJPg89C!k%UG;vN@+6Z]7P$[=V[#!>QșBOex|yOY6^v2L' +M+%~˸&l>ݡ(m6 Z^V_nPa 5_-]j--1;]wB\<(_R%+-R˾AuC5Yi9HDbtrs;7hHjDaI_Gh4 IFf`uoMdX$ioqdS+͖TEeԀ}_t8.NnLʞ k=3QdUQ $IU7Csi Rspn$I"-`_qc331{ -~Kؔ;տ+JTx4iCvxKrorI<طtld}QZm;,Yo)*eG8SWA-056֐_~pp;Ow|'ɍ@ àxugn"&"I9S|o?"+ 7ӵ~ v\ @p!?h{썽[E™ a|VLhq2g+D&I:lkiL|*qai5ZcRcmXarpD&PY0t0Z'$9p>pQI $`- ϐ!Ⱦvlz(N՜"/^~[2=w&Nf}˝ڦZִ Ƀ3z/zږǓ2(5ȰH~d߫\£x,4]ę|oBTx4/**cu63q&iӖeb LϝA^IQaV^{be_oRPPM~ @#âΜ1 O?HPJ~@09g)I@+%k_OZbEBW=R5>],+Pul==vq[INHR8Tze[޵,+3;i=&AMc5UeW[s3k\D74꽟a#@[W94 J+KYPOw߮\  M5@ Y ~5=:J Yꗜ'tO,Yiܾxf Ej>;X[48VR0̶1u˶ A3ettm_UtbOy{|7~X;jlj|;uG TN3!k2=bze%{[n;> ?~/}w* 0ۮWBvx.H??YT$"vi'CMxyr,T.:@pI&k$wJV'=D$Jh9[Szyʞp⍆/uʎ4wHĦ[ @YK/qhKzYi]%+ռ|#K u0 g¡;c]72jTѽBIGTWD#A{^ $ li0Ëֳп{RmP˩ IDAT d[H Đ2k O)߮?(yG#P&%3-6^f͏ڿysvdQqUj_=)>Eo{>`|*oi3T>+-{?[0Ѿ9s'\=lxжnA{uxPu->O<] 4/ڛoXoIT 7"恢`=Oc=k֯X{>~}xrFFUڦOP&N$OAJ9^+x挚~ )9T5EV;p|q K<+yKc,eI[u#rR1'Ev0bV!IC% [޴F3 _FVjnKpj4rb`r:;nվ> YV8Zu'I Rlr7{ŤSB򿸿_ 沫o|jkqQ]fV[Q4`Yu_D5۬2uFE-iHI{? ϛK:>G}';0JO~>|eΜux_}}?Akq$^8} =wn3QcGC|<aPoqx~CHJFYԶ>0G1@Q45p7d^p|Fl_Qת"V܋! eoSJw/mu]|RB2|]dprn|w)(N8n_Pumoh[ሳnw2_cܡ흌U%^Ti?<\UE'uL/RZQ_PqD oHHi¾>TxZ FUNX5h[O[[T 9RTEKIy1m6dJt{Qr̜M6p/S;|#Ӳ%Zb]d 3͇?aф|vʘa} rX^(g)bRr_KMd0Cq11 Y_ڦb\fEaSya3AQ|./\_ =e^˙*Z]0Eݲ~\4 +Y~[y 79ou0iPCǃqG"`FUTU46ډ4pߵ+}~H ȣ q{ކ+ac˅0#5[E VmՉ<;dj~:%́ 4Ud_SqJ{AS5ʾdUN2dSvl ou;I$4Tf듡]{JT-"gi 1jj}z}/x&hvCU].\Hf#ػ)3 i@Ҳ~;Eb5עxDz$&Bk~Od 4PUP̬m>I/f=a_l[TpZ`]e gNʴ3h1i0+T3Q]Ҍϻ+4 WK!Ta#J{n>[C;sNdP}] ]AS.,fD%J\sGg$⧜*2[Xn;Rs+7>FéB(^g ɐsʆ=`@bҪgX' /2g@i w7jJvd3GL6oD;V宥 xn/vFOt5̛ڎY3-^\GQ^pN2SG؊ߙu l*@Qἀ\OȚS{fDن3c_}/zdRбL˝ΙIpV'XVD:> s ?,Ҥp`D?k̄ LƘ?FNF{ kHqfr3ѷvsTJ rv6u #ezI zI С8y7s?+L]zĊzx|OVqshQ.%Xbz8:glq8dSk+ುߧ$Aa2&+zg 1g7d/ ;ًU43uC[I ln9hLcE'A7$I)1xBVv"E Rwgie`j' `7]FȘPwž~O6t^[45~N7M)g֚O)+- P\GRerâ˚ Z %wm>mVӪ?XTsY\ca WooE+֗TNϥ^N\$I"%=8b2KGN~qܭm9ydV()+f+|lb\1oDf3"-׏w9<93|JDVH9k.!&Tt<ʮ:ťmN-hK3w|di8d&~dts[8P!rDYo릹|$I©:ȧᜭuGNz;m;^?2:W`nf=vǶɆ\IHODBvmb9!sSrRUW`?BPD:>c'%뙒3a2QdUQ/2IA_j}0*7e`I(So of~47=GI"We%ƩW_ N'R|<757chaKJ FcW\0m,$$s0nS;(/CY$\U!*\B" <%\5撫{|iFu5f HE8[ZзoC&Ď|Ha#C[F]p~ d&ܡy17N0?x65%~*e[t ly˨e*9K b_2` *_R[%CwKNA`~>Imw7k(BaG7wKƮV!eܬ8bPSJXiX6Ar᷁skAca.hs&{t?_K}.@#Hn.MR+1gNxQU=D'j?Ttҹga@ mO{/io$18.ܞv9r F㒬Im8Cԕ1 G6q[vFs1>As55ηY0n/# m3n&Cs[3;oԯ\EMQ53wǼmopycX0niPy :9ve؅|ch}xWPj{)(ⶢ#IG+C\ToVROu9F ɾS{,OKIg8U'QhZt'UuM^ 󋘖;08Quwwm}cԿX2jӼo4vde{8[05Ne(BCK=_͑CXf:7κկΧԷ4%XV^}BʿHǧVwU5#o6I΁|=7j}5ee#e-ݓ5ǣ~I?5x_}ޝ_֟ާDK8!B;>3b11J~!o )& }6;~ 9ɜ$I8| tF u%%0;x,%Kzf@ z`!Ұaxx\)"O\PYqWh~Lxr=x@ |N> ~ |B _j%RR2rN"2dO31JJ>W(c>$5g UH mRp[is|kh&D5^/_BpP]Ҍu+5+ wW |@ SX~P!*DI2(@ @ @ @ @ @ @ @ @ @ O3?a [Px"WӐ3|__&Ʃ@ 'z>[vPw`^?Sd)ĥJx J7MB J=I/zdfЁuޟvulϘ10&27h~*WzLkpjj:$ 2(xN7ʞ4T"!2ZM:^j=y9 QK?wÖS>#%t/T9YrR|lxC݉-{-;Xn>aGPgi_| %$>yC1WBݎvtr}_? ͭp=Bs~~/3I&_޶.ℽ/y;a(1~S[t_<]RGG !CKtZ}rS*pJ+ NmЭK0*u>&:Eb7UptF wv:C&m*opr'۽$ݧXnpݖݎFsÀ1_QtS;l#ުg/A {d΅+4[J#+5_ڳ)9wH'%1+}oejC+sž5v:H9W$ߍaDV>Ri|뷟Nݟ}<ۿ@ >ɚ 2uIʔn y- vEc9KШu\1#Đ2k vTV!m̚yA<SdM0bJ8œI|kyW+5 )xM]NCkebWTVgP} adn?0guoqzɽR1}80O+T_ڍ]}߹ ùZh=.L^ >ں ߂xز|ϝ3 ~z'K\w߾>^ug໷B| |Qؼ׬u$}lCGǷҗ'+'IpbX4~"iO+"/!̡w7iskap*:lm9$s|Vגf=զw|΍{-;~s,˟56MegGZ| ~}= OgoU>?},1v1_eӰnxnyDahlI]Mu;D+C$30gIV_+‚oBMyGtZʀ+JǠ̚?m@ c5)%, ;u8 UeNMmJf IDATg=~撢eS:}oTxZ FU8{ 2/W?PbԵ*2_fX~+}I<IYv;c1]wN l_wҠ`m*cnR9Fΰ;nV|ͮ4( 33#وVP0}߽(a2˕ oP_C.BxsEYxnvL `|hi9yq9㡹6̜pan}O^V@MGoWq VZ̴_$xu:i&*\š_F97Y9gp6gM5º04͞vy8Smzs& x#̽9P0gM7>r43;`HZx}0υ<ܕhkUsDX^ @p1 *mLLs5cd==vQIfnzsO9K&xl?v*?,1k*X/jOw Z1Pv _${քj]kUv 0aИGX+{(¹{Crh6cFwO=zG65Q.3xԿ&z*AtDz~TzEMY>cGDOH-?>al9SbX:8UP`Sc}vuw-I{ O7nӧYC9+ |U^PxVB?@~&dfeZ»>lo~\(r&X dd q/ӠK vO`@S.755V˕isWlD~O`SN㛡:IT6<3$vh(3pWh2=gU8IϥZ[R_!Ta#J{n_i9gZZk (^Kք~~,k-7G1ER{RThT8v;+}p90IWtKOOds@$3 N\ȿ83 SudK5cGfsGoӿW1>'+d艗,n3qC>zOF+;c&LxCWbG~ۜyu9~+iwge8zͭf˸p_@ >|)f0tNkAk~2sB ?}$2(ԝ躻;FbddsAYo6t^[Rw;ݖ]3O5WTD'Kd/V. $If+dLV8]+A"}*o H!{ƇLz$,#Ɯ}kG55hnknhk04IA`Mi6doTJH>Ny;㻷[ٵv(ۢ3 jiP{#NJ*8Q.5g  uٛZ_3X+K {cEvks ,<g%߱OV@Iu4gv1m\5v{"=>5g7ROWRt/ #cnRpzxcԎ>| \6?#$A93IcsH u oʘ}s L 3w-Q@pY6ArgkAcAM:CˌYEqܗ{0eE%~*fp{ Fy:ѽpzƉ2P`2ۦ{t?ӥOPeL_;^o}{^ʜ;ds}/_Vvѧdnw3~q̛uo[4omj{ރg~leo/~AOy^} dl_ѴQiFkc7m$2o?4mOhCVu9k7t,[j5J+}#0O3zl-,61{~M3㠙 :оv ų?1g&>~vY2+9C῿ 挳՛VE#?suWᖟ}lGsu$)Z@ .br=//'ʉym=b\}^wwa,&_KKb,{0k 3$}:~s'3[z̬ 0]5|\GVmA T!@  o>Y, eOQpfl̯}yy!ᙟcf@ .~e_PB @ Lβˠ@ @ ."DF @ "B$k@ @ ."DF @ "B$k@ @ ."DF .]|?}_1~)3FB @ H0Nl}gʘ,32T oA&i`tZ(3bB@ 't>EV:мw4Tкܣ#ܤ7WVcJ\){ N9O CSBoCZٓJ]4DFk78I]#1!Zyxcw5*wGsùC:{`ߕ`g:^=/kBUx {;uerT5eG[٭g5>;/3bBB$'x=fJ=" 0+&6S{>S_wλʺ G3>9pz/[wLf&gOO|_r*5(eY+nCӽ|iWHMޭÎVmob+on[OIh< B50 48>%TE0i0}i5Ix?m_3o̿0 ϲ'( >Ͷїg0qym2=o/+~훖;Ɩ}oejoV3Ro؀L.9~ $W62bBHvs @oO$/WFo[` {_Rw *Qb* J@y-*j$AB䗨 5o`ˉGO׫z+Ab;h08A./ooTq7Uu' ޹Wd fbȪ>xu:lJvJcOt[v;  d|Ee_M]z:h{Ju ۟w3zKu9l+(~] h^:V!̞Ƭ:ݪ}vo6g[@f {^Ԩڭ I_CgSH8b2);ת+,]Īq#KV+v_M6}Lvc:1нRmP oW4D :4>bK !s|MxBx5m,S[cJ8BCנ4O LE Vi(}{^4yC: $v;9|N^rT@)lFAqf;i?\5#+5>scOęO?ʇ={῕=*}/u@VWoX'/t]TMmS/qߕ? 96wa}qo+ÒK&*2"0 t9\~o,,&ߏ{ߏSuncNz%eŔה5pmVF5[9S_EbL>-wJ6p ռה'R(:G"+dnvF MCkC mOM"9.OJ֣:u͵| 9~)o`MmV_Bv;x4%eŬ;yjiXw+]24]Je]N!}MYN;nOXϮ U7;\3fzJD/==B@ >dǛv6 rɀa;/[% 5<9W% O{`/ؖe0 ~no4 R~@@Vy[צ& h2lOwDH驑3ɜٯ-aJO4ϱ5qDCU*W<FWz ىkU>VvG $K8b%w^Cw!py 2 7|m &,}V [Ǫ-=e^˙*Z]0Ew㗒WnZj`75`p!S\3rf^w`-;nš8ik./m!c|]s---\u);o#1&Y.C 2@&dMbm*oVѿI#&P8/η|:rFQo9[p(Wek%$VWUp /%.:ջߧV=d҉ž[_ u~+{?Voe0 'g0 \^76b9ښ"׷/_ K&mLL3+NH#9/;$ެ(qpżiuK{'x^!oHKbt3scd Va^0bj:}z&I$ vy׎Sd)l|؃>=ݎdިu g{|-'ܮTeG^%M+%|BvzΩ +Bɞ5gW`Z;{뿥] 9BcaH gsqS1wY ۺq45T8oV@ZJ:ROkC_os{sHa3+~ $EV8ye] m&Y#xgrپd[BlT?%R1{fc\1L͝K҇`{j[pN CBbG'a挾KGNeHIql LNcWmj}FGL^+'c̵v$kOdZLM=oŗ\EmS ~$ ,*l=ɲں} E=5V/=kBϮ*ow|++}n:gʿp@ =f^`pХ' 0Af) ˚+ 4U܏oLTe?w'I)'k F{$CU*W;4l|+Y4j3*RPoM̐Y =}f/ʴ3mt3T4OhUtnn0 dM8G8X ɢ}v߽RmzsJhY$'E_Kc3"'\jJvd3GLf J_hg4\4K'^̼95SRwB5cp{=|;ɚ76̹s~<#YNu9piIF!Es[7>2%Ny;㻷[ٵv(ۢ3 jiP{#Su*TU_N}K=HDJ\r3{1qd18UJIy㴹[ygr2 LlQRVWW )Ou|Y#81[hlm@~$IdmVH*=6Ləΰ(@IY1-|kTU_ ^u]tM5ԷA:6R'??;&6*Ny;㻷[=3ĩ:9Pɪ|[8X i?`u 3￴dwHn?sNlaT1 ;iszΖǽZT=Yv=oˌAEV̺rwͥyj8c%A)zq[=tܣ.} ,gG`)og|T܁${ڷ_ώ>1Wtp{9~o ]+(=K&q,m$oPW0  3o!͉3p{;fE46η3/ϸW mL,\>ڿyc^'ddx5/e5yyz<]h>w2`ɪ|[; 15XQf:7_Z"IrH{V1.*yk=6S0t*j+m}W_Ĵcmc4=c -|5G*i),$WI+R蹧ъü ߡV0}픷3#ʾj{)(ⶢ#IG+7?;@FYq %s)_t_X3k@ e;*m)W DE:b/X]]ʂZvUV]eok =z )@HHHIrsIrg+=9{33=eP$A$&UK$D"H$3]@"Hncp)i!"H$D"`D"//H$D"H~&mPD"H$D"H$g2X#H$D"H$Dr!5D"H$D"H$g2X#H$D"H$Dr!5D"H$D"H$g2X#H$gwMEؤz'ʰn$D~Ц]tyWO .H~9Z(0q,2^$|_EJ`IqFLs M2^a(J`. ,y[Y.(XM&k_]Z* lJ*RX&ķQ<h 4|~ ߱AkFU C+MoL>W¸\l]_n0lvl~נr$X_N r֛l:k4ҧi,p*jFo9]vvo矡DfU:NЈMSPTX񌗂a+t'9鿡#sj\ܹ-7TFtEr|s>[mfօ&NIMBQT>\0y :;{KCnA6W 5lO.>_ItˡcXJ*Jou#n0}iS:24g-濫?0 o_Tx4K&0L]ٙ,޶M w5XE~QV\"sMZ`l`XgbZ&[n- &[Ana]QD>2k}IIH!OyT+S>Vm#; D>';Xvٵ]v9ߺu\އ1#m۶{wPR@U{HV~>|?IJWOأgmP{Q$9XV@R77l~G~8tNZmVܠ-yLb[*AQϽv>/{JӀxU9pNZ=D$* MS{O@6TR]~]zX#,VaLlC+LGNG{NgK~{&sN4־s$= λE1kbauw@#ʱ&k/]vv90?CV*AFE οBI*C€IKLERZQBbt,za:2͕C%Xu0.]J&fwNLDU4*,]+YmQ2,-7}޺ؑ0WMad1|濵0k?ڧtdb)|KBQ%o7xʽ9ܺK]Ir2G/<>K3 f\x%'?$6"i]J5W08Ld7ɍB~16( 51 uRܺ}CoPtlޙcIkҢA[3?xlӗi鵂)v+?gv;/XO;ω6ʀzh5=z]{=;ocnHP du+Ml,_EM}t,ֈ6JZ&)/69AiʼnM.S4v3YgbBf [ذCj?s |bOqV5G#*D5S94Ŷ Z g'Fk]`:D`K[&Zﲈm8Nw"UkM#B x_Af$űz8u{J+ܹ)4[ŏx9krF?Ͼ7ؿOC~i[ޫV1cGddSZ9S}d>' 4OBTB媡暴1I3rE ^C c| c:.K'rۄh]gݎkvކeY,/&+ I:egLS8FYhˊ-*M| {$D'ҫM_ɨgH0Vf.cg gW8)N'a?ay- s^}o1dΒmuQ$D'"s)iRXR Ѫ`Yu!_ZWҺyx;ӡyi(dZɛ^?5~N`L;;)1 >v~îG0o}u(￯-Å0s:0 ,9kC Ŝvp?P6~m''g]v9Cݝ -ŗ]8Qkܳ?qJ[~p?9s{km6MB x=D>Yv򩝻^xS@j)[zҲgsh&.9BIu]O=_ڽ;=PuDD_{Oz)vlrd`uH9H`vj* mr։qlp5]c\oYlTbO> UUNʲ?Ч]RRIoэ iSٓX"Q ҊR0 NILSzgQzR3{9-Am~UA1^VBnvPU=yvwR~cא9տTzϩi3["#q=8O| Jll*E |/2(&{xf:z?ڲ%bsrPEٗ]6BdGۡ Yx~'7[*3]Y|3V!<+hF*,Gxf?4O:p{mCy;Kyg{,At3s.qѯ< Sۧ sV]KD"9+Q$[X, ,] FsTL/ldx:0Sh5Xl)ZmһIu]{'{a-@^d~jPgv䨅ȢX} *tDs@1*Uc#NWa憬UuOMw"ߩT]ׂGp_n WBQ]txˠI's~9iq`y3ٖ~`9}ԿOW~8 ka/=5]c>[2<Z{>A]fjVZ^kջVTYs_NMˤOtJ̻?U=h CN2J+JXk[` z"X֕:-]8bۡ-ңã,fq),bt5OV}k?㭠eVLp el:Q=2꿗l[0 w \Ks/o5Xh 2ٞ;@;XNc?~y9=q M%:"dy?xi~*U9r"ҊRp!.2G .MWi{"K/q""%g8r""FC+ oEL5Jۿù߻&o/; K I}w_w?G]9F ֤`9R%.NL*lЯ ^zy6b$j>xzٛ*͍F%5%5SOǃ쿸n.VNj׮(11ee/BINk(Δơv톹i#VVs&'hԓb;{~`A^szv7Z%6g/z+ƛ0>A!, %!`D"kRD6QXz!pǺ}7D%)^'GZb @LD 7~xPU\;Y~ƥgSHmFQ ʽ*׏M:E,2ogD$6CQT4U ֱ{ 8]-]Vr2~curOY ;g th) XfHp.t%o/yȰH㽥WwҖHŚݫQ:EqfLLDlȭlz|Q;3(U9QzzO=0 6_O6x=aNզC҇w9r"qB]4̡ `Xi<>_4-&:hӬmЭ]_Fv_nM(*8V[Ց6~O\ĉNU?'Կ"~vTx+8F\lN}EA:QX9Pת7Qxz7Mk.uJtT<6_Q!A%&vm׋:pf'O+(m|E[gWDEՓ ѡyg:vn'?A]WӠte{V[w 49;tܺEQHKlAVؑuz_T{qhO}XOWL^aO}XoERuJh4IrT\k([wӵew9Jxƹު' r՗tMOtoՃ;~Y[(8yD28}h6MZV^ˊ(.+b[VZ7kKSCPhue5߉u>ӂ`!Q6V^8V?L ̌hW_ 6q" vl%%vy=z:+7.%&}TU+9i%%XҦ-֎혙=zbe4mPAQx-$+0ڔrţ o!b χҪ:L;^ \US-a`'n)8skGL J Xr+%T?1Rn,˷(αH魒ҤPh.Z7S>^cb_}^{ҍC /r>Jf w,֪#ŧ }Z)Aӏlvi̿׃*A=%g`AA L˂&k^9CMVۥ:]jX8e/J:&܍~ډyz8F=źW}j钻d+~ԛnag_'i@Mo~ΨPTqv'ue|I] IDATax;z 18p.Gjrl,"cJwYb^^^.øzDERR^}k8|<+ _DGQXe.2,=Fc&׌1 oCQԠe2oQ=Fsߢ( {rw~{QTz[;wg@Yi'g39,$ Vu|!0-y{jnw;y|擀f%w`ʀ>? :⭋g"N &[(sj:s-*=A~1:6T8 ־ꗚƄqn]j-|ڮ}ǡc qm!g'޼=mW];Q5cv,Ԝ0ymK/bmބN-_ 9/]y'_Z_͕9U\׿f[B&s4 Elx &vt{aVffp̝;1W@I <ܙl)׭]7ECJ1c+Jf^}`O*:go]0}ֽ(XEg#T1+!}IL"Y(].ߥ%$b{֖H$Ihh&m1~DԡP{eYUq=[oD"{vH$_;T=K-H$oQPthD>}!JlCV4A6+3emx];eF"9Х $&1 rOf|a(D#ڵ+ڥDEa`fd`,Z<Y H$Y|IiD"u4D"9+۠$D"H$D"H dF"H$D"H$ Bk$D"H$D"H dF"H$D"H$ Bk$D"H$D"H dF"H{ڵ`X6 ]/ֈobTXZimHUqFN r֛l,8iZf{)o9*?(?8dg!\ķQ z&KD  d#S  >ŃeoxNTYY{_au>vuR~*'hĦ)(*xK^!+z_4]22j]vog;U; ?Ͼ~t; }b=¨g[ w>m]|_EJ.qٳP^} ?kv1 _#Cd8䟀>yKti 3_=OO‘0nPB~J53 ~LwpX W /  nK7{.%9M*6( Ķ_ 0j@0`}0qE@u_UahQ9$}݋}OzMom41MPz+uL!,Va_\X\f6J]v>#T+8.Cm`x*eNgK/6cۿ(o0xΉYF^Ao;o9ߟaqDPLJiZ>}R` 8^o{1rMq_;PsTkKġ"zjsx( [»_5|glFQw]p`Zp۝GoBiP/?6dJbH$?r&JZ )TVd)SMo#8,b[Gkz8m11}A W?XT!ybŶ ^56ey9e\5tv5}\[yMZ p_RIl_wξvO^~UU~* WƩh5X23tW08Pw_vc]z0}0<#BMز/N'Xrf4AJT=(bKpUbfgkwbEC|>@b 7Xot%*Lm'};x^T5o j @A`nm I r%̙|vľN> k Y|vw]GO/6=:S ܙ]6Mr_W—;c^뮣>s`+p='ZAGJ: N7X&nBܻ5i0Z 5 gBBd? {`ch_8Q.9@D tuk`9yg|;Y"} M毀9AǙ&:9r{z \{D" P~b$klk-{[NGkF!mJB[ (WOәя8^s\V k +-+ԨVĵR8Y'Aަw@j_#[̀A0(j:k;+ i HO9X0AnLsxGtrĿ?BοǮBmdDN'7XjH~U*fFT}U )n(0τ!bU=2\pi)߃ɿ/' U#\\ka`Qf;0m>1:o^gN表+75^v3i(4cBn~ Ͽ9^9&U1\1q0E=+>IW7 6dN B%ubj 0c`'aoO=zuz'|&hx=~/pT*mʝ1w_ } ?/k@k`9ygw?w"x{б5~s}v r'y\:fg>x>H$Il'eY7iEOo5Xl9pm8 MʏE-ݤZ} XpyM4ZQ_rSd~ꂘ .ѡXI/י_ChQPe~ʾEf}n叟Ʋ`ϷF3ua>v V~xĵTY*Ue(O J,4J]N+}#Twj7*]\_NQgsnZ' ?޾3K1⌌!}7Ui93F <1#UR ^Cy+,%k,wM>Y(6֩_!f1;]׎;oUW(qw>rĬ݇, `(ߣgʕ`g:(6>g>eX=RP }ٿ!7 "¡YB~J jҪ69C1sL?X B'垟E(w'nHg4?sae}2E8z*'(|v= /?=/rdK$A6*M?-M57V9h,{dT:X>ۋQotNY,~qE) Ov\jKRӶ|˄/~F n-gD4c_ߙR1s(xJb[(ķQx֪3k02Uc].~Qck' XBR /B'ASh3Ts& JCM߉S>uSsRl &No4}7D%)^']L_4pbf՘iW!ʚ_L췜u"Ծv<6|Xx;ogU9bŬW=YbE7vpҾr=&Qp{ቋI=?)jCȈl5ld?`+ڵƊ|S[WӮ{.MgZ"$N\סlO;Nʑ{Le#j~KJE}NMXQӡx.X%Ikqf|g;OV4p_GEs,z[=CzJ+Rab7<`Aq] z\L r|gI.8`]ׇ s,UNܵqhEb ؿĤhBİ{ٴط&bU+J\hT٨BQ4eOzJ,o6P/;ߩ}#}TJY*׿ JXd2h9Hт5|KԻ_O%)v{J˝詊+@ \UyHlMFZHyXZEUO_?3:4ŗ,X- |Nn[̐xSq¨p$6'{}b⚯5r0X`  _P7n"WIfB2 ZBT>YuFF|LOy,[op~cqE̒~]E s}q6~q"8SpIIUJ <ş׉IG_iw DRcTb{1K~dIYEYJJR+ט|~_K> X|~:P~F 4?%:ʋ,Zb&Ź*9R/(` VrKmGj qvҠdfTT]:,V!آVVmjèëMz^&j՟f6 $Ϣ4""AdzRv۵}#TW0߉}@Cl"S:Ϯ_,φnG4Qh9HpY /v W=7Y^5QGEm8Qw]<; ^x8qK,7j8K&GŒ閕V w;SoA8wb`@Q xɎ o|M]оEB69b˅Kq^x&+>b61jck\}C} 1 =RpzzTxoŧwej.x␆w&O}XES3D=Ga`Oqُvf lϺ;ħbM`_"mx7ŗ"~%J 8,ߢ8[IԄ(tL4`}[3S_R.S5,l5F`0tUuoGFq=T߬cxnRvrTY=>^cbl~ۑ׊d~5/&[3ppG)zEAu}kK/W*_s}FgܓnLZnhk'P/;.ݎP``AAm'vc׿zRqQ}_k;]> X/uBM !Fl@R5{kxA՛ŁUgq`q\>}X!pbo#u;eЦyve5*BMb <x\!D>;_8G#.F,9(4P^|^>]$&v"ti-F /X8PjLqPN?V[Yx_a,8Y&>uF{&WQ s?e^@Yvpx{X|f@iNc@wa#38+^g"}|=O|Ml?HVzDO~F`5wUrVD?X8`'U%upskP>+X_יZ<g.;UyPK$?JKv|wi D"H$!LYyKO/uk{i5 >x{ n/z0s ʔ+a>-ttiD"H$2F3kWĹ2`'ͥ%r/ʦ'yS幯JH$ dF"H$iӺQT?vx}eGϥ-%Imw\)qi H$D"9m[%ȓoJH$?4D"H$D"H$ə H$D"H$D"A`D"H$D"H$ H$D"H$D"A`D"H$D"H$ H$]g46I2(i(D"+iz^w=eK$_/ yE|ufR5 KVFU C+M5a =hIAzmEt>M`l/-GG6'W1}2?d6 OdRzt\B~|ĶP} ˲:v$!ñ,3NξNoܞ: &)6 EQp;d?,?pD뤶ɖ~)t>vv.Cihn'^ËeYet~vkTe׾[_sHnaۡ͵q޺u\އ1#mivŨZcy*0Wd.X?V~>|?IJWOأgmP{Q$9XV@Rڙ:0Wq`Ɋ>b)ζ8B)x༻\F-_d5xCD€t<%gcbδ*}n𖏼M&-E`pŗwxo3L% Xo3L\Fi}U)}T4Il_`cg_{^cyMLşJӀxU9nWU; ?NKP`=JY#k M/a{> [) sEjQn:$-17JiE M :S^Z'Mc{bXhRuH}\R(?nj(v;`qĿNڧkM#B gI_N_lr||-"*v3mӔlJ+WB?OOBTB媡1I3rE0\>d:*(>pĻu]=&V#5OH wU_ 4&&­Ӻyx;ӡyDz=oaY'ˋ?HRl39~4([GS\VTlʏ'!:K1M’o]HVoǐa\8;Tx+؛k%o.zV׮a]G`ށi~WJCS5:dB< IQY[jtW08Pw_vc]zB#O%vl[Ю#L'9ɿa:a'JOpDqlNSjEWvegֹ:>:vag2osZz&TLIh/}'%!hs1H<ߌs; r\+XJ+JIN<纛fq)vPU=yatJMg_ޞAE9o\$6#ofꀋ  .*z$)᳌In(v;`P/;tSPۧ.&&"x[wTv)HIHegΎƍ4OEܙiQZkX*jNCiK/ ) **xfl~ɥ؜dQeW%%+'QCP; bSU0̜Q曱g&^A5v,|Va>3syjցx|;oc:;yƗ_:;s{gAL ڤ =30w կ< Sۧ sV]KD"9+Q$[H, ,]㊠:0jr$wAqVC,[I'<^a>  tR9:YoATSnճN~NKybw+ZT|`oYkqtz_ Zj[tص}`q-U?ŲU:k~ч2 uN%yh0"tW0G>oSU"AsN'7Xr:稘^6wro9C҇3P^ͪ]k z׊9+w.W:˩iiןNy"QaQthމg*svW]d˖%wٖdKظv(NB BH&7@rnB@BB blcp]m\e}w9?FZi-ΑV}}l77s͜9Ozzylcl=o;[FJ?UT7T3;oQ(|M e[`X߬eM6bUˈI`wm u&TޓWUPT%C/e$`gV\ΏivrI:m,cm9^1ۚSk]~ÕmNJ㙵O`6sG/dE%܆&xtŬrbbaL }D~}G&ߩ~Bo-mD2\a'kn|9edgoZkʺ7X}cxnĘ5}X|X>={0-=-= ^/׋Wq?G@KH@hh`-Z`Mřa#.,t>}Ǽ>ϟZ XKpk.}~7{/P-1}h|? 4\܊Kҏ]TQQhs ſy&}NlO[ 9“YK 6/?ث 6>ljsEmIu8-N?dqjIz`MGl}O -PfsfEL֠C}O.O m_]n9 &uVqW;*? ^i2^ \Q }"&Ye=t|'N?R2ڏ~#L=čV<~;Ɨ; .Uc.4fvۄzqN;NFJ?YDBLbȵw4j[ojk< w`CzJz#޲B}4 ۶)8Ϭܹ&Ft ۖCbl^fд8بX;`M +-%!&%\I'mG7mh;} tTmۼ%挚ϥçPU_š3IM sR~3?ZO, NS{79׶?ô,r-}tD/66k8x 8]Fƞ;II #Mwb_#H//;O(BO~'7r֎HKfѸEdz>]q@C}؟蓧`_@SSACeeP^]^}%$`++(.)F5md.hC]Z"- '/k0Wy=IIT8>< cR'ڶ-\i_.ʱmDۢcP|58b~j3RqMt4.Ui1k P`|T:e(`CC͑&y! U>c`CV:*?)Iѩ- e38)b&8Őb){j@?]o[Į wټG3٨F!J I@]"MɗD?22ُLS"鈾cu4Qt_ǿ ugm btk3l?s-g3mΌIII{O Y8&^sXۼk G3i=QyN|g5l~5~璝1ѿ@umU5s=<(eZL^VnIi5%t|'N?22ُLS"aTWRPpt_u,OQilP30.?ujgI`΍uW^ϗگttRU 3-^=cP))YYX|'cWUx+  ௩:j׶`[piۿ"ެ档s`hk){ZZvxaP֏-M (Y'%SDhioIIqBv7n>Sy۽@M\+ 6/҂^h7@J|I:5ŭK/i>mk\Õs6?ey$kA:KIHG%jdLhUKr\M뙒=}21tWBqdg`a2t9_sQF?Nv_xycqyŇ_r+IIdjcH_}D~'~d'! W;lƯl|˯iCӆ[OM"w@m^إ%ZW3͌抳L~S'8x0 ƤKF9WI <\Kam,I6MAc.*6hCzM>hg?[]tc2pђz`!.DGG~ЧtpfYyx@L }xqP4˯ڱ׍_AKj핐ih؈]Y<\3B>Adt@gCMM-%ީJE˄?G^ua?#^f`[̖OSFB7Sr\~< pa'\N3jT)Խo-^,3kl*OXl5oh+H[^bv\mN]o!#ycaU;%?PN Li^+j> hƈKƶ-6-ɛ˭si|\r5ms݁,;݉ij/opeD?22ُL,]F7t@~G65h ]ah5rM9s}xxNHXE0M?'8}Ϗsr*Y\7݌7®Ÿ:<}x))C~[׏Gr}z^KϺ׿|iQ(d/n7B0PRS BazG2zvRF7q1dgO3 >W:0,>rXj.BlГgB׶iJ) B_+=t3˿]_m5+oTP|QBS^SƟ߼O)BP(9M)AP|&QA) BP( BP\D`BP( BP( E ( BP( BP\D`BP( BP( E ( BP( BP\D`BP\8 '=]7+}}=Xݾ>i~.?(c轝O02sxQxAl+,9;R7 Ein MIm% 僊ca+ ,_7< @:C.3O7n8 "w,^9:7D1klmR Ȓ1Hc=M67[\L>aQ2蝫3lAbæ?8&~K#ZLosjšMlYdɏJ=kX~(eqe3 O>tr``o|A$tfč!,,]?F*ߑ~Bwdq"?R?Cc6?} >vy e5b }V.j=~x|矌lMC/DOC'_O~Z˿U5}|G?G^ӦۮFd& Wj꺧7#lX0/A'?9"=_`YiΏq1pa8axY\`M` 9:h7;cb~JZh$p{&+6ISrQuʦp-uan/QᦦԆtՏ^蓧3&n0vJԘC5E679?'Y]*__Y}tl9=%n[w(a/1)[2O߰}V&sYi:OicuH;_ *\Ld@NGtOhjɣ_N׻mozӹX\r%ni(쑙#D7^\ttOJN'ݿp"_/K }`xuF kOޖE @}1NB^x^odD\x;^=w{q?i#p폄n8~=o./O\ IDAT o~(5tvX$HSՑ^jpxIZvmD%i ulNuԇ.i,0hl^(aCі\XiSv&_w|'ӏs4|pL4zk^)vZԝ9Ɉ`M8d h(oaʓ6h9I[&iuR2;_8Ck&IRYp29߮wYz$7G&hm߸$a| |:r7?[*V{$ggZo4!6`sk`@X-ܰ{u')B9g?jtY4 I??w5ORoFD -B<[O`퐚,VS\|aÝp[58C/Üv+ icE߷ 8~| B QNI>F7Kھa౟gW/_YNrU k${Xo+kWŽ֝Ƈ"_2¦SFiY2N,ڎp]Wy𻿴O8#Ko+c̎ȅ#?0\9 ?}Xw2Mx] Jo}YRCr;PY q!1%%b|Id w@UQ\zual6pmb w}qr[ns+Zy 4;^8[E-'& i}!w \zܾwrI!rx/ RklƯζS"h*N_-_2pP~~,w5D2e;!)N8GO;_csQ޶Cå0.L vO 7\>zwol w/[øl0տG&7?c"\SXv'<,5?p>AͯP3~2L+?E:!q߲n8G7B}4sFv}]eߖ}"Oqx U(:I"a.)e+[ :taS~Vew~d"ӂ\nqAM;l`. ^3+ć|K]ܱ0t!T~\\'2pT#+?:I}(&s#q}N*'m،Ř8Ƥ~0w`TqLǦ",to$G'y$!VQ0m,Xol>R5_߄;]UpXk+kD|~ `nH'Ê.o$q}pjJ|etm^EJ(zΏp>\99;wOnX;zZND?/gHPضxoޥm7 ^]epoyK89, X?}H̦f͡pg+iP(l>`JЭmG~`" e6gYω~Cw"m.jKmVOLpi|)#\pI}td|~G2~k 'C[U+V4 u{]ψpmOQ916[d KL97mVJ~*l? >yC?o+i<})I@!wTךb|f?;P̙(V#zH;߉~lnPxW!no~}vWe{!ɉP]<J΋DkZokf Ό/={@]p)kHNPHV/[U'(J|$%Cq–}Įo}Ih3'Nzx4챟Ͽݺ`]TW(Ot7?dwf6D}Z$Z bo݅2GuRz#\;B95CGdWoQAEg58b~jwNl&5GęslhPw֦pI)Th:d_b}>!KGSަv, e䣺5_Ww2Nс~dח]8 y7ff36huG.78:BowEGv=m4ɻ eJWNterƋ< ;leiakKoK/ۭC2cXa)-kYvg υ&`O}]ς?A Z馦;*K_X]|^޾:5#ZW}RB]ZCb{,цw68?XQ`%? ``ttQB=u3gM10"jN/;PSV)Vc[oRhhm~s:>ه '%b O?T~ekBs&>>#FX4UBa'2nΏ]eg gTT Bq@r]'fMb̼΂~ xs;d?Gp_5>wJuvsR+ř+-g +l9åv*bqr} ?'$Ͼ y>%S2=hPaP!ޒ8I#utq=b`4M7`A6+ 6Z?ŠHLE]M}MLFJݱbwIR/d5Ⱥ`~*OE77VQaA&tn<۠do:zduP^h7@EMҩ)'h{m>xv/%td|~H'XXZ<{5e f39ov~8q`Oy}1NwqLlY&1{u8g`G|bl8N?`l Nwڿd1[w6:sȝ}|n|8] W gWݍdwʷ,S]:ϮNGB:c3, jW̏yÄ3iPt^8ݣ/khKW:ׇֽĸ/Lu9et޲_ܳNo496ؙ{Pyf9{ rBɏJE˄G^uI2I{Es~F_l݉'Og7\>(?j|U _g֌lsW^Om]d/3-8{bӦcI"mrE'Nc/T_߉˖ddYEbҾ'i6~; D  Byf`_@uPW*#\+:0!;ǯLӧgPTW-{4P( BP( B)ncP BP( BP(*XP( BP( Bq5 BP( BP(*XP( BP( Bq5 BP( BP(*XP(w.^!/#(E) BP(\`T]rha jX>8aQ?.0ȹ~>*O324 Mf/ q˜蕣c[pzHJXpI&%,4F\mcdszLMAZ~^O//ӏ|޹:$fhh:lc45HԱ6[zĶO_Y~Ds]_6d3J'  dN@7`Oܘ`eo'DzwH'# f%+=C]c-o` CIe1ng̴aLΚFτ^M?%Ea2}lLux~(( w(g^Br|O~/O[m±30u0mԞ@z\tӇm۔՜cM).OKNg9ˁXw`#MXvM}\|7|Y~~d ɥç鼴 )sG- g?Ldݬ_mێ'ӯ,L~\t(.*mG6_ GqE\;+V_x` qQrUgߩ=2!!iCY8r<.Ns$?o(vIAQ>qQB~Y@͉5c]*__YC҆hGKcY:O~a5.:+[_"1&+/]NG8L2F/c>ak9͇78ϔ ESdi<`Z'PYee29H;я,=#P( ŧA;6cNci^iR#k *I~D~+3Ib<(vd3Ϭ}SOvI2HOaqx[매esj]T?HoLBP(~FㅳU"}BG: hz9W!sfŽKl'(i':p='OhOtMLFlOS[cFmeaNuJ w,p.Q:6A+M56qh_{a/xd,42&[c9֏kz[}A _Cr?\p29߮w'H9RTy2RGw0;o^i>b6{+Nj-%!&~'W=BBt"SsfP\QDU}ӳ[~#8RTP Op! 䓕;)cGC{QL1;mͤS: IJZr:#DLAcy}ˤ )㒣$$n[HKKymYh[~gH?Ѥ&&mͷe&.:^ ]M<.B}S=)΃o@C1vҒ7 hJ?>,K~C G/jSN.toW;Տ,;P B4(RG m+lF~Ʌ;| 78Mա[c} s%t᭵9wKt,\᧶8c4}LJm<+Rws- ]``xp)_r1ֿ_19. w?~dG'i@Rua0:o0s6jךyݮpsPȯA'?md'A[ױms<z> giS~vĥjEtơLj1hpO|dn7:a6'8Lp;J?57/ rxɌ{c[ea<4ٜfSw\?' ߉ -YS?1{fpٿ'l?//KOfʗIz$㷻p򻃓sq2R1o"bXۑXغM˃pvd؛*}쐸ymdhmgV\R{i:np m!16o/~fhppc<4x;5;}9KoxvFr\2-%.:hvy=h{N$!&1쮠f44qayas;Lp;J?54ll{/pq-b~m^sFSЙ$&9DK'D\r%ў)#\pԜؐ_ ԥ#թ?o<#gd/3'Յ"#B):Џ2a6 ތS}f~i A8(hҮ`CC͑&yA~_҉NҸWx4X򘇵?Xa,b?-lzmV2X~V?2E:~uq(?Δ& 93&!&!RJ΂ rc<1e,x53Gam󮙪*yxC4ڴLŨAc>83+#W6璝19XDYyӶB[**8XXtMgYS)(J?~87;SOq|gY=k%9.3允7{YEm׳c`J 4TFͧSNi=b9_sN8k9?1>GzryF_fa:Kbl(n~-eY'5U$$25g:N-z;a}35{~5F>I\2lϯ[ Lg"\KY>G~Y[_`i->Xp7p xf_$N葉syln͈UwH+3if19kjЫ_LZ~87R2&MDBP(j&}N;ӆ2b[<ʰj~űWĦM wYu yOɞVgzt170૷)eqU~Fb},?hrbm*{S6;VJ~T/X&̸Ty9 ''}O]M퓧3.L?N*/?dŎ'r6l}.=`iӱ$61n*O|/"HW$ ¦oG4~[??21c.kc/^Q d$UcፌjBͶaWp1>~jkxgכ,wϬ 5 ռMf7K]co 6P\~8**:->]u}e5w8O 3clz%c ~c`Y9C7b݁-95h ]ah5r [w`- .EwbZ~ˮۃ7ҏ[F~lTbY7κ%}o#pR~`D?N_ֹD4>.9ʚ65PN Li^N)~[̚W_%feZ ,D1cIO`Ѹ%x\1|mVWؿp`DoC-A_ P( ŧnKPP(˧\G~~GBP( BדntB|0PRS BP( ĥTP(mRzr[h6ڶ1-S)EP( BQBS^SƟ߼O)BP( B7A=P( BP( Bq5 BP( BP(*XP( BP( Bq5 BP( BP(*XP( BP( Bq5 Bqp璻蕘2˘1rRBP(:떯a\yg7݌T+μ MIm% 僊ca+ ,_7< @:C.3O7n8 "w,^9:7D1klmR Ȓ1Hc=M67[\L>aQ2蝫3lAbæ?8&~K#ZLosjšMlYdɏJ=kX~(eqe3 O>tr``o|A$tfč!,,]?F*ߑ~Bwdq"?R `V\ҳq<5ֲX\7&Ғb٭:olxX=|۶)9ǖÛ8R\a2}lLux~(( ?]YbZ~੠̴aL˙m[rb|%$r>>ؿqtfC}8uִ CIe1ngI#m_\tOz5u3~OIEngSIMLEt^w8.]pӒ.5\_-mK/YD.d+?'Gup:x_'OƘsZ4F-1W }%&b|Zaڵ SL2?osQƘo:gOBIaz!5G `GxW]~O^ M1}$D}^e:La;?oۇ+ .M<8t+ ?lwZ2oT0;_?l9.wYz$7G&?R&LFJO}:R{b_)i^5c!!!iCY8r<.NTT<ێlÃkz48%{:fQx=.V}"vW(,!yFN jS2>{˗+7z!F{A<.˧\˄Il>[7w,w$.*[.;';_PAQ,yxsLKyw[|\rM'IʢWj;-9eY8+KwPK*|=4@F~'"MOf2-ܹeA;({&'99Nrn/@T͝&D4Au@pAI*uLFk-Mk 2ׄu^ԕ4|mici?=> iDuRcXiQ}d':.|5o \(7qFϮ:ytT{_+ctzN& *ҟ]mkvcU ctDAi5 wU8wN[ _=Ob@w8DE^O:$%a><ף$$A؋/k_ϛN'a/1;mԨ<xڌP*Ɩ-cŨYC1usz< \.[?|:a H$?#|o[(up V;!.M&?HȜܗ~I߳;u; =&+C^SbU8ox?Q$2Q!TcOW*6e:(Ǫ}gĦ*8 i'g=7:mF fWD1{lN #,6lGw `d6W]۲];Jvҏ u_ sR84G}]^eaL< ױ&% WS圓_[ _%&"љPXZ@yM9R2nY׮.ELdl g 1^n8VF;E3-[ɭKS5z%!9!ۃHrBW@ vl'6fտ@A@:`X$'m ]RY;]䋋G7tkӉa| ZEL~#.q)պ#sl"pz]Ly!lo TnW?V7+x۵@'w{[ݵб79pU/:X'] d [z*21w d] 3bՍ8HIZMw?/ΞźevӏUq &]enL\ kFΫ*LzwNt'9@?>;WNe&L_ "^a|oG?|@?@h `AЖ?tV[Tn?;JvcUmOC%`u:dicY+U;W4mCCVܱ Oz/> `XK?irڢãӵo.|VFLvO.C{oZ֟: jg >񃲛u_qa5rӽSSG^Dm} 08- 4vp }?>x 7oY±ʒ7285ʙnxtˋ`;éwߪ܎~o 9R~OCd 6|CU]e¨oX!vsX{J;9i g ;donrw5H;0M.qɼML$;,:OW}dYB@vcw~3u{V7{o>ە/Yٯ{)Xyߜ*kEq2x>YT c:P|fYYp: Æ~]i,Bް-[,PRRPRRp?Gp0].<筿?,,D0%&䓡%"Nc&@L0iꀁ7` J?fA$$̑H$'x&eJTG0HrGOQpU|]nNR,}ڿAtga3D)lL  c@7"E~OS3Icsnl}Dz}E5O 7 1_gNq6 U.{v%&r ";峣_?U&0zh @X YoUߪJVjVSmOۃ#{?nLz611> :ZU]a0iUAJb*cPQS=3nhч(IޡmM.(jr 6\Mӵq|!ޚϘ38)DGt`ٶA1(m#?ߤwFq9w58N$ke`Vo(:[߾FLd,OFDX$V,_#PPذo-1-V44 s1&tveȰ(j]5ś4%]c9W~گU~c5!r>=~;aܮ|~<$2jk{67Nq̜gb0<J|GF_~ТW/nݠjZa;LO %& ]Жp,*D?e MQzAIJۉ,۷u -sC"ZlK\ٶ IDAT# ~ѦLAhFnnm!]E+ ·\UE;i_?n[D%]F9/r^PY nΖ* M:gTsM<@at`MB4˟q qݕ&YZ0&L1Uc n*z뵥~pjDpF+ 9 'T2Y8]ȶ'{|GؚP{d|i>+YߩJD¯p6EɯQ7uf@vSWge!_lԏBz(:vջV1B!zfDƶ`q""7:BNpKV͔הW/3hٸoC҇r| dP^SFEmEF3ڽS:Dp]ͮe~;~^(.e J>1pاj&G+E:U=ZVBaNA V-';kOTU**cD!).U<.]#}5T%KVm g$U3*jS^o.jJ'1(jv?l]m~~YW'6L#sVzքwDy1]zYpѸ} 7MZjMr1"8Q۠QغF=T2Z2#/#/%=-ᩬ\(zo.XqxOd7ռJBb7q;jt`Sm%[&My0Ǡd'(py:.uP}hpТ;{”*K!m9⤣?g੃Ȏ O('Nb.PSb-O(qǾ s'@}ʊg=T:h@[ZǪ} Bc_Řzp e#S/TqQ]WŀX'd@ATm `tMXFgeS~돵T=8Zy2PȏyՐ3).e}(B|TBSnaгZT8vU?T=VUbi߁cw~DGt #u.ys;d[;T,.BE8ͷB*"M]JbGSNطa.Ce(@XQ>[lí[|!̼m.υ^~[H?vA;8 '*n iʈYt7eOVX_hh7=󊇁dL0 8`;mI%69" ,Zǝ7YDz|5`-XP['.M X~xm r?T2Rps sr׳𞦕/ '{$N3#GXc ik%3NȰHwmJ^%gt.+|KFgq3 u{Wk*)g|Ӧ& @qY_'hL&=Mը)gE*aS9Ʉ9ˆpF).+FAaHP><4Ay|i8GG3ap6apx߭o|S2UrJ*ҷP#_(u|Z 94W}n-ݲI@7/+[v8ncƏ?$1v/_ߊY_G2gb:Wh#G ͷĊն·( M9hMq}(:`VV`|zCJ?Mz}wD"9Q26 D"0vp3oʐH$sPz+REԱPeU#6'cl$B>tܴ@"H$?( R?!갓 :cGqctM: sH~f8 $Ę\yԹj,tCJH$zQ @~1Jt4fM5Fn.ſ(_͗ D"Xe /~TD"H~qxO*A",۠$D"H$D"HN dF"H$D"H$Bk$D"H$D"HN dF"H$D"H$Bk$D"H$D"HN Ӡ$ArG4ؾnzJׁ|i'ɧ9cyD"H$3>1:OW0u]ptt+L|<-LyO}c_ѱu[?1tlTE_pSl!#E ּUn%_ v /ntagF4g˟sSOW9蔩bp`ΖOthPUUVHR{FLW r_`x|€ 5{&Vl+gGg(:=p@: MbxL/3ޤ`Gk?Tҏm?m _BCg/ކۘqtaPz [/~=1k>[GGؓ [9PVپG"H$X7r 0Z.X/Ι*y?O#y[ʚ᪆8;;' V:Sc: C8DO[~>y|>K2Bml®:?2 gUB [V[?iʰkx@lw۩ji57qX18,09aKg(5$ ݏH>;뷾#ovP U #oqઆ ua~cC~;ӟv,Ɂφpe018m(w7,\ _/Z~+3 RX:Uἱl7g3tKN˂vPu|z$wE玅p]pDo54f= ph`0> :JNKev䷲@UMZz;W¾B(.j!\:/1٣Dpk"H*5v?'.G`H?:%;@կaKg }B\"H$ƜpȘqN~2B%YχAPEAUɢ ~У+iX3>߮'*^t-cBye`RUD@4:qxsbʛD" r/'`߬c~Dx~aWfZzNl=zAbï"Z[b9vVL95oqBW6́UŪ[.f6;mujF{7L_>bۊ 0L%wAIj bLE%0$HcjozXQ'MlZJ^K$DTB}o+[ "gE+* ĕESDN;ΰ#\$^ L=fs4[qW7MW4|<"B9'jV. P_f1g`B\wIVV[ᮅBΙ*UE#1N%cT4W >CS8_=lGQ`a,yMU|6Wqds`Gm?TOP`g+!ݓ}EUKw=S}p ^'ɚzfZAeyIDFɝV9to:AUWzvk"V>]VjՋ-D.)EŸ|F)lbRbzcEfECpL8b;E`_fOx.U}9W[QV/:)Sfq1B/u۪~IDGAx7R|LpQY-V۫ap7C+D"R{٪:Ķ~[ jKMjKMtTqFٸpA]IQ*vRYh[C9CpD(Z>x5:Bl8 >"6Z W|bm6VVa<5 TQ:!&~ΓP<z(7o| 7*2CN}EA ='ht?UcǗm ?C?+X<^~;=X#y -7y{nО36Zg)^7[j`q̾F܅otõSChtv !/_<9"Lin|"$'ёpŹdơoWKD {C~H{rPGuo\xtp|%-w9}ě"7K$Qj33F$}nq Cxp_Q(8*{ʾk~>˫5[avgߡV*n$q&Z$n/f|XD"H7giB>o;)#T6> @kKL* McAB/a38" ,Zǝ7YLy2j)3>i<.vpN7lﶊsrm4XǭؐN='GC7:3pjBw[>P4n!J :˭ڷ`xpFTg.daٽvk:wk\M[l7d ٔϯnlH?v' V1ˁc VMஊos~j~[wnq[#vw~GKx¼zлa* x1qi#=_lI[h.Mɾa%MCjg ė.>%4^eKr冧uK Hc9OUw= yn5i;͟vJv nx| ~q.D"HE:_7iD"H$*U H$D"H$Dr WH$?N,Of IDATD"H$ȕ5D"H$D"H$'2X#H$D"H$Dr!5D"H$D"H$'2X#H$D"H$Dr!5D"H$D"H$'iPDr #hl 7=pו- <xeX'b?_'ߑ:%3t8g<#H$/`͘{ħ+:.8`:K L|IYIk & Q<_>e /O@:n{ R{Fl/)ck*/Ptw;}UAs70 3I#s3Ϲ)'wFЫtT1 8\g':4ߪܪ}$g=G#}y0]a=Tz+ 㳣P3|Vl8|vOQ&V1<&l\oM0YJ`۶6r/ }١Rom̸_?L:1p:Kar_\;7] w F3f{_?| |mS =\nغx ܞk?EGۧ`/'Arss~?gH$D" )Xo8#aص]-]BO3UF0; {a5CU gq)w8=vmO2tu7p-y*/P}&ns|>N%eل] t[e v01'&ʭڷa8X?CFE1S?Fko cqPY`rGÖ~CPkNIg(|vo}F`A."FU 4džv?O[Y PW/>acp90|X8ݓZ!m)> }UNr_iCoÊ 7큓ww~6qDbei~mCRD" 4⮅Mi5SG1H詐rpٵ@'oNrJbV:\(7qF`~4i :^[?:q vH!7:3IIh r1Ec|_6ZCo|ԕ4oEwQ1Neg:=ZH>;I!ŽbK @ ^O?vf~;YO[}J` XF|6: V:3ᆋ -Y6YyǞO8Sn~o:Dm ~X/}u.{c[wCixȷKtRXGxc 1,XV-VD6 RphB~<]k߾!u%@fQz~رo+CpU' ܮ 獅8qx}XzvQޜ=I$DKoH9I:\8 RFV] V9^#>]!uJBO= [Q짝|' 8hs0q8.voG61m W'D"if5^Z8b{sb/I]K8#ix)~ò|C&ïsue-G)@\w1Mr9zoMf>ٳXUnG>=QegϺZOL8]kYW:L$7ܪ}+}BwIk >C/mRs0 yh@~WI35.щ0"(o ;ۙ_V*sDSb)ħ滾U}}te:IY* >V8~0LP44aUnվm(6/4>4Vj## 2jBݾB [Z{r'}߷~J[^P+o`(n{<X O)k8^y: [r8a.VrX5s!9VSU 4/AYcw\DIg+T@Q 6ĘZjv"VI[D"Vþ ze[yCervHivq Lv|f+XSS";銆ϓgBRD5D? AՅL29XL4ڪܪ}+ܵPYh9S}x#=ƩdLX}*gu'M( L~=%*6C*x 8]ȶyPR?Ef@-_g[X+tOuU /B%LI3o{'jY[ٴKlWL"#Ċ9 bGǓ_I"Efp1pL<ǙD{'`MXAq򠖹RW/ɧaxx!kj|ƤĖ߻R'g͊mpK+vN#k̞"RiXُc?W[)91燕}kwIDG퍍Icj5۫ExΗb:*H$TضPY` ؏pxAmImΙ*(.06JCQEnT* "p(`Q9EUFcRG-Ǔ2\FkR]lRSbִƪܪ};윧F*T'Ĥyj5YefP >C`7r_FUEf٩":jmg+og~Kr6`C8{-sWW#`@ ,΁׈>>-Klx1қ"ţ#ĝ+uD7˫: k'C? V3x"엿^6j^3`]#.hxT=?ͅG 'GZؒלӇMO !rtKe69cD"gDZ:ěpyp_Q(8*~o{ͿEH\VʾCOE_N-Iָ~fϗOM $EdF"H$&s>&3Xӝ2BhĤ[1V$R6Ӂ#¢xI~oyW< ci:#3bg'GF5ox܊ sx4tz|0c &tcEN㶹t00 Xonܪ}+jDuv`"@-k Qxø}-մƟ~CO MƆ|c~`n8`ş )/6g g{뀸{u E8zk`KzWw|$'_SaKPZ W=]ٰxqH,ۘ˥߿ מ/$Ĉ-2sU2v(EG Wm}/|"LApY]<8ዉ)nnOܱnI"iciΓb]cr}Zߧ**_ذꦋ!ṿ\nծxbO\%ߤ}w"͞CILg0w; 'WVJa"gB~JQƕM-o*'gYOkgBO f~o+CoOֺg&{Yޟ/V?!ӜUMaS5O爵Pv rD"HGɘ>&$D"GY)E8߾< y䱔H$D'cl9k$D"HڃJ~cPy%D"tRD"H$D"H$'reD"H$IgIH$D"i+k$D"H$D"HN dF"H$D"H$Bk$D"H$D"HN dF"H$D"H$Bk$D"H$D"HN dF"HN|/b;-?wT 85ڴ yLW̐\"rߌI|; 6}S_azħi`5 S02 3W gkĦ*(*=f )hMr+ՏOW}WX4'|q Ӏ>42i>]}B~g ALӀu|Cʭڷ?@rJs4b*n(gc]?\CE79`\1>; >CG, NЉiņgIoboc&3?Zڟ~f~/m M?()8aTUrr6?cqثINa=ngoލnE2&tL`woEGtWCΤ{4tCggAK.ƣ{lԛSslgEء7p'_V|''pǝ g?i2)0NGQigg ;{bo͋V[QCǘNxtE;ctCj )xI]q{\l9[7Y7T E>ӎr O6O>;'PxL"c7tCgSzm[ڤ`Gk?Tҏ~Bv~cl/= Qz`1VDt.g%%WVzq ܿ{ԍv$)x45Xo8#aص]-1Ι*y?O#y[.ɚ᪆8;;' V:Sc: ;aRWr+/<w2>CDcIOI/PS_MJ|G,=._}vI+#2y4>\/zZJ:^Kνpn<&˚@n=y[=-g&u:$n͂q1Y(~~K|¾=>c!.Np Ky?AfzvO5ܹ"Cg`Z&?}X;F+NGvտojf˧>½(Bwc(l$/qQ\6*+OVGF_a.c.bOn]&1I?sZ[p=_8d|iizT@ 6v<ʕ6n@ILD]X|#=f~ot~f~;쁘v"&孅m&!T77I ̾3/rrw7=J>TC! W5aP4c^vW>S5/kR0*I$xTFzWcUJ,zە{4%'D*kѶL+(k]qlHg{ED˃,Pc;)uQس4η z;-{Pq[g] /ͧaҪs~X`ՁV\?&~z=܀f8KκMmbu4vK%qtJsƭ\zo= ѡY}wl%m@@Z5<GQPr 4RXV8āY34Ea_[w4mTVwTlVXWϠC`pGv;쉬[͞W-9!RK|c;,Jsb~)z9ox:7y0MRܱ!=rN-{Pq[g]WP'MVI_\ UVw/JzSj u?ԁq= 'u(:5~͸ G]| Pt;*ߖh{c Gܴ-XY?i;uFٝ}=@={ff^܏>{W_㷝ҳ'F(=p?$'D;\½(ƻ:G^W܏,B<ɧQ Ġ_u5EBvl10Z:yn%`;Fa88F g1IڨGP}`{F^ U{+_n:tW,L9FD݌a_[:XEՠhkS~W d9)7SL-Y5}PSlM88J+= z(vM$9z)TYilr6xp9*6nN}E\S-{Pq[g]y ˆ>51|ş>[w3yȴ fy' L. G%!&-慥ϐ((ͧiYM]k5{بXesۀe'7yv@3QZ IDAT J>zW 34[rz.+Ή]vEs[e}!q־v>]mV(& s0f8ZR\ Ӡ 5s&%tm.I/w#5%UŎiljhssBZ!RS_Cr|)խo>No u??6tKCܓgQz**jiG߳O7mR=(;UQ7 x9އD~QlAJ׮/E$JjWGۡ? %{zEʬ`SI C^, @' u4-|Πz`YpN+T0ozI魅T*= (sN{E`Jtw O̙ SH䷤ Gw7~=Ƌ-5GיkCDp>aᩰ;] N .Ai[BD'3ˮDEf\[ڽ_iWٳ ^NMdxQ H^;5qQq6>MM} k~yظ?aGI-Gepi.}Kn-)>QQ[!ӈrEQos > 8Q~F#>&e[>2H̲ux,ˢKR*x˲39xw ΤSܹ" D?o mxN=7"jkzh3.MWy>l6vبX(I+NhwL\$[2X\G#}#ퟑ7Gewllj~_V]JM} g;M֓ہIiUWljNg]i`Mj*ghgۍnmڤɨÇ]6Bn2lA*&44 ǃX$$qb|kjS&LL0cA[`=ܮ]tXxX'Ob~QXcps&nڵv7>̯:4ʆk>Azl}|BIN̑H$A= iW3NiTb;*|L,ܐ:LmufG(FݠSUdW>bFHtZ.㵕/Mbl̾s/u;lsT3SZU ?KBL"sΘO;}k<(XX,@5{Vs\ə5N+sb%޺`ؤ6/ljNg]ibb&%qhg}l׷-ԧJP\ 5X%%|JBVuU(IQ ڶo?(;bږsxsC"%aqx^ORhstK۟4 37mpaf#GZ(~@Πr,˹}^QJ$k+ML+ 8b>*3Lq@gXozԖX]b02QXtE#3"BwƑoBli~6,~ $e(~[ۥەo* ,:gTbӶoDykRqrn_%~2U˯nV<襪ȊL?8f`Ƞ'v`iOVV/Og$+9}k_o<;EmvfLBLb| Qx<>OCe1o=p +V͔הO 1 `M 5 &'U`a󁍌;LL5dI~JH[w7?O-yLj+X93kkPPvPeIUQCV"/`RvjEGL[UWL87mפTlmnWz+OҫK[J[7k8ge?~Emo$3R2:$>:̗S_Ҳ(*X?'*U~:q]ω}yJՉM@̈́hs}6,,>p# 0zHri xt(__/Affb܉U^03/3/W/\7ߊs®>+"|# ^J- 4w%9oXh\VlKjDJȰm R(&GיtVq:pZ373]Gޱ]~MlT,)Tn>~2韖+5UcHNVkx1ATVPY[Σ;٥7QNi׷vӲqnE!=;CzNut;U%ה m6vv;᛼U˚@}T ]qH;qYxcRTV&F?#/.{uoSTV~OIUq9f4]g{ _Nϖ;2UT([ϓjLg<rm /6L!CUXuۍ>g5✴j,@k.̼^Y2DlߝN;~Q .0 mK؄o.Pq_88uʨ^(g6+aw8>o7>#%+} 3[ρ+_>ۼCgpF18=_3{SƲ,rኳ%bAeUUɦ5<^Y"|CgMKu]5Xр|%Ljsg>XIAi{+<ʓ6퇷άspn]1p_7XGr䡠S2ӳ6lQQSΗ;)>fݎa~x+wnWgM8qXΣ;<6/b6dcGgcW@1kHN3tiD"9IIȕg_Gr0 iD"u@aTcbX_e%#H$!2X#H$9%<#D"9DnH$D"H$D"!5D"H$D"H$#dF"H$D"H${ H$D"H$D"|D"H$D"H$2X#H$>z_k$r|!H$D ]`{?6(l/>nz)X8dVS LCeUsF|oB`]^J[=_6zMU>_4`E%* LLvm*baU:U,6Z?5Gln J>E_[HV k_ɷ]zl'WY^e}t~;Ípۡ;]=~T ξ߅ ,#qR~.wbp#%)~~51||z]/~O`xw OcKa(rxXdd>(.\ t1LnEBYe:>dH${id/<:De:ۣ}]mc&~56d[@l=|uMeknI )?lqt(ahl}͠hiN~T"`;4Rcҷ+4<հ/zy`Q~; L4`=&Eeզ~W}m5QH{ľfкk_ɷtFߤ$1) oT÷K sN?'7~µoAn|kJ(5 P18Ə#?vƿr ?~sE?oSooE9diz_?v? 5=k`=HcуoF2(`^^0-x6jǎ:>{seJ8pL:D"5 f7|dqt[ ELzO$Bj*6 )(?lө[ʞ Mׅz &?*Id_hGogy樤 bh(nbヲChO m_yA*u%=k~g2kƞ%o>~mo0k_UmgN q],+-OX|`Z@&T9N?NNTo-Bω*3=%pڍ'GBľ)%=RaD̽ jwϿ#6LSl)JHJPQ-[ f}||bd-NAN0\ؔ6vU_ܟBM]eo1K?߷10L^a.xYguJ4RQƓ;k? ?GODIڥwIi#ㅥⷠAWP^ } Xյ0< . K'mu˥?<'Gҿnm~u0'.g6u7{4g$D"gmIQzٝi#T0n#$mTU]r'V+\0.f>uO}:>f\r±@ Q zOK!}orqp$V[$tss>⻊QCr$վ־vw]åjc9 #y9NیUT +4vc 6Irٷd@/(8"p0:7}wTE ˛pv~p/\z7tN/h6\O0f(/r$%à`_J5 w=snspޭ{e;:v̛/49Q9?? p<"8%ϙ 3 ܁i;4黩cQ"U{X|U'?~ax/`pHsnptH;AA.OÉ>nY0Xqv;,Sl*r c|#_"so_/_Mu@įf"7~4Gl8jQɤS+&~}hPU(dD')X@Rʗya;Jc8^W yV*PvȢu]s`A]88Q୵@+u3.p78J@ϩ}_"ӰiPkW;N.¢t  ]'I4+̀#=Ƌ-KZt*=O7T#fSw\6r^[G4M _:2:w _miŐ2{ a $.V۟N]=,[+fr@8«Hi()68oE%>YWu?)ϳqRP8߾CP^  y*bHR|AX|%Rk_?E{V Tۿ{W8R.ʒP>dS5N#_ЯXSp"9_ | z .!J$D zWS̡k83BycowʼniTb;*|LL[jnHr&pK>6 :+ F':Ia{L,qfp% 'St&WtQ9t,GL─P[zB =ILAW#^wj7!j-=cg-8kQu~NNƏ+t襒lSȜza/`WqzfMok_O @lߍۢʚKK!&Č̩8c1҈U~%*ڠB87RU+qv zz5zD"H$Yp%z8ҤT WigH[9T8 c jŬ+NhXh& k!sd(ugb!iin?UYuV? 2PY`9[hwj߈i2+l#m'8f`Š'vYvm믴awƑo:uTNR8.##:Kk't2 yCB5?Z_~߫%D"iNyYW,dSɜQU**- #wԖZԖuVqŊ@Ejx @LGqeӏQ֙ \C:9|ή-Д =k:{y¢ EQ,h/n0~R]dQSl9G 8@vGs4 RQuv4]k}ۚ߮}?qbEA 'kdo'߮v)Q 7FCjPnٷ`>l^*DuχV>/&`稀,_\+6:CD ]gMP_8'xͿrv ۔⬍k8'x2pI\Lω|'{_|X #ٺPk~WkGJ'_P_f% ^xxcO ;TP^%8l wøap3>?‚Eڿ.[:uh:רOo[Vj$D~ZY3nņF1*WvdsbA(-VT19Ae5: 5\| Xgo](8u?}7:CQ5!{[> 4{-r5Gw”\,XA tiX&aeY~+uf< h*_%cu,C8[>9o8۵]AY2١[M6<uʨ^(gVµ_䇫9,^lv'#v߮pxQEiV|^u^/um* b;*xaZ܈k^xJR\~(Ŋ^@bVlmkgT߽8 1b "N8gpb~kQo*oqRM{W8s/O:<^qy~v\:o>yڥx[{O3Vҝ(/ ."s/y(I bM}3]bj77 OD:mI$˲ۨ>8h.ݩm{C!H$4F~G~G~ae]XϒI Xw_ΣXKZ|?֐r|jtȏȏ|wXm8O"H$(g޽F}_^ FCU|SZoH$D"Wӳnz)X8dVS LCeUsF|oB`]^J[=_6zMU>_4`E%* LLvm*baU:U,6Z?5Gln J>E_[HV k_ɷ]zl'WY^e}t~;Ípۡ;]=~T ξ߅ ,#qR~.wbp#ES5& JfZ.Mu]kf?q46˲(<=߰ &\Mjr7Lr!mꀲnq+ek[1} 9#Geڗ3sbgEͯN~1GG? 'cMUKaiᄅ9+l,/^jesN'c `o~_\wb(W43Kν1-퇷< > K׺0L#"jF-u߮}o'߮vI:ticmfծ/,QD7~µojr*(~@UUt= (#qR~.wbp[u/1y sfBIKUDZJ3b-=/6}J4|Mvt 4 t2j>iq7rM\10:klxƙ[@l=|un$nI )?lqt(ahl}͠hiN~T"`;Ff:\\ᩆxѣ]{oe:K07.* ,6ku6h@bpC?'4.]N]æ+0& &xIQ}]jطv9}Z|t'^UFƠY'qZ~$._GcIOI/PS_MJ|G,?}>K~~.n͎#K6;rE1{\&ƇOOKIkxٹnݍԧtMg(('>:&\EQY!Oj?f ?[>a_LDUA8qQ]ʝ+m\wäw*}ZLu,Iܺ.cT1ٳQ~;M:2YEr97R\qm#馏p/%yT?']36nv׮vo~ؓw׽IbL\@:j?v? ׾<O{ 3=; Px3?Ə#?vƿ}ozTց!CЮanB@&~ot~f~;쁘v"&%2 vLLtIjN`4)gaآEL5aP4bۂɏJR- ˇ=J>TC! W6Re;: Ģx͟/kƞ% %`?RbS}6hSp鱝(Yb`P}b=ƩIp?qSY`uQ9QHO[h9ط=cB'Ki-*u}$%{?pu@isw2 n[0sy\rhc+wpӬۙ>l.Mꖜͳn_ )3Ϲn /yvr & zo= ѡY}wl%m@@9Z|4()xyINfٶؓ gh`㩬Yܽkxe >y(hzEA1 ӠSKaYnW짩٬ܱA=RQ[9|geOdMj0 |/`?RbS}Kׁ[iU 'iÍQ}G܀S5 -w2~Ii -ǿп )_|:s|i#X؜LUWNŜq?$FԩIn_p?K%~?ކz:_ʷ%:^Q:7m ֯!G~f1OnjmNv'Gu/PϞ뮻vY^(m롇ѯ!JFO<'=Wdvp/+J.MM<;@E#P?~iA11W]{cPlrG<_DW.WZą߼'QmO[_*E[S1ic?Nh97?ACgR3ӧpn&xA,؅wӿb$$ż}6ה3 ->ym}$$Te@Z6 ~@Z{wwlAT>HMNcO@T4p;7BブL~+ 'sa-0.}bgidwDg.8%u1:&t"p}x1tIJeѾE_[I`kW'?\Vא'iÍ>] ~zά'H?Noㄖξ-?d[J|<枼 NJO~܋C(m`5~=tӖ!EA1 gX@ ~PZ}AԌ-t*ʾRI"v*(pTP:n6eJ@YR|o;(֑xnmb|I{ݐvy~0+ƈ~͵!σ}~萌6gc4b܁%z%iAXY VgUE&~4CGl8jQWj1W tP1UBFt$e|˂?ɹBc3>G7$B*gDSeqhC,F^Aa>ʬ`#fwOQ[k9WgP]dnxp+y[?|Πz`rqPG|'^}SawƁq]]5*'I4+L=Ƌ-KGיkCt*=O7T~$[Yg3.kcޯ[9qXʜ5{VsKxcéi 3iի~*.*~ҧ`o8o<92H,)׷Qhw4B$Gepi.}Kn-$)>QQ[!ӈrEQ_sydgzYc%a4>:˲蒔++Dz,dz,]?8mxN=7"jkzhs qS(*+Dq9m_6baYk%U%F6\sj)C3iT+w`㷹j_[;N.w&')-";7MܛLvAn8?oÍ;:q&5Vg(IIbR)#e_˯3ڤɨÇ]:_~U!VG[MJZJZޅpSxuԁQP8jk1X5)X|Gq1u ̭[un׮]Qg`,|^'1u(GHQYyJnpY n|_%1uh_ |~o&X4#HN`Mtj5GAܠSUdW>bFHBУzMNLb'|5Ɲ੶_? yfڷ*|m;t˄u|FYnj-tT; z>T;2j^:0t+3kZ[:)NЉtgڰY$$t'!dk ƥi)tNBEM9uަkJ(XEޱ]L<Ή]PM8t)5AfmCpΌpn>.㵕/Mbl̾r/u@7mx6Gr\2F%.:UDAbٳ+Ͼ.@p< m_A`9c>U%$$2Dcݷ&r) .MN((l9D0ьqRmw7ԙ!NjZOMwRpeo2et0rvIbls?|'w2~9 ݒxo]űQϞ'd>'XYrשΰY^o|/k[0OݡjZ˱JJ/*o+.(*,@4e`m[QC隊ұ#VQmN0w_@=< /XoeNJtq: m\nibaz[Ui߫o8+#=\!XmJI+9z8ҤT -WIigH[9T8 c jŬ+NhXh& +-C\QbΦ=`Am%C.N9X~&dY,HPBeElBk}#}ˬ}ا׋he9ɷ҆cCiG )S%:Iߺ,vAٍ;|;e/7}6;3&!&1@~g5Ye1o=p +V͔הO q3L710<^OOˢ Xx|6Ⱦl]ONV'c0YQZ]Σc(v}IyM Ѯ 1*jЃPCoeṱڟ<&j[Ԝin?UUQ 'WaJqWWޔT~mo[oU]eG>Ns8X2' ʡp;[OI~cqxkN=N755~>칠}. Vwƿ}[~Wش-.EA*/kp5q| >p# 0j*(JlQjNzn?(ӳdaػffk}Οsm_o-͔u?ƜBZ0P;?o槯1m |w1\FnL8 oɦފ[@Mo,}GʓsDEu9o,}'sKJϢ}ﶘr%{MYe.q;Jyy _3qlJ7 6.6Z^=k(dT1̄cfbUy;l(mugH##w]҆[>?L9 &c;v|K_]+~ﯚÌ's#ܲk M1]pVvev??'^yó}YYz^^>`Np6h{򏏟nvxUޫxuܲW;`[wonqu{dTؾs0_H==s v&ΊDճ_"K}ޯG:|~w{W%4SZ Y88Ek |{n?ޮoż2wvQm EK6~Kgwav8~6?>u< ]n'`ƮYc+"Gŋ\H"s^lt5xT '_D!&ںt/&TK #jG/[$B_)If5\lJ y+믩#9}ܭ@!'2o tH QFDDDDDDD$(Y#"""""""BI!Jֈ JDreAn~>-ۏϷowBn7,XWu|_WUDD7$k>HNom?s_$Zu&^}v |Eng %H4:`8@džGYY ϳ:Ď8lf gXea7V)4sIv4v;̸'HݝbG)Ԏ9q!ؽfߣԖ7H!3-:&|0>1&f! Rmx_{+}W ~W +?^'%~q/^yWī=o"pxʀ=ᩗᵏ=|[_sH? vrF![g`<79foE"P^ -hj;~?sztNWP_>:mt0Ov&\y.L:҂pU^_EDDV>a-hO~a'6e^:Mƛ1AW7Qx a60ŋm>"UgoE}zGf5ϷzةcMv:+YhzVͳ}_3aFkq7= M\b|vll Ic+P!mo_w` A@Dj?^y?{2׾^U2_??FK~0%Cn7`kL]2l+&YOz'Zmx3JѫQrGtDCP&LmmpWÎ6}'6Ơ,D)Yb8xtZa~/%ԿZZJ}x6]6}O {Ɉ#ë}O{ ȃ՟r-~ԝE)8O_^=־[o_, ~~o8:1~#8oc?bQ7·N4wc`13d^T8؝Q9Ju;ŧK' -Mw57o2ݙ(|;Ԅ<8,ؾ~?^KG7Kݺnmǫ}z4l)‰G77[p3n#^p\z[idt҂Lx6wԫ-WEPY cÒ5P}zw|ӎiGm[ށ徆Zn={</0l]W=GX;}Ś磄cܜ^n:tY70mR]mCvO`&ҘvW!'Y8`ʎ]  Oˁ#Lvr̂,vW/#=Q̆./Y%Z%Dۧ787P&o|Oj|}oDڿK`r~xW>0c"|};%_N? GkaH?݁нO0r~ ppKݵ.9#7p˃nssJvԛv(D sO5~<}:Rl8g:v;~9\}ׄ4 *y~wA77]ᲳLnIWCxo8XVuxﯮr(_>7o Ok~ 3ΊUޫ~?:e [c_Ɉb7)w7SY >^ֻ'; ~\7q !\{;+ c;f8\+&?Ic!'>{N&DD$Œ5#~72Xi&1^ztW;`rCZ7]rA'ZAep90'"sS~' i#;g~`cI8ٛ̉NЩyrZ;'ߟƸ(z%ʁR'/#^╏Wht]os(Yj}I0S{gK>^'Md5g;c{oA/ˋ*`?Mn+ǟw?TƗfpߧNH|k.p~wp{W;iGub]ֆ#w9 nG8n,;~͍as;gH [o x5ػmd\{5}rap_xwVA.wd G%//8Vo^~z\ >W{uܓmFxe7u%ncw[ I7 %?__~9 6UTԡۆ߇?ߘW ID-5k>k2x{Dko۠s7~N=tצm2D±aCF~b48l_h&wQM6Զ#we׬ 3,QvNѺuQ׽eu_mxmK = ^ ڗ~^WW"Z;&Y N?k_+ rǘ1kċ?Ț/MOx՟`YhS8~rMO5n/k HwhI{vgmvK]^0{ǥ`н k {q;&#=6.mյo6}xWe)uvEOy4W/qgo|OrpӚn7oX k| >Y7_߽17^-xu71V-/ !)h\KNn_ mO?__~yƄ́;@; tcPQXGv6ekMWsi X{߇H-lf4wDwVQ0 Z>ap;͏XY2k{K/~oʫ6opTZ`O>]ɖ@m_B׆#oGpb;cޣswqw533qV]ӵ0e^=8w'oa;Ldٵzti{T &Im\Q^:cyY;7V%u3~ޚ5Ow}͂h+zpOkOkAvVlbsN mZy{Kn?:.:2?uc»p oj=;k(0w=mLv[eh?7M&vC5뗟kZWK[nW/iQg/A,j1e[~%Oh?޽E6/_jY/_@u/P!Ӭ8 A0Ţ1^?^RQ A/uE 0d^ rG͠ϱemjdx[%^˯֎ w6wyQ`Wyڿm=?O:cG+yk̚^ k3oJ/; ޘz>u fg&^|]qzo9)G3?A3ox/3Jw='](-.s4U77|۝Q?X//@ wiq|l}y~2m w}% ?߄ o?~ǹ {Ia+=׹w$*njj;sL#a &$pGdW~ڧoR̉YzCECm*ux?/Ώ֟`Q`*;{o<~kJn~n/Q,P~ZT]wA:upoq-|{]>s宿J͓VN< qб,X<Ӹ[.n,^59>k濹JxY zYxfxi;pe$]rKHǝ%n>tv;~?^Wɔ~ki~Z[u|<-ut{9_97Vx?C_<CawY?$/tM_)spgOuuM,nd^Py}^_<+k@$"ϺKя~8~OqN>NUmC~oի픃sq=k Rañz?^yk/+jxMeZ0r QYsy>fěEn^M^?+Yˋ^ K'>{Xuza7 Mmҝ8NcɷNh| fpSccr2[NNY6jyz)yṽ4b Q<(W!Wp( :.XuELm~~_'{Ō)-+yW[OVZ;x^?uxzuc{u1 bϛGq4Riٳ"JF~.NX'Gɬ2 IDAT?FN'q? PQM^y|&y͘DM+kmy(uCSn RQc pe6  `*᳷?#lx3ʚ-nvEXljy[?  AB1 2#¶yKaB`&4s-?gɘK,ώcma4I4xl`369dt2x}[-=m?S>^^+^=. !Q`ȀH+~OF׫}OՄ!ǐ5yJvCSs+ӍKZVwn\BQ;pޤS[S?Ǐ bq;ȴQ3Gs?Y\+S[pQ簮x-/,'3;qѳUh|_ށ9-n?v$ƶ[ֻ<D IcO!-ƪ+|mɿYm5tNw:S ʢ;cOeotmck{ 7)WL }vf*~ۯOWW>~?k>h~=H# ~jd/)}ǫd~OӦD,ؑO~SR'4}ZFnw&xǯ1 F`Y"r&kY> azV^`437dKQLn oɻ?3Lj:hcه{͝)PasQFm$kIdwC oF)z5Jh xM0;B/+lNlAY+Rqc7Vqؿ!{KFh-~ Vֿixǟ?ޤxMMwo^{2{Hju,rS{xW1`DBHޜy,2ٴs#o~5;Sՙ;Q;Jz0)#3P͆"xp4L.y}<yӃ O6fxk ?PS=[V?~ЄotG7Ɓi1,?0H-Myu9#fŖetL]#7YW#$kvdt`n_~s~Ȑ^Za!#'4 F y iSxgś+^𷦳7;v?헌Z_-&[_Ok?<EЫK{ e֕ 7^y?Kd=?ǫdwo`0SO621۾ݺ>DH#G9[7m[ ݻ]0p̞p^{^l,F{ pE#pv$Gqvr۲W,'C뢋1ٱO&L |?sp3 1o3j].]  :oAW!$ ];|1p<+ЦgO$iL)ܤS8a0 ɗ8#G@f:UUtә4b ?:zwU5fL.9n 'cÀм+^K5 /hl)R{wr~xW>JWF<:F8;v$VAKuY{yK sL"=~S^uYɝ+'o%fΙ>mI FϞsMO{&ѩ3'k<d"ZYrm[ S"z k扲8#unW^q:7-Du k&tnoz:T"wO^ÁK /3|ǧ!AzID F#s_Bm>b +Vy4d;K:-BHp(@KQ*w8}֨*wt9Q~N M+\ ݆?KZ3,|c.+vMw2:8@>&q`F_hࡈzG\ H; p4v=^%ċ_׿mߖ@m5F`&1xS{gK>^'MdUTp ϱ'h毟,ς4̙c~7y}IS۱;p/Ma؎͚mkXlJnщcN5^UV*|4K7.SVgN8k_x.7p-} P][͟~! 32_GIcO%hٸ3 q8S.Oy q6$N=s{SƝD0ފ^_2G+x+m&sʫ˙R8`:Z_S{gK>^'Md۔ٹs`~bDX'L;=wCMLp/[52#|  EW;NI 99G Dߛ31Y}JJ` c/_mѻ{pgn7nb>9VQR^:r= `t9j4uy} ).t.]ZL!CcMϰ{ohtmй‡Iˁa[||OoR n;Mf/X<a7-Lz6Lj\km|h`ϯ~2ka(ȇ I'/XZ7?a^g{$@F'/E}oo?|k{DvyMi4cƬ /~ʷZok_"k4m_?U2߃f ]ټk#]{3}Lr2sb.?4T4~;Ps@A+p^|zt<1G~50 ǡhN90L,bM 5Fń!dzW<^Zи@hVz &Gm9CUi6-!'cCq^O:ݾY|MI;nbOkh_ڤw5kiWp<=wWIny>/mhx뽺%^]]0GkKf_տ/cV':ںcCc._?[o5~~/5_?A_&3u w/& 8woسK$0<[ߞ8%'L8|$Ίcu/'Q~ثW; tcPQXGv6ekMWtm{z5P7}¦lNsg@Tqg e w{`Pa(}%c~HWk3_ wMFdli1 o~%t|m8?{'{LncцLrAnlt+'c vP0 EB1̴LΣ1?b*sfCGD(7-eT1¡fd,?[?~Qڲ<>!#˦]䳮Oθ'y}ɤ'̇g\T4|'~O9ͻ6XݮKĆ gU EB|q M h_UAF0QW0bE*zJF,㵽KfD$=W"v xa?]'3#Zn;=>n}(oW%ċ-_~v]ߒ\mSϡz{&,z߫?ë}ԟ`;솤ʰJJ>ϰ àkn9& 9̴,=t"EkboܹP5.z} ;p EpSfdg5vO7.apa [t3e%->&;GE1/ھ{^ϱ{^`6kd߁*#'# &\Q盀`[ܵH0 hnK|`#b -۔eZ]a0kbH H㘡DZdv0;;kcV'F-^۽/Y#^oWݭO9TTz*6`g|{퍟k>~O{09;J1zxmٲmɎի:hQgfgii99N;{{/ٳs8w& {"]ѩn6hNƠA χ}"<׬)]n9kaGaM^ucS[&2@/ 04leӜ|Ba'4%oɨ TqX˚Vy{J Ҳ lÒmqXH~ׯY8Pfѣۖώ0Sb+{I&c. `!\PԎIxmoOy_}Z;&˜8T816ώ_[ڞ퍟ho8#8i) kٸ/o~FG|eDƄ8,0 6il9xźTWyĩ<9OTTW8|2L,*k*Yqn)Ww;ٔU&ak:|V@Vz6S a6{ţKݛ^Us1d#v[tcu`>l"n?MEZ0}L,Ӣj?z ݼ<4id3δ+QVpkmg\R^^B~ׯY86%Jeo0pM>aYm?m70 38 Pa]q 7W>6.6\^=Rwעx*_Xx?/Ώ֟'koǩ:̽~5\F xSLM7BebeDo]Bw~<0y{ܻ -YL̜Rĩ)ZKkv0ż2lE.mg7C {q*6m"| ݿ)*r/ #&3w9FFu؟|f'/"Rwgb}<'lN?cM8m#pUٴߊS}hh_:4߈ѡNE9{3_ickg%)ݰV٤@ t0* *%Yd Yd ){mTB %*!IB @/K)##'rr0d4h%YրA%2rJ@*I%dYBd$I+L{'NAC={Q/m=ݣ6]qͲ̋hԸW^{lagƏ:u[PFc6nY~==jsrG׵sn*W翳>>sD hrSNH@21!19T$(Ǔ$%5$j$ANP(e%IPH*YjeYțז촟_|M o?ժu>}3woZg! 䋿OB2}nN>I߲t\֫ETg*{ awZF2$Q%AN"6.ssKL,yKBly+77W } ϳƇfZ:#x>yRи8 Ϟ$K(%d4h4II( Mzx )ICXz-;QfvMx.V; +Y={ t+_ςyqͯjYfhӶU=ӬyGQf]?]?U.xy7KU=cϑ\Z,\Fz-nH{=e>b䨉ԬՌ53`])3q _ʁѮ}wЦmtgw9hʪ#$$llQXY"6>KK+d7תܹDG(R5DѣL!EH|+J*Ub@ }Rݹ{/_c``Axp1 'riϟ1saa=Ǫ)`Of2Ѻw=6mA~ݱfߙ5k!Ŋh3ְeNzꊳS9:{tK/Ŋd5Xn )[Yrđ'1c> eéB9ڷoEtt ߎisXj1tHS$oҠ~mʕ+gϙ={ :e΋3٣ ܹG:uaѨa]FTT4ogAl߶SSSt.?~жCNdm,iӆ̟77oBY؏gyڗ]~Ο`DEEӡCk<+x ^ 'NcaaΉgz#p͑\~y/?n$J%VmdIߞϕkLTHNعs7^^UnxƲj ;6`aakx5z Ə@m_Яp֮YJٲu+Wꜛ9ꣷQQlٺ]֑ՇTNdzukf[v:bddȼyP()v.]ikv^=ҹs𯛛 Ʋ~Vm=]…K,]2WѤi{Zs =z\{C^+JJЧM Νe#9ٱ}O( _8SUA3ӧݹ?|hvϑbkc3TIGZʁֹ ~$!!j_yWS>X%u(X^N:˹s8;϶M`J޳/W=L/'#K+JQ\;}|y(^҃{^V;/PT( |ݻavǍQ S0n%i9v{rww%>>k)3xxT͕'h{snVM3 D"..+ArXH=rx&MivfZȝ;2,`XJ%vvCAA$&&Rn{kTDPpO/LBBB\Ŋo_,]:uKDDD;,UNDD$O=wܼyjիɓ p}J$%%i\ RV5bbby3Ipss! @bckj5g^X Z tљ"ׯC3=+cjjB7?NZYs:۶i9rGo^Nbb"kUo԰.W]gќ={,uwwK%xlZrXᯔ){ {r!I( ,Q-KP$dQY H?SzhcK@@ EJ5|}{cllZ<}F@@ &+[Z|ꚑ)Zn@TTtxx*$&&Mժ^koʕ--;бU1l@іp:uI갾eiJ͈$S>[h4imZ7gժTh(W׋g֝:u/_ϻw[^[jLFkm~2@d({!Tp28v4..NXZZg_.]frNKd)l߶[v2R/YA._ӥK{`(-F>7u>YN娏ަV̦߰!CPW Ћ5>XI?"k4:^N ..O-5؉pOZ6iu$>2|&eor֟Kɩ30Kw҂ ;/'Q sSu>63ӻt0=$4 Wb_,u:+ tcnv']وHi73|a:2ZvTCRA`hh#)y͛!>}mνbz{@hhsʮ'-Ç _ )$v:su55477Z9cN6aa:)(UgMŋc䨉lXr.2W,%si_-,177cH䙙f؆^=-Mk6֙_'iwN׫ې?Q#+ ++KބehjJj>S¿(d)OMcScHn:">/(&)p;nmm+DFAJJλʩσ+W^' /( $I˫2p9j 3ARsPMrey+GǢ sg^0xp_Vu[[xw[ʕ-С zTCC5ǎ9~I4 ..N}9U(JhrOgϞL?c}O:if*kch׶ ֡HK:O>% GV%ϛ:zJo 6I3,tEwEdbO3Qt>| SSB{sI>|LaV/*XZZPdN111ǧ#..JB9…KZR's ǜmٲP(9z",'y4q4ܾ}7Gfoɕ,K.l#gtYw}J&..>]zeʔ"&mU×8SPN}MrКf:}*UK:ύ?ыJׇDT.^1~)=lRye#GNPSwɨMO 5QmdE$ڒ"DI5  52*޼;Gbbf($ȉڍ%$DEEǟ;fW>\Ert,Bxx7nkk+Av׫/^ɓg/dȟRɉg([4QQl8:ͅ… M?7o H鎟j5+V,[O8;u?[g#,4'dYǘҲen<7oUz2u۷؈E P(Xv3:2eJf'BCPTQ9a|jbc(/\o8a CÙe>r͚&o-bzlmiذG@mػǧ#Fٳ2vOr?/GsFs2,<$dBR PJJ$ H3#K$e^lR1[[͛ǘ&gG)oBr4ϳ[|(T ϞJ/+WvݻXڵӮm mu0a(qssaBVȴiQN6+Î}YZbzBC011٩<˖n:`aaζ?ffhѢvUbnAr{u#o<ع;FVShaJ,`F8j`ڶK^0vp6lFiӺytԱ̝f;`llL͚̝3&sv.O>,ޏX1`@O|u)ä*U3dp?mv @RbFO"&&2eJ1s$ s͉F1gbcQ6m\Q?wTV 1cӺU4+=@ǽalG>˗m~bQΎ}}hIPʘ1Cl۾ %ujos1--7}ɓdž_~9;<|l޼g^PH+Vysә+Mg\3P`||:r\nҤ,^5k73V.eP(Xp&ldΟy f+WF`dd̛SVh԰.3Od,m('>RT0gT~.]"I Vug 5Q[@,^4KV0tXllh߮愆~t[s[>43s3gNSL9ÆERx/ѬP !'&aeiEdD JI kƱ{5);Iާ@BD P&}ϻݨ@ 7JHH@V|r޾}ǵk72SKG0*'o IIԄ$ $0(( m9JL&MR@/wb~&?$<<%E>[v&j"|{˖-;yKM~8LIk$dYFIҙT*S旂HL.BIɋ$ 9gAn'%_ь5YiݺYMbkk~~k G.]E$?W/d_6g4=v) 3R5ﳠR|IzOZQ)YT$!'@fF?ө]lI Ne$YBR$gB% 4cȲ$(rr4)eeFFP&"h@ ~ȇUF-FrBRj+K)?;6U(' %uQ@ F?$jw SyJٗTIL&=IolA@ f*$ҴeQHr|KW@ "`4uX^|m&\HSe @ P|ljLKEJO #|,גϞl/再AAQN۽{^KNLL-7M]\z#yÆm,#}֧}8|ܼEG9663e^|MEGպtCL:_F*TSSM1~nN>I߲t\֫+}M=aaiCA >3j#/s1do_KG_ߖZ?c 8qg`n ͅ=?JsSOF83͂[0~w4oj CO~?xXL&9x~~kiԸժ7{_.]S... Q~+5dфI`4lԆ5ӣgcb2wb6jW:vk߲u'^ O۷{fmc,S~+fڞӧӻUoLz-4x4qqqm6mQճ>͚w- ﯻg~:tŕktWZ/ 22)SgSv3m Ӊ9=s>=z݀&M۳nVEoknff>elE,X_Qwz࠶vѪuХK_Nq]۶/_iϋbiԨلZ2rD?i=zw<~1cRFcjnisɑ fۿ8H}֐Zҿpuq/_1bUoL-5{ΟD*uꏜw$ f77o뛻w3~tjjJ-1rB>} 4gY߃h٪3oބ2m\=jӲU Iƍ[=D.\NϜ@֐f;yK?;#';Y:*3=WW3w5k5F&t҇}S&~3ud~F+#8w"Gݣ6:9>gWOndQ$޼ e4h/lՅEEfK( mlɤI3(]_}-7Rʗ+÷T*YvFOl3 CR ̄j?ٹ<ǍDidժ:'%i:l =a@LMTT4:ý`\]ߐ89'NO'{@xxs :5Ǫ)`Of| Fnaa3r`)} K,~3ΝѧׂkkkzH֥/_ӫ` 2aԆj~ g횥-[*K]JETPRE.Xs>/_KpO89H/N[;~&Mͧ#eʔd)= :<<},-XJӦ ?o:oބhMe󲴟ӤiZlƒX|5^aҹ9kL ҏ:k *Os ŵk7Xl5VVZ]>CE ڏ[7x πOsӘz>ϠQݓŋzXXkېyY GuӻQQѬ[}3kdƍkkKFJ0+zr+ô/QL2cc#޻OttFT<=+YYy̷8|8AA:!M:|Хk?n řW^sCٕΝ»߰5v0wT6tW[Sg TT*U܈ciӌ%aeeŋ8ٳh۶7 22 s.^'qTPV'L%""[g Jɛoի)_ ׃kPL)mc y-FFbb"}hϭ\ٍ/^ut^6T*y^~+]:KalٺSQ;O?n+*Dz(_ ̲-gMsyrtrJ3xP\5퐐˗|)(`4r۾},?]Ko'sJp,gt?}ЬiC]̹s~$!!j_.yWS>X%dKipwe'V8~%J̔'jKо}K[Ri[x6U=tR161ΰmU+3}%4,%KVA|˫2ڠRdEܥxb9=PTi)U+;|Ynݺꬽ_ߑ\x9˺{Oƍ˗˯=^Rd}z =z\ܿ׮gxmCCVVdO4/(W4}-SlI.2dhvz=x񒘘71~.:uXJiּ#? >>P(K_Lɭ u^BѬiCTq>s0?kj:]uފSRaڷ@YV)cZ]tݡ}J64ٰ`bb5TjתFLL 7o Inn.Hll]|Z +:Vҵ#..ԪU-vHj[jTDPp1O})YE*V5~j=-砠`ө\:j D5k4x4g^r-3 '""*mZ亭^@tۅpv.vqq 8g?-=t>;8M@\]hj[w:ޖ]OZJq<<*ɓgG'',,Jz6͎|xIII:D@ko궧geLMMӟ} Og參o`bbiA_;H3er:U$"""R^nbll D? Y=S jt-pXHe;?JO+}P8U(Ǹ߱nV?o}7oSsV4iRM3kBܹEW"3W]Ktt Fge*VVi]S~QJЦ/ +KtúHrcbL^JZ'p28v4..NXZZg_.]foX[g}}Z[[Tbnnm},afn戔 tېą}h4˗7OMYaCH85jxe`nɩSx {#˓~ȋ/ٸq;WAbbQQTꞽ>Bng8'/*:֟~諤Hc +>>XE '--Z+A퍱kyPlw>ͱK[wi~/?_^o[-;`)kҥNSMhinfz v$= {ώŏzy$^Yiv$I!??~akli  \yie|m,Y*>V Cټe:Jc""ҸuC:5<[ARѴYeECf)H}',- M8&4m0u+qqܼh69U+sBCè۹yJ@#|sDEEcaiqP ɟC{,eYwv@ιsj*e`BR%=k2/^#GMd+W&]ip|#D%077cǎq_ָx5|RPA?;-7rr 6 wy~ۗ"аZΗ;;B88caaSy [[N:ǥ@*VDTȾsKv%+ԇqPvÇ _ )$v:ccc *2*~y/,b KK n a7rLȰ z>r˩A^is3Ϗ+}AVѩc[:|ݚÇ3o^zŢgoZZ>B3kԪUZq-.C٧B g™h4i4˗.?$&&渮RKpy._$mDllΪRHjԄ%S;=zS=eڀwy^,--(Yx122xb9r"ahѓ:Ǐ=F~ .%(P 9!&&Xƍ[:Uj2NʡRx1Eu-vϟIGc``w3,s)ڵmAÆu(R+lmmt"7m sg^0xp_Vu[[xSJ΄.vfKã:,9rAWFa0ի ˳2JI̅\3ܪ}gZ"664#]}mPLL鈋3n|TK*NL[\NRщ;Sx1ͣT2eJV3gBP٣KrpVH:qt,}׺~;zDN*P(Sm۶֭;j+p)_!((~뤏aF+[C˗EfK#yOYǏp RfK5YfFF,;Ige&NqE~ ypwe}+V)sOKؿw*Wv23է~;QnM|9#cbbL>_Zb ܿeWYgO3IZTo qqq)gN_# WvWWgJ%wnİ~V)P}]E`:cmm=={vaḸ8!2=Ԕ-dپ5k7ajjJǑe ek\Bhh*?8# 33.>J%'NlDFEiX/N۱?nEh9pt,ʯDZd-#GOwwW?~eL>}m03nBYu+`q?]'Ef ++K;lA{:)hoǕ`oؖ6Ԭ酽&NgРXZsIBBd-̮]XM&ݼӬAv׫/^ɓg:rs=<*qC?Uӧϙ5{a7ZNGiTNvzRBfr_Lnjob](S|306e۶عs7qqqo_ZC_PY̝IgRPVuzʒ+3=_~^sy͝F9[>y2uje 'b <GǢlڸB뺹!ldwshdѴIMg\3P`||:rOW؃aa̞hll[Cn|sy"yJe@*ifaΊ g,[:W,ߟsسg?3f.CU=zB6]Y|v9t6o[_o+/ L;@/W\n+cI0@ SE^r(Je?r96^t@ Q@ Z;eݼ|D5r0 # 9@  1gT @ Q@ F@  @ D0*@ `T @ Q@ @4=zGmΝ[ @~;ĔEG@ `sO_$@ HA6}&tؿwA|yyq"#(\]:IΈ8w>%5kz3r LMMe>|KӪ IDAT̢b``@Z>l &&Yq8u,*+0r  2?#T*5r0VVٳmb֬L>[BM )%֧\nɛז fsUڵ CCP6@ (L2EtCz*Wv# 2NYh6;!_޼Ȳ\ʀ=iӦ9JKV`anNe2 wŋQݓ;QtI~qhܸaat鏑G J7vM@@ ˲˗B]p/{%u4N%Ib[Pm~Ԫ AΞ@6i׶jC5mAVRIrIIIܹm[`ddmBՅ @GdF3J1vǎ"0*+RRETq#6.+ӦM3T*U֩]}Jeis Kؾ},?KK m9ܾ}%3۳je~ cɒ$%iP*gd̞5Ysyr9zׇkk/^utyͮ\uXȏ[̳g/@ 6bhpcm JZՈ͐,wuu\;op%kQldp,$#2=]~""mgDDDs˙Qf5~I|yӝ'࿉Ȍ ""2-u>1GL*uӝei%XJ ..[wr9^|EBB<"II,,,lZ4oQr#GOR#Ŋh'%i8ʎEETRUU{YjnZWU{B=c,AȎ,pʺ~>8s|wW)DDD43ŋ[88Q3TZ5!#yxgV}{`cc:oŴsZ"W^cө^ ŋC6lڴЮ] {xMs}< pQ ʊ~_~M.U sLMBBEbl߯uSkU]LTTڷ1֬ 3g& Z5t"""JFot|heΜoppg옡̜93A>|Zhll7&|9KWciiuj{oqwwe|3e_=8\VRObЁ3&Mȗ/ud옡G4cLj*gφ[oAAZۓʕ˳a^y<]'""db֯ĈؽA=r0d|3N,"""gT2g]h޼UDDD2<1Ϝ#*2̠X}QqIDDDS2jDΝ;Ore4}.狈DDDDDɨ(Q2*""""JFEDDDDQ%""""dTDDDDDɨ(Q2*""""JFEDDDDQ%""""dTDDDD(%"""""JFEDDDDɨQQ2*""""dTDDDD(%"""""JFEDDDDɨQQ2*""""dTDDDDQ%""""dTDDDDDɨ(Q2*""""JFEDDDDQ%""""dTDDDDDɨ(Q2*""""JFEDDDDɨQQ2*""""dTDDDD(%"""""JFEDDDDɨQQ2*""""dTDDDD(%"""""JFEDDDDɨ(Q2*""""JFEDDDDQ%""""dTDDDDDɨ(Q2*""""JFEDDDDQ%""""dTDDDD,]Rݻ*+2(%"""""JFEDDDDɨQQ2*""""dTDDDD(%"""""JFEDDDDɨQQ2*""""dTDDDDQ%""""dTDDDDDɨ(Q2*""""".FE>s櫪jODDDgFf" p%.6DDDDTѿr""""7LFEDDDDrin 틗'gk[6]9ŲGLWM=QUpE~k[̀QU^H,z*34u>ٿi ;[re6ٱPŲ#% 3Fh#?FVi-BsN(n^LтF~rՐȿLle˔皳Q/mHN7ܕŵ gzfZn\[;S˫4 Ӱ{`݆-i؞dEC6n: s޽0PA`)}sD^vty VIƍ4 iԛ)^ N?t,GPIHH[nӺsNU2ői\ȟ+%2)ya:[s,[,'VmUle&L{9GuWؽ?7nr|(w7W< x\^_Qre`j?8=}[ǯ5>^mEFHF5Fsie>W0 Ba>*W^Et%/TWA船NN3cf'>R1Uع[ۧ{B}sUOʓ <[zO|2ҶeZW,KO>NZ>01ɑY2Zӳe]hu>c#>21g+[>*Wޥ%mW ٻ0JhAsW mJF3耋cdOYb=aP-d9iX6wno gyue^"#)P.[Rn-RSSYf#װR5C]o3k̇{2uN9Fn6ҥa\Ik٘&dO{a5H|TT^; @wql? @~w:Ь]Z7[>6QQ||!6~#Sf-bNݴ #1jT:NfT7^km]^6ȭ;.K.m^bɒ߲QBoىukѽKC}k2krGTt4 жe#^yM笎۔z>v 7os6Ne>wԔ|=iUԫef;wXoJBF}@V5u}9mc;5;beie\3-ԧ]O1sr67ލHa?zwoO 8r+d#.@-B ɬ{ ::GMbXZYR?zv@~C,~ڰ ݻūɑ2KѿOW\]ӕ?j|>~5!qrryض6n9Ӿ9'9Pb w9ww(P~^PAlH++Kɿe2z%67.f{?ϲ, 9Lβ#tm95=}}f)o0d9zvk3-cȈXYYѴKt jGXl-ŋ2\/`kkK׈3~X.[PtI._ƜE+t*k_"22wzwsصTmP!0VaOۍ8|Om0b:Nj3{a=A57y=AȮ<.Cuvl>2KWҩ] || z{ݟU1ԙPo`iiit^糑hӢ!];s^':kaSPs\]v&LM)P 3󱆎$66E+!̙2{{;~ҟ&I7NH]ܜ 8r v;KK r9~2K@p>1_/>~ .,]âѵ%|2t<~J`uaanAȅth?_o8%kt6cǮ4?%551_ͤL钴l 1qӍ_NgN|gMT,r.]etW gS;GhhjըG{q/%롷6ׯzx㌚08Z7k`rKV3`pOI~̔妍=-2q6GZչq3p >2Fԡ8rs|6 ᇟ(P f/Y6gv~ܜ>=:Š1v %I$rCo0yԫ!s'<0n,Əx2fl q+c'Nŕ?`Ȉi6=p VbYߜT>:\]prrduh f>1I.e¦YӚEZ9Wq"6Mru\]V 5+lYDd3A~3>%uhEM\,wS&.]zZ\ڬCMdT4+mS֡A2wwW>1g /aXV\>zcg7|ְ~>2W(V~ۉ 5kTQfԭvZ\nrFqwsss  {!>nHF.ZI>FͷoCfxy [[,ˡRLĤ$ع ŋ.2$GӢF٠^mz>uw+Ӯe#ڵllc'ϰrNN|9jm7GOp0{[3x{ ~D.\)c133W{gZ->/W;rs"D8v2?bKU+#11yWѬa= JvqMmn!66ukAfŊly50\sҏeܶG-[ʖݾ ww#p%%^m]ʵj sgdfij1̒^ 4oO` `aag~}xΜ@g/yRtI=\,II>\!JʰgaH*߿l@rU'ϒLg+@)NѺ< xD_pAvlKh%=u0ޞܻwȌ_|S?x\5W"**&]?74xXS顓:7W zs\MWYKWg_Yz)M#r\`_ O1x~rK7+U-Xf#ѧG'#6.K7nL$ۓΨ}b #7ol74xxF5!!vNGO#!".Ӄ dmK!{~iSbJ߁ݓ/<_Ʃz<|<'ʝ( Ր6eGmWfu9̱psuJ'~QF:T|eVVQQQO~툌c#۳3%ގ~ dT{3i(X OGG{ w7Wv?cT,E޼!4t%o0WWg_/lm6fKqwu!=f/\[=:i|eWy{ilc xryy<ʊ6-ҪY/VX8~ gF}w%q6˗G'*ŧK:mN/5xi9vf}B.aԩYKKKu}o1|(C?y˜pM`&DDD=\u-]G{&,5i|Ȼp3:ʫlx+5=sW7 \sh7{CRݽ#Qܺ}2Kbcm-c~RRR(_Ivǎ[QLrr/?tRGqqv2ܺBll F9dVV$$$IYˡ/ IDAT/x>߳f^^͕;On,ώG2v8'R>Ϻ"ބ,WPSq)W9fff<[zh7z-R%\M]\N x'6?ùU6y~MQRр@~ݻn,24u*߃Ғ#O|$.پ69@rDĒ^$ٍy.(@3Mgjlx+KYr@7/:>SivSkt p=M/=/I#bbbHMMЌ0J!)97 oXӵS+f_%e|/z cG5%aonb(V/ k++f[ABB"}9t[3]XXX0}oI\\2L;nScKV|6b"ċs=8M^Q|WSx =1oJnY_qMqZ(Wojrxy'v8[~ّ:ѱ 5 &))yWBO;Y3\spqH8eg,f* g= 4F~ŋckk˭;\ɛ݂ۓ{))sgVk72s!VƯ2hZt vvv/VkkKjJ eJ;^6Fac}^m~a6W9@JTPO#u*H\]΅\*,%iRnWϟȤx~qZӞw5z@W/FVi7.f'|$.^͑L9nўV]| (ɸa 3[7Ugu8Ѱt6O_g4m>|)U8n sP,_6$];bʬEpggҖm)Ő1~|''^<]ڷdރKjh\`|tudiiɸ0s2\OtL,=zׇ#k?lP빪|1h:0.XYZRR9zu`tOQz_N֖)fAA/Bo݄^R9'jlJȤ.thk7Ⱥ~ڊB~t5^n sbwqsuet؊c'N'X@.˿5^>3.qwsݾY[|~ҥ)85UNXF5GRr2mMp!_םyW-W|=K0߃Wz"״16㫩󈊎=BѨL'3Z.` ܸ 1(Z//}2k1/\ٙ]jĤm&077g`Z~;8:_/}ޤ12EEsnc=;zTiw~3ӂ&-WXxUMU`dA-i4 %Ջ42?ݽ[_-))VzӶeCW?teYCMDDD34͍^zOd3?EӚEԧgAkK]msiQy2~پظF/UQǑDWv??X,ԊLbqB.zϟ4:CTR<6NWEqw0p8VV|5zuB9s~tSOѬt(VQUdekYvgiiOQ>˧!q"ӞOgW<5/""""d.O mxIDDDDU""""MF-mNsR͉(Ϸ~aA;'&UmxEDDDDrKQQ2*""""dTDDDD(+L!#&>:~}/|u&k?bcʾ6b"'jԃ{m+q}D0_Lorδ؋>aɊen޺M}8|6um3u޽{yrly>yzB.^N;iOI>v }\"JFUswsųG/YIc^VmS󗬦C}'VA_:mWΜhXo/qfTk[ TٔIFIؽ?7nqK,Uk۲c}?HJJm/V_[N~G*fxen/YХ},uvrC ?'%%{az:;k7ڱs*lp?P?%97|BopN8f/cJUӣS]u~{ߏ6]\PfMEE 7LΏ`cm?|ؿ'Sg/899Pjkkw;9K9.tl UQ.ZIȅ+8ӲI}ڵjl̷5v~>ӻ+VVєYXRSSӰ=߇uk`nny߸{7"ݽ=ʖ6MxO71w9_:{{;\ΌyK9t$)R/U7L钆;p8v1|{F֮}9zن~bv"|zV%HSQl@lQBƏywHn g錙8,3~h:{1gΆDZ5 eMlZ5h;&Lט將̅͜\3-ףCfefmEp6|?bc(Pwzwp!_zRSSY~+7pwskZXYŬ>q-[/S"G <"%+e߁޸֢{6r>v NN. zM p]4y%ú9o?w ,[meS=!6V.M̜~ݻ (I^QO=r+d#.@-B 2[~Ίz:6-\]St 9k)8QnMMɅKW[:2ILJ2*ˬٶsQ*Cۖx Il8Iݾ1gm֯Ç{`eihznӃ-Cv]?hzΆ\ڊeħcccrxL.F| Sf.177Jr 'GwWدfq>"NNN4o67S{XǴ/ݻzՊَ= 9jX_wkX[YQBY.NvV&Ĩ S9p8j7JFF9X[[k.^F\\6kT"|bd&'.N=!3l$ڴhH׎8uʼnNZpU>< . IZ=37?ǿd0y6ԥvg gKـF˚ܼF+zʳ_.oG]Y,,̌ac'Ӷe#z֖3!̘ gGChR1n ZŁCǙ0~Ž:reOeU 8YWbFoA%|sҕ nb?}2u[㿞Eddk;!.ӡmS|{ۓW6A?p8̖3al.hl~޶7QXNeoסg z{ANMM員u''G/_G`x3npӣ3n.XcPx1 zqFJ ,SȨ9IlJpv9+/բ}&|Xer=1KI!cu^8|QGf rR1-t&LKWYf#:Ņ-?mc)K`I]?=ѐԪQ^J2Coaccr5a437maܤn3%l;\ɔYpqv^] H jG`%fetYt Gv(/wL\3{>5)Gm̌SgBB J#F%ۨ|6b">^|^/ Ѿ榿Q2/t^Wd$v xyڱXʗdY:n|K KF}>vv\,:6Zל+/Y|`Cor&Z7ܜe\Ҽ۷{x,ss 1_>4pL~9r>΂ uߓĸa `g+Fߏhc}\b=K= )Czq+ ^Fߍ'9χaan|d''tx/%[f&pi8ȉ{))٭=uk\U,۬\}ľ]>|E ZZ5k@dT4+mS֡:wwW>1g /argO9;|=3I{O;5s ~ٶ'N L> {!>NـR _vй}KڶhL2'=(/X[[akkxq9 \mǟ%"^իV0ܿ'~ˉ3"U,iҰvU4M?Ř/>*卾U<{! fOX.}WTD-^E quI {ۏȨh5y2ع 0Ev]?yW_" Ynm HEiڮFcH9nlֱU*r++m O\]XOhײ3\Qe4 c`?y=lPպkn =U1alB.^y*۬R^ 4|lKQ{;J=4kȉSgxzeu"2*WŨ3H\)Xh&̌Uѓ9NΝs_ҥ2f~.Ӥ.v5d9HԬ^sss;jr&MwݳѱFz{Q <{p~l9wTjT3DWBKCGO`ccM_AoN1=n\"**gΎ^ b~#!!r62$<%:z<|Z5VvޞFsW˓rxqrt.U >FJDEC^'ϒLg\@)Nvɳ~5}M7_l>RR9D~Ԍ?vqv6>{03#%5sLl,ŋJ=WgGCCx0(^9 |˃)&&8=r)GG\32<^wtߍX ĉĤ$ɼHJ #""b!ˏ k׍/љX.^ʤr]3R3ۙ*]:?ޘL^=fJ;:,Hu?,,,pt'~YSNq߼ƲU8v41$˳+g)ZgYΦ]:puڀq }̉kff[yP/t]q̞ώYA뙉|<̖ؓӶʵسD||1ᬘ?kV`uhʊ]0:#{;mNϥ?3$9)9m?"c5\Y'ߝ HF36JߣZnپs/y]k+NJ 2$ 2/Д؏L_W7 w£,gr։>cjrm P\]y[{|}fؘeֱ*GdTѾ>ތGv1=~A?x.?Fh@O\]׷]yGguj?2{ !eVΦ]yɑȨ (C46Mof[yо3:ܔ\52<\p-}4_8/ 3K^c#۳3%ގ~'yLKKwDDFqv9K0'rR%qxѥ}?ù+5vbA{\N%999}"!!!˸J@;eXc>ʕ7n}|%fĊcF˝>{<ߖM16n9ggsYn.srr2geܡGnsػ(.N&W7?tѬť+p'<Ri)]kk~}h};v'%%e=k!z37uZz{Ͱ9>ŋiO?`ȊsrDĒx8)~GIGz_w^}]>[:iFҜ=)r6ʋ2\1:fbgaܰTƖ) ŋbI9A'>rWgCdJq)]++K.f~G^OF/SNM ʝG=3׼o434r4*ׇ$@~7 /z{xz zacmo;\Sao b/֪-p=&ov MFL23Pztw2SPA""X[ʗ p?hU~:bccæҕkF7WX`~F\q/?m|3c/<_;,ZYEC8gc>V7Wg8rTߵ07p!_6|?.HJJ*˗1yKcaaKҾ%qq,^t4X[Y1s )͡#'bj IDATx]~Tt ī/!^2-7NA"ҵS+f_%e|/z 9~jVdanI{/ v=bDGDz|ã wX9.] +ęsشl[HAmɁŊ`ڨZ)qnBB˹<[e'ޞKIa瞃<[\ c/\&.N ೼գIlJߕ2yTe^#OׂCXi+=>,\V`iiALb~KV|6b"ċs=8M^=rx *ރe.zگgvܝ5g܉|ҤǵPhܠnޞ=~;XYYێ=عߤpedўV]| (ɸaM y@ͩZ~؏&x+a3cR}17W:5B̳b2|5z0aW3HIM3=t#)96Q/μū܇5Ѣq}VA7$urr`ꗟ3mR~5dJ(Ɨ#?1J&^yb5z6>^hߦ)ne/ </Sf-˸8;ӣkA_츻thk7Ⱥ~ڊB~t2Q9ׇ#k?lP빪|1hiZp_;0{7>W[vk2}udMhPvJظg=6.D)?d9SKRuZ+"0$t^Sg/\\xp-,\Ea?_V T(yrm"b^\ ^ HDD/{FEDDD/{FEDDDDɨ(Q2*""""JFEDDDDQ%""""dTDDDDDɨ(Q2*򨍛Nܻw_}w#$$$t)}0vA=Xlȣu:me^^>/7LP~#M`?R2*8[ 6nL~^)ㅥſ:vO[}Y,\,_L3?ۯY$v܇nٽ0eJ'|`Ute~ߟ~W,ڶl_ ARR2m[4x~ESprx,^w(Vďwzw֖s24_;1Gh%!L&iתS[6nm=:{ ϜɁWGX[{|E峥jwWz3gCm\ q/%fzкtyP峰J ȔYظj6lmr:3-ѓKTqҖ2Kdܤ\t{¥}'13ft| t$8}Sg/S=;m^łQĆ{lQc4v5h{ok{X-ґr \%>srN;;;;3m,ISLLLq|Z6ol[y+͚e'g98|}}=.HW_o\KW;N0crۀVλ,[OXӢ$''s?T9 |\:P⫢u#%UsY#051ƵtILy$ LTQwկ/őY﷛7oBua\{X֏HKMޖ?4Aݚu>Ȯ} }GBt/rYC?mtbٞزc_zN鋎Nmsglں{ ކͨ]b*٪ՉxBDd$7-ЀhznG[[U*ѫk dTŽg:whll,ݜeW<|cù=~jGYII2V~.>Aa'GOxD$ʵ Ԅӹc+EWN!,1V]y7աWE4j0}ekp)TЁͿ:5=2s\ĵwhܠo[Z7N)o3&t~)kY_an^ƒ6gj oc׾t= #RgLvKGG;~e1(P)奍o_j?y^ӽp,-̙cg|͘siլ>-1+affB6x&NocƲo7fi0nxFN-=&e˸pbYгT(;q-]{lܧ+:<N`*QLA\toTǻ.Y.t6}Y2ZZF`n]lM@ތUFOM`׊nbV4WWܽ3ѳ%;,|CBWxl0ZFOŦUsdˎ;x:agc͛P>8SZ˕NLʒ7A^e~:oGf)숻K)KBb"CFMj tВdbbl2ޟ_!aL0LRRS:z:^}f888۩ed-K~Eb杌8+fg~ yˉ_O_,-?aZ=]&89s-l܁- 9ԥ:z*իx2RRyny(?_;L8Z6mt.LpAG#8rR0&{>|Sײk7оrf_AORVMKB6GhoZLvC:m/YiP #"2JqLeyU=@TQ5DDFl$GRSS5q?k e8s2w+ŕRD1 ?:};жhij#*99_4މp^#ݸJVJ K m;eGiת)v꠯uWÍ%+7/]XB`5>wm¯M{oSݾsiQbYBb;&&ƙ򖒚O ( w(Vɧ%kV,NH;v]J$Ps*FT._:}Chij2u PbYZw9خo_20lm |'GK|Skibnfes͒9˸\yW^BBGd͌ѕ ~i;4oWݹ;W;ݼ}/eJ3wg2kK }yy˳bl9}2wRю/s]rJ3õwXt"hؾ L=PqSIyL+n/QQ L9}9qS<]rBB11J}R9y"WbSUVo؆KL90߲빋쩣(W&}*g2$&&z66xI5x#CGO% 8pyV|S[8s<6+ū7v"KYYZcnn8GNLN+~E궗ԭU7p76k|QG[E(&*G]x"{!U*(RȨhwT,Ζw<|D-+Ks\K* eHLJ"c.\A/ʥ+7x%T(L=K+zhhhPkOn޾iX)t(."2eU.@Tm)e9LvU{Ɋ!ժxrQQk+Kʺb-́Fcɛ|fTkXO:d=&&K_3St*:uLTlg̛*…4} 99rCAOOk:-7c`P@=|7!1)/L4 !#ݘ>1*eUdłϼ%kYrmZifsLS>q+i;##C"Լg8r N'ɈB9̙ƭ{eT 99Хc}]1Dţ} ܵ fOɞGٱ k7At؈Ȩ>C*'55jd><)?-MM ?Uo_w?dC>}Nl\$&%}V})Ϳ7**{'bbUIQ*EcLKUXYZdZ6$1&K esuN3UrCq*뻙T?9&MMMԭۖynY32P\T'MM R?^sW^|zӬn{NF }VGUn!]hX&vqNwcanJy.ua^sW^Q^2T(놭58OSN/.֒=]]\J}8qNJ;ݵg/^SZνGx57N[[x5/DCC=y.w?Pzt^;7Q W(V*^[;+>!!_wߺbjqd> ӮUSʸѓg*%}yz)))t2niŊʂ/6V mmm>Ϣ^~8 {{ԤVu/~.O޵tqttUp rT/54WRZ~/訳oq)U[kRRRɩ>}*i~ͅ/ʔoU/*xݼY}ڣ/jYA/~JNTG{[,-ys)}}=-r ܉O g]_#G{[<]8{ g/^v*YPSkY}N?]ʮ_07#,<\iٓgJ}n{8mPg/\̅|\IFF&]lˠ3yTB__w~KNm֩ NdEԫ]8nډMS\ G˘Q̹Hw~Drebg9~X*μeӆ~w&q x4=+Z.Ⱦߏ\ ip2dZ?) gSyoC&W,_ XY+.hX9KIJJDqgfMםW3dTqbIW(7 oIsLMۖ-WRCfujUws.\.,ے Zɧ%M͗sbgcʹXr#LԔMaddDG/=}g,GS|}Z.ރǒK Ə@:Vk+ǛhjhPF rDœ;q @*ͩŜEԔ*ѭR`ii}ٵ0:rr}.>$%'}8FB әg TWͪiݔ9VCa'N)u̎ggj?Dl\ffT(x[S&glܺXlS\ERgeœCzj6v=ͿO >9UUG `=L]]\KG#u܈ް-{w=]Pɑŋ~vwW:LN+~:5x ;1ov6xjg.[{-^BdI՞_2lttt0r 4jG ʷN !YIIɴhߓeI;̘4<~3*Ҿ<|C7>̌J=>/ub+MO\w b@Ӓ+ IDAT !CoIU X[[ߎ}Ѥa]wRl_@ K߄pz4k{)1,]"EQB/ ZZ,_(445(Q̙)cQ'}<~5VGg)gIs\J0_/rX3*B!ȜQ!B!B!`T!B FB!B!BH0*B!$B!BQ!B!B! !B FB!`4?,^ѓfKA!BH0ϳ0='2ebB!hKduF_=}}}B!h&Š ~‚c;Yb#>ĈU+ѵ7zGDq\MLMM_:;BCCCkXy7աWE4j0zzsa<ƫo035Vu/~ځuwTy+͚G9ySf.ڍ;hڐ?y8^C#w3jר@~#x(P)k`cmx̩sx>7# :HB!Dh.=1ҪY#|}ZpcV̄mE`sڵn=b8Ұ~M.]S^œ{kؼ}~hkI# g̤8:1lP tT,ԤWXZ/D1g :1nxFN-=Ҝ4?_ӻ[GLLٰeN`J%B!d|}Zа^zPYÕ{v"511b֔m\Jܾ{_ް Rř0r`}Dm[|ONm?+4[?y+-,gYl9}2wR;[ktuuZܸu&g28qU>~MH%B!= "2dcb\!}$2#333Q~Tt4Y=+YMȴl}ω#55ĤMBB"tPZG#B!M455[Bb"}ܔnqtC_O +ɘW2 #ÌGck9%( 6*J?|FaU͋cia6m|渭F̝>& {!B2"_A/~JNTG{[,-yXG__bE q5i,&g/\Uw s3bc㈏OP,KNN xmRSR:;.ckcMJJ w*:'$*-+[ƅXq.ǁsH;KB!Ddd4X[7(U™XGxxkZ0flN7սHIIzs3S~h\M[KDEm^---HGųo1J/eޖT_Neϲ CWGGi="9r ]ĈbE,Nn m[~OB{TXwR'ӹ?E dټR)B!?œCzj6v=ͿO >PWj%Əƭ{ٸbbbDZUݜ ǚU+Ӻ)s&*:NtF`w ^ep8 S1q:&mҰy'6mWj݀Nkn?WhV޳e>mܟI-\/v|:̊[Tػ ܞrVꄭf&c116Ze]FZZ*%1)ŝe_]KI֫m--IMKW lY3_紑~.._ɰA=151B?~s3l4#hTm7&9%sRR쇥o?*WE:xƹӿX<]pwQZ8=:Pƭt'))WnR2O۷n_[+! ?.mDCOQÕj^㒓;y))^4 *~*~4 `TkXaOR>=ѹVYnν{^ԄZսk9 |\:P⫢;]Jo'(ȢY3- p+7̂kYt-MStmKf)Q`ٖdޅ3m^ VU\T< bъ <| Wo[tu>oCX0c,aYbo9ռ<յZԨR^];`P@_itbܸu 990_7?IKKV#oEU!ŊfnB\ĉ~=;%kcccկt d=\v7!Pvu:wl œc(s=x+^|՛q)*Y.[ZRL_]FгL5/rkgzvރ'9q${2oW=d͆*{;~Њ*+dmں{ ކͨ] /]gX:w2%UlGvm6?dYK~ņ-yK4o ( œzTvαň3vZZT"}_Jq;v88vJ7 ,[xJӪig`kcŬ)m=;PZeʗϧucktfLiߦ4ZBtL,ꅾ.O"....mgρ0yGZJgx9>bbl) =?_;L8Z6mr2ޟ_!aL0 w8 + szu逡a<Ɗ-ȅי[z njj1<}{IѡI:oیWonN9fJhijvhkXq4_j`:""<}U=U^BB=x  ]]~C'`XJ(X .\Ʒu{J|ԐKQ;Lػp.[/G-47gLm!.cm94,MMMzu퀥~;0iBJsgY,-9zR0zMl;of9~WPpA5~OGf.X~+^dȁ9U.^ӲiCLp͡:uv:~6Sc줸ʍKRWmȉؼrϛ9o'N_[w.½GL Mq3xkzw눉1 ]:c#C4|2 IүF8}v?JckiP&G]x8o䷹˙1аpLpAGunoDFE3wgL8q"˴n^ыWcnfJ>9MA^e~:oGf)숻K\o׾T,Lj!?>>3׉Y&Fֿ{!g,gg]K[w073U74V?4bڭhM?S)OΨ39f F@o[iXBN}Qک oڶnڪZ(i) Sg=~ꋜ!Fcgm:z*O_("?u}}=UctuI61+ )Pynɲ zoij|:h̙%*o?>^yKg(/^RL,_DVoFFu۾ L=ScIyb΅پ I̞:JNjZM(͛U12j,~l"fP֍3."511b֔t\Jܾ{kRVU/Sh#߆Rv yٺwm¯ Jt=U)DW9U=J7cR:7hco>Q^e,خ/[N݀t~>~]+ȉSpwQjGn8 >\y7DFEuڷ?Պܱ4g̤ xKٶUjTD-኶6f/Is-VZZyPEWW #*n,w8BH;"*yGSHMU~1|ߺG{[ UKK [l`o-{+WFpة,pUC\c9댪>Sc/Hll#cUo֛m#ȉ3;y^HGo?*y{+VSSukp)`>wק夁ie~Nm)U™-;S_,_^]SS6#j=ccb?yoei|a"X4X**:F^#M)R!_r0)!?Ty>= "2dcb\ᯑFk1xd|EA;8{zTEsTĤ$K/s+K$1ʑ}!>'6.Tw*hKI8gYN&{e_*ڸiNR]lldHdTLε'X^S>u(˶✦(8}ܧMBB"(ϕOMMCrڊgeՎ>=^O>ןQV\yGiY"=uKWmsʷ:SJÌTqgX[bTvgޒ,Y6-MJQ4H\~NyuFU1K0 3̼ T< ?Dgh0ߏ1{*tlMablg:vzO5෋[ws 3:5VFJyKV3`DGOOdȨPEgq2&"2HbxDT#*ڹӫK,->*΋aH!077['oe´mm9y*u%4,ue{1R52N)cۻjUbXZM߾J5_Wg/RrL5uwQJm:99=W5M72QT5֫Ona`PC{Q*Odc## ;}L4 ?eFs~@sEQ㋎ɗ~GOνFSbܖ3VEEEhumi];Щ}+v?̊5~hjhҦEcM?S)Oym1gݵg/^SZνG5f(YMMM^~_FbE ameAttt-.pQfG)))JLlm=oKgg"" {z^UOSӢ"6 IDAT"ŋhDDFi<\033QE6hiiq Jp&::-;3߲ȨXZ7om-6#e[6AOOO+E{{[RRS9:=7,\]LxYqFJ/g2#'T*i2gj&\6իzKVnʗpelݵ#]8Zs!zviOJJ*'!66ŋ1> VOj֏ 1yB'Z1e9ʂmkaOK4Fқ7$9ftmKۖ-:yuF<}E]coL=iݼ(mBB"ZQg?#1qB޼ e1~T}fؘ$''+}s$zɂcGo۱ ~ٷu7+3FŵTqzvW[ %'\ 6ҿq ffTR<_{4do.f'MWgߏQ[w(h'//c-99G}<$''qoBBYl=MQ%k)_Egq98/=yJtL,KWmH'jT:H߄rb̰#&Sի"hkً\zK~"ǀN[û;.OĽgѡFJ#‘gص0v ?w|Is\J0_c0j,k-*?Ha'v;Dhh8I8ҷ/ukU_3*B!ȜQ!B!B!`T!B FB!B!BH0*B!$B!BQ!B!B! !B FB!`4?LރO`j5 /={SϿZukC'ț%'A3d Ҵm7nܾ?f!&[V!ѓg2sq9|:'M< o)O6wC5%;OVBQWuz?_G]!-ARR28jנ[i*sǠ?v,1mU(!,Rblڶw896TXvczvUFeoBh۩/rEG>~k`cm)s|&:ڔq-E -- %|˺ѷǏp^ @N}hTﮔYv+DWGCN1uŧuSw j6}A~7XZSjخ9::n}c)/VDσGO1m^mMtS Nٞ×iekƺ-xZZe㯲{5[8} Q*@m,\FF ܋kXy7աWE4j0zzǧ[8tS=;{SƭRi^<$<" {{:z7v*>!a[7ѡVu/jUbɜؿ23E+s>ZԨR^]; |_'.i0mmشrn h> ĄZ+շy>OINNfҵ,XMл9WFݹ0{7P71W[U.3ʅXaWF_Ozӽ7aPXQDݸrVo՛hiiR#ۼ8mRާ\̋?_hք۬ZiX 133~j6wA^2q@<˗aՆ?yLMq-]|K_:H")J!j,1j]؍MXƖ;-ػ`î(Hԥ/d;3̜3g̽bld2 quu";6.C]1s5MogPRN̞Gy)iTȐ~qRTUr.%lԹK{Cu~+nƭ;38VLpqr(rxѾ`ʝ9z4iix{0;cݦ@^voOTWT 1,_7ILL̘> &3<")9}C'?m>NQri󱱲d`Acjj}"dz6j􉣈awp_'G{"^Ghhh0v@jx3|Pof/X073E'gWӍ6v7g.\@ω+ `~ztnOdhߺ9n.ՈGKQ,e)sY٪*c8v9zlZ6_5fp(&8$mm ՛1W,hڨ>-K~_M&!3-lȀop?)+VoS> ܾ%Uٶs?gޔ0ud!w1ؖF #ܸB /7E'O_b[T*IQsOqbOv_Z3/`˚EH$R֢V?&_W ̀Mv3|4֯eGFeȨIX[2j?R&Űud*:v>z=;r0ocX~0Ĥdzwk1;`ܥ8;VDy8^$ƌO^,2vߥ0}HLit;+-giT6,K|_cϊ5[Ȕ)c)~wswrM 062̴TT#CAx9hݢ v#>!>ABђJqqv .>Эckzvi~bqԘI3r'>ΎUK.\ > ~6лTܔVqq\Qw/ N gOYQ~ZZk7UFD^h?ݴgǪ::ZL75mcCAc"_Ϗ KNLH=`H <OE^;CşIIIeg,a*WPAK* ^2rzumx9rk7n+&idu$vSۖJ3,HlV\}/_WذT@zyHHLR |}<ӣCnpj>zȢEarްGʌ뫈luNZ*|ۡ]?~"CX}Vh[ʢ`gkShjj/^{%ŝzږ)K R֢V?ڍܸcv{ ȉ3JA\Qeo}tNõkywOٸC)o=4gC!{Jʇ Ux_6jIq2hX[Y(mU 5\ Ҟ^gIff&qq>ciaFBbRQSSݙPCIMMcH\qKq͵RMM= ##ڵʪ[DBPptmm72.Y[[]{'a|^$%%sbeq=ADl,bbb |&Œ/CtuhAc\2F/~ƽrVVuл~OjE\VZX+]z9)/-̰TA1!]سkyeg?*>S tD*{2F\|N,?C?׃q:9 _NJj*-/ќ` Ie[ +[UBҒÖnNJcXMM x)~k~ sS$6r^hWm;`U?~Dfd\3 dyƜ}.]IdT4餤&)+@zz._C.\_ҡM Qmkuuu !{2.oJKQ25֊ky| j;_~oEaV1\>9?335ʹ1o<hJ$TE_l76.З'JKQ25Tn7Q:Ƃh|atym-,áJ%ƛ(VmiY`ΎU>i?ZչB/^!}de<¥kۣ@O3yN}*ez,3)oz*[&3ȓqH55Jql~ԯSлYb-#~N%*ODlˈ7~*zU+lkhV AܥjјF RSccb_ťZeyx"ڵ+ј8:@FZR).^S*셫r狶6QѼxh9ٰe'TTɒqqZ*UG|Yb=g5)Vu"<҂lGVU.)>nTte씹tjגmIN~ǃԪ᎛ꋨvq)~0FKKGNKϑ:j3/;k3s3Y`LV0Xf QocbJo ۍL9BRR2ժVf򘡌?KyܖWo`9,?%_'}2f ~YNE|:n/PcjbCy^F4[4*0ʡu_/6oKuO}>;dhs&)F :5ow&8Z0sc#/okXf IQӥз>֟EThEII,끩E hc*Kid.K[-jbe!rs=: d8z(6ӑazt ) Ϻ;JYYXezE܌m;M55*cڄ>kJ?B+y YV??zumXLff&L?#&ڷRvIH$̜7bDEb=,Le &| ڳ`2]f^Q6dzHLl,:::;0wT޽KB g عM{ط}PD|*"*\y[{AIT_n6@bԸ񭁍%KE IDATu"T@ "ص0QQ1gd`cewz)>-ߍ83*@ C@ `T @ Q@ @@  @ "@ `T @ @ @@ F@ "@ D0Z,_3 EC9s zGjjڿR]﫮 }Z_/ sos@LV=7ub<|KvĤd^iMo+\1}R\f}ɟ [wb1,\. Wj4k_?2=lˡ./&2-CGMfۺ%Iablw o`8UE]]?g--)V-s<9oim|-FPphپFt\3x%WjpsY_sWB?+=4OPf9W0 ^.!'+/(,%M$Λ 'aF˒x f&tԆ`o9w* ,}}]mV^GƊ>=;(986o˕kx&~ӣ=jj'nq?B*ġJ%|ە&mt ?/\ W`meՋ/9WOH5i_WAg٪ܽLuj߻3ZRiea-\Lbb2ffa7%nh>]035VܓŮ?ǡ|#C 2ؿ;d9o"{.%lԹK{C5O13觮Obצhh|4KWo2zlΟCϜžGy)iTȐ~qR /#weö\r uu]:抲^dɊ \ FSC/ƺ1jXƭ$lX`*Wb?z!ߴlBǶ_[W^jjp)f/XNtJgm ES?{v$++={051u455 mSU"++;0v @"Q㷵8|ޥPtթPV>]בt?OZ5<&%%kǞ-+IIM-3]OԾïg/h@ߞpVM* t+Z6BirfyT<ݝ:}f18*+3yׂBP{U+V[wgqV=:(9K12į.sƣ'ϙ>{|} ze GLlxD\%Z7i#vrřמ෵[q3LYð~TUm`l۹/6J=3ȿŸr)hǀo(ھFy/s47cρ]8cU&ƫ7,}#F|7W eB>ohki1&L[9C]Nt5v6V\vuwbceI& z}=| ^EDbgkłYco$tAZ,8S.g9xowŒkA59 ɴkTII3ѾMszumKZn[+HHLbAhkKy%Ɋ/^ b9$)){2r"^V٪l GqsFLl#'O"@8TsA \ زfG7/fDIJb.y3ȱ3IIMa00߲j-x 셩Ivf'L/2.ʊ՛T9U 2\|>/)y9qtuOmpqr鳗޸'Ϟ3mJung6qu^(wuuuo dl]H1϶m؉3<|Z!3COOɳjtnZcldgd**+lfρс*+z?M+ܜD"a>9ȱ?ϱr tuzːQdPRMa8:TVs#.\Ɨ_ԣs8TϷ1H$wĈ]1g))~uYi'Q/Ehhh? jcwy\e'WG癋2Es&Ȕ?m>6V 웽015fՆyF)=s 4N('ZZ1y0C.E&Xu9~9 6*ɤJ߄ce 7j'rm |~IMK S:#--W깼y-2*AOĘA}0+U¥y#(f_N aɊ8U [wyŵ} {P_wGOOQv!7o)=_f`an @t5{)&@L+qvʟ/r+$TLnځc<90̀rq pܳ owXi7Rd222յ⌥ wsGOex(l܎cG RJ;&[s%łY @((-6V@C-͈~/wgYM\m 7'lu?!֝<@4?L jjfx;sԅ/`k]NiAS,NCAZ6\лMǕk64. +O,.jT&2Z5~*Oƭ,kK\b6V񲠨yx9+Ѳ ))g_Q'OtQeQUiϋ$/2` Lgn K钁~-30PJͿb}߹Kl\"ry IԪJ d3dds]W~OV=vA? nT`GRR2eM6dk*@jjt].cUDg:s; 8;Vֺ\=yWQx]#zdgs*8@U`fqj}j9++{&&&] .\#2=\x9  CYR6q,<gUsb~|O^JR؎D\l ; KyҠN-u&_•ݥ8xKзG>Ÿ0fb]]< 1)ӆ<,vh_fެ-Dzt5-MH55iߦ9m[5,^ȨfOT(^}}b͵شqqyR M7ό U7Q݅=Ę7QohkkQRyΞ)))\t̹`IqV}Oh8r QocvsAժ#H8{Jx;DZZ}0ӬICn_HOu5]ڱ5+̄ѡ UB+MR q]W++ 6VXZs5PlxǾC1PrE\ВJ9^\.õsRMRemyCJA6GH(0 ))By[444rۡJT^ /7CX>Lg/\ձ o!ϔ3zDbiaNff&E,t[3/seܜ*g,.NUˈ/4DM‰SJlK*2otuҾnN/IvvuF<|Dq===ȱSR}RMbk]+וmN2m_dF2nwC>+6 b*ҢLͩx)ΎU16 w3ؿ{/_F-p>4'm G][؈G"` ex? j9oŮ@_G{}|q ѴQl ^]6:!&SǏ` ֕ fgu^&>ÄC9v'k Ϻ;JYYXezg=]9tb2梁W}>;dhsR;ԭIJev#3S鿐LǩPކCvS?.޽KBə>g)Dd$0;~.voYQV@*a2`xV:exGP7Yo73y[^ęѿ,DO&S.g4D-+q+555- `vK;aWDm_l x88NTTLf$x: eW*>!Yy'-O JNLl|CN1R>!=:#/} ;tR֚F? TsdLLhԏ>=; |BB>d1ؿ{D@ !Ό @ D0*@ @ @ Q@ F@  @ D0*@ `T @ Q@ @@  @ "1U뷗IYG'pϡ.D]A 6>/i{@y"ҩOZU9L ,/W%ڪzXy>U}OU BsPuLqFֳ篠tPf9|6 b>A D0ZKHCdeeѰygƎDzH$jvݻ*Vc`θ:)!2* mӣ>^̗_4o MJJ +l#6.=[Vz2n}Gy/v.g5ڿ}6Nސ IDATB|BmM J^~5FF|Ӳ ~(dz8U¦m{x S:~-}@a{?#'N}ӭK /7?a?vx,ѹ ~kﲲs: Sc^]AS3smlc0t݇=yt=\?wnS /^F`U΂oAZJ}>ȿ`$%%PF;Vqn9I;- Xv 7nA)DZZe耋1q>!{Ҧe%Y}7s3fLRGau﫮 ӕm+ESyOԪQ^XW,_f Ϫ},k+KڵnFF mG~;ȿŸr)hǀo |&~#RMTbƄQhiIa [wvV*w<{e Ivqg٪ܽLuj߻3ZRi>!7ѓgu_E ꌋSUzq<ݜx&۝(4c!Qѱ,?86o˕kx&~ӣ=jjj6ScfNAkǡڼ$$&&cffL]_w@ OC_ƅY2wrv6@C'puv`w~K /`Etlܶ^qjϟg.2v<͙cu;qҵC+dzNGOil/}6c7},r9'ūW|۽f\ ͬIHL]zf'L/2.ʊ՛̤kVvy"ׂnӭSk 9z 󗬢R[\1epO%f;oSSc^E#S$ cjbD̘ڔ+U.]ѹ .N<}sXcd TtcaoqlݭssXs3ų܈#?ϻwٸcn\d-x 셩1}:d$l-5TCbi:o2ƉS畂/#]]͉*u016,ySalԪNHKo\XS* uuu6lݕ7՛8z}=| ^ED%UɆ篘4s4W׶}ֱM/'kH=f[>]qsF\|"o(񇪕+"3fp"=2}7ouK .ƊnnNl,i֤M7וPï~R/OBbcFB[['/INN@ O1zH$ꔳ4󻎎SǍ@MMM1!Ãx9M{M :~!ps&=:Xh0z-6WSIYnpj>zJJxwX8{^۝4nA u8:TfP "^}:k$qLlKO/wg.^۸:W9R&3L>A>w{*ֱ5=֙L;aqv1c?zt]Κ=vR0ğ*OJNm"2*s') }Aә;m"]˛C~b̙M1mί C_OھՋշ9QR^e!odd4II4񫧰ꞮnT*eן1 v Rņ DFFY̤ wsmulS+(JᏟA>YM|H$x;t†_F;tkA[GOO Od2}(ٱ*ȭP5i@uX&N7_>HOě(eg=yƗPCTB=\%ocbY}3]s^hu?馼WVwn>PvMQez:29W#.>בJDձ47#>J!RMMKUΝdddP}#H S<ܔ'# I5v)ظ<?lh/OPxvnNJY6555~CЭ;ǐ:y➓g.Ұ/RMbmq..Qzym-qqr`ϋc"svv! ,P%¨h[$:&Xe^k@OWq)RS Õ;aHO]J AwY7j\@Pp(:څ..--HHHR,,؟gf į>v%LLȌc(˵e!`nz'7fgrlfgەdrb~->Cj}7|KVVIckcC <غ GÄ?~JRr2rRYRr9g}=d144 9)9X0+syTFZzb^횜<}mᣧ<~[-IU^ZZR˫ٻ;b]4mT^NQ.[P{f` fd$+`ܖ܆s|W!ϒKeW sSV:]Yb=+Voc%I>Ɪƣ>'pan戆F-b}߹Kl\"ry IԪqy7_bk]^~;`϶vЏx3ȿ*؉ Q jj'?SǍ}fDH.!7QX2<ƿo~!Vo];Ưgy~xLŸ0i4151BCC+Ddǭnj쉩8Z)4˛x AALkv!DKK @c7^鋔0ű}[9dY+Ԥ}mՔ.xz"b=2 y}^s᫊ ̴++Mҫ1ӻ[{?ªuH$Lggk)w* 5ВJbx9nѩmK ;{S066_XC[Kʴ r--9y{6&_U~ԯSлYb-#~N%q/Jئ/M&%zũ*x}E;ޘ. n wVI{XΜU+(Tc?#}E;sw-rF菳cU,-$##}䀖Tʹהp\wƭ;J'^c_FPp( 9YYYpw׏.peΜLcYu+| ,H$4Kx'm+k LJJBރG^uuҾnNXޫ{p'7GZcme'cᏞ&~P6V&mEM+p* z:U>]'m4R@PDf*%6.-;ꌑLq(tޱ56,9/^FWMʤg/\d;=]x5+nǓl'3-oNXYsF0{Ί}Aq34>狶6QѼxCޝV=q.c(ӧ}{㉫sml'$2y"5nHFfݦTQkՌGOYtn5ZZZ8r'^>J_:v'^Our !ӮK)l ܇;,͉z?-/{gUU6. n1pD{0FEQs l c5:v"آ ]Kދ7Y˵sڞI32yb~[tnݹǠ=H$Vۂ[;쿛_Br=u>Rcu?e˔D…װ!..m m֤>&&6N6{.$5-m;ablyYQ[VVHF?uӶEvb@~WdcddH#{ uJZ[ѭs"{zq9v9DB:!Wfʸ߼w -h~}\ёEdza..!#33c~nTW׭=0{ 455Y=%kWǽSk-_Ol\<-醺h^q ]vdKi' [5%11YIJJٱū_.`< yBTpm)[$ƭrgyً,_0 s/gcr\M͸z6pi)'..ɳsuըh~~!%%'jVNw892J7kٴu7LeeHڔ-SDĦ5Cxҕ ~.͛ԧWrx7QcפKELG_:Гd|m#:&@?x"k6q]$ԫU^*^A^thӌd׻x!66=Ve{l&X#`{5 TJمb2_6#>,Hyª8|IIɔ.ènrߗ'H~6Է;?떵X~/_G"QΏUܯZJO0 5[wRkWM&'@=b?޸E||"ԩY^ ~_= %3#K 3:iFFs_ff&{1^zukWwda<6nͅKPHe'11usEbb055íM\*$ ec?c,U+;nW7<ȱS'$bSښ:ӾzvS_~3\e.aߡKxD$Vљ5ȕxIVDjuTt [ҕGOOJ׺舊JV!ٗySS#:kAf {e ez {g#B`ldH.mcUĹ QUUK D#wGA&EyTJ qF3ԇ+b@& cX"Ӳ՛xL4w`ȁ2Χ:/]Ҋ~cAlpk'՝s/^G`dh@Уk;Y|Vgǯܰ>}zt*(b+Ê[HKKO_C ףP6_['ϜgB\u񻠘+0o4c!VџR%hK#OŒ}ȀWaoXKF>q$QQ,_yW3X2/^1R.fبiGWG[%e耞~ |'O_ (!xF(O**8p]ٵ'ψxwR hoKN**LN~G'~+ztV!}*#܂-#x!H غvLnb nZJ-LuQUx{بi4mTM]y%7l#"2*GhOyf.cto{Y돾T&'E8{J3b <~DޥԮQHIIރG#5lݹmXXi| enĸ4_)cʵ~rhĹ PFU?#'(!c9:pa( VqM:i,7g;|vi[ ^=;cWΆg.0v|ϝ +%>kVX[Yp 6lم͚ԗaWߦ[6qL89W8F?}Y+p 3ceU=]9&ʫ7,[ }=])LmciޑWnw;*޹gjU*KKM؈'8E%.[] /^e鼬$]OO7WYKТ+ u!>!'[Y؏[[my%k7mɳL>,"Trb tBoN4ZŋjIOn:/bHFc兦&AC]]:chڨ>z]PGSS3 5VguDŲrHTUr6na1TsMik:z 3thTvoxD$KMBͱcbYd&Fddd0aztm*8s"nߕ%6m=cG*9=kֲWg\sa1}oIue+g,Qڔ*80Ttb-\lhk¥kd`ڶh,Tto ɞ֝{\v[dTgxbL7\jah1< y,j^2k oVjVDo.H$.[ˣЧ-SRrFO4k\ ~ ''E?7/ӧ9<y8ϰ)m SY:O!!U*9g8;v$6ҹ/tng{<jTv+y\2XZP._J%iii-WV֟ IDATA_Z sAvoUg#"}Z1@_c#9)*93l!^kKY2x䔏ֹ =p0iB`Wl і-4Huuer*V^:/bx222hS5uFJRY~P0#==XݼCb|2xc]‚{۲kl0352^G nfjBdTl0Z5 pͻrXU.\q'[٠ P)aoW(JN|!/^J%g\*9ϥ<~߾4 SFF+ed[֝YvvT훙d%6.Az%g: Prγ܌Ȩĵv{B?aL_w=$--z)dWE&,-MW\ܼ}Mb&ڴ@*}\WsqȈ'Ȯ8}:5{tT.R|'iԪ!m_z̏ޥp//w|'(8WsQfTUU~+m\1B(,EiEA~1W~xkf+yu#C֓JdfffޥиU EYqmՆN- OMHZדO_Oo"m\llApmPVp]JZ[q}LbΫ7\u-ٖ yj.'>̳m}}HL?i3;y/_BZzZ>*CEԧ۩**ro{*Ǿ]aۮ\*0ЫeJYٳ/v9_MëLŽAiϬۀ{-ظ\m06L,P?OgkڨGo.<ƣ'o;IKmجI'&<;q+1dd@*)t϶-V.Jnvd>55ώߊcHi_**rkrD"AWG϶RXRsE2[RlWCG]mϝ7m-"i#d}pmu 2*& =oF ?K 8:GUE#C.\[T%$U{csdރXl}<:ѯWW:< y˜ss 1aP~Rr VEzSvu{Ē>z:RtlۜrE%<"SQ}씵}mmگ-448g_&##|m(j㩩i)ꛛΕ%+VFPDu[pkGbb2wac%8z ]DOCY _ř*;e]:t$&&0)5VsE(ٙa3sr!!!_ iլqwlی'0l4ڶc#cbu}=ȱ3Yf@J'pEKvf[n/){K 3wOaafʝlپ7ײg_p;U*9k|QZ%J*QrʢgzVm>L 070G5 6'y@_6-}8ؕ#66QYo+!;eUÅ0mRwi ^c/ŵ~-dl,ɋMzv"޾e`Wt;՛۠;yq~5[۰f?1Tt'#3/ҢESu"Hpv6%m>bԷ7HTUYϻw)[HHL@_*eߟ{)&Ɔ:1%, {!bIU $% ՗Kʾ{FF3hdqre >!Gzq9v9DB:Qr(HR]mmITt4Zŋ`˼icEtL,'.>}==jըL_ϼ)#}Г`jj̛>U뷲e{ q ӯWWel,ɋkxJY[Q\yкzR)+6 k+ O!7##Ca#hhSڊn?{#C>uvka iײ =sνoo0PQaXz3BW.tвb ͖{>z~iĠE*uӶEvb@~7dԵ^-bٱE%ʹuh;qn 4o_g&x|B"o#ޥusEbJRRr&7Ƞq+ǀ>BsѾ:k>87= w~k3y.;7-W qfTMƃ'!|w)j1jx?ߥŊ[i_HFkRSӸp:N0SE^ٿ/) 01:tl'1HɍG!O\ё:5 }XZQ3 參 ~ 7ϟ>Ajj6M8.s!jc_6o ULMܮ-5+{ oţ/I5c#>ocf629 W2gJ,-L[8G_ѭp6mpj 3SY٤dVʩs'[A2I۴S.nhZKWonvBBGMܾP2320Cf4m5+Ё$''n11t)s4c!Ŧ S[Jv yB> ; cG#jKQ*k3!<"R%щ*{O?ׯ#033S_d0 ~|X,,LpkkZDFб@AۖM;d,&Ɔ̘8svꓵ%CD]M=x!۴{hʩsp^VsM }})M\0o*B!Օ N i~  .7{N!̙:U+*lg"8yWߦ[6qLхK3yl@OHH` FLd9`X<`@owשDшq3iXS#2*kx5g%cW Tm6j>&=#Qsun)/^aeaw5q܀ )+n!-=NyfSF1s>3/g@ow1U)?֡R_&N_ߺr[g&&&zbdhP^~'>KשScia#2vyceaƀ>YIYִQ}OIdTWoyTt L K FbbK}6&-syFFhԕ_z6""?}66I3bei)U&*8ǰ~$%'nΆz?pk-Od] :ڜ8u^n;u"4lBq!/364(Чѡ20v(Dᶔѩ"_]lWؕ 2s'`g_BG{J6 UUUzuP̘ ۲623O->tت8x,\VѠnM^` >iK#JbꜥxZŋӠn\}M0\uqlҕؗAƭk+<+⧊s("ƈaT,-L\ qmY@]i;;r쾊tžѵckLJu173)ݪVbbYGzFUU\͵w7} \*`Sښ8r Z7ҕ fTR1Gk7nζ,#{ɞUkKGH׺2RIv稫Ѳy#٪ҏg]ӽ=Sf-!<܊cxD$KMBٮR%pN )pz hjj檃U+׳GGŲrGswLzR]TTT8c!Bm5efJ蔥[g$ QSʖ)M6mT~rU@2o$8KMct܆uS3FFL8ؕ#3~nT_f[ʂl'7=n}TM#kpϠѬ۴Fcnf6B~yգih`nfFDKnP'OM>&ҡ*| RDQ^Dl\K'{~Ȑg#C 062K*}X!TFLlȀC01 SEUX"cF.+ 3Y0H$d? V yEhow nUg--MIOO'&&k7P.$X-śY,D]J wާ g:+K3m:g wi򦭥E8|ޥ/A06N-ז\x5nޘuiZP2RI^fe%wpr%1Yl/?{~o/Y[hvVf{CҨUE:5[A4qǶ{^ϔܸy;rK***o}|%ΏU \WħT^ˎ DFEs]4p\A> ظ5zsɡ<3&P-euZeNRSӨUC*8ǡOD1o#@ uubc`5kr ҙ 4[ uB#!!g_Q;[<\QN62enj,*+*v,̲,:Fg.OWaQ迌4m@222eK9}=]^(TSUQ}!){BVedd`>h\vvBTTTX8{<{Ů= izxtCk~eZ?:Ϛ}p'p9|Err ii>oL?Wmg.вYCN:,ܬRO*/Lbc ~k ' lvPAeq$ybú$ӄm~D"AWGv׳ v6l۵^KzuL)kl'7ޟSRSIN~f/ϟ}Q SvvԘcg[/PLC:5)\G~>WO)Âbga(/Z4uFu* ZP- uutZo֤vsx/UJ9RQuljgaB?%!1 RRS?Ӡn87۷QS?yo*>//3*E䳊?g=UޏcJ=sA~SP"(H1z3Ȩ^ȍf::hxikel%5gpJ;9gY3B uu:mNM9}"KV)V ~g?š ҹ}  lvllR}ia#K#bI w֭^ԫ]dz NnjT.+ Q1hS{E|ZEEF? 3W,T)etXP,兩Q[݊iADqXZH>gzaѠNMF >jjjt9D~ε#ūל~qyr)nw֖l$$$N.APmk7fO 2*Y8RLCsdddP)`n_,zKHmU+;s]gffr%*8ٶޗaa}I:Gr;MUTQPQ;JLJ&<"H[ _ˎ}9x2,G_$#=Q`W3SIK߉r舉!g]iZW%,͹t9ˏ2x~~c``l?6vgdd.%%ǪXٙa3sr!!!_ iլlFRæT 222\ѱmVsqJ%'NG-)]I< yJpvV ʗ+ô9Kޥ-f&zхf2i"~[MMM#"y]x2m;Qͥf&DɳՇSgQSa/aW֪;s'ϰ03Nl[l 6FՊyKM=~.'աMiضGOaim3FDr=zҟ&{F۩Rɑ^ޏ*QT$Du[pkGbb2wԋ]TpWCɳ9Ư;ֲǗ:5y~K./Rʌ9wȱԮBVܹm;+߂#0gJV.. ~8;رp8liިQե{w  }lʔ}rPKڪ̜;[shtukm,nZ-OĘ~*Wtdlز|ĘՕutL,'.>}==jըL_ϬM [fޥ`ff{Z5z{FF3hdqre >dBFYi ,֞Wao`,p[X8UYGBb"T(>g^ ԋc'ϱsA$ש /%,͙8j0ˑ!H:4lPvxUglߪ)^NRR2Ύ:~\֡::<ƭ1ЗҼOڬ۴hyȶy ۖ/̊5~]CjjlX0sW谰~_>ƮuǗx)SGa|uY ҽ"m)SE|-G##Ca#hhSڊn|V׮{,ZظxJY[ \&u؏mYoR֯[҈Դ4v>(UҊ{~"<ח2x^~>e@ng0q")_, fYJ㧘RWˣT:@ߵ߭[Yƽg,Y%7&̠q+ǀ>_MqfT]#'hSozZgo2Rߧ HKKP~iWmWl K^zMtt {#""*$O 'jj G:Ύ)Y’F~G ̨@ _C@ dT @ Q@ @$@  @ "@ dT @ ɨ@ @$@ HF@ "@ D2ZLA#'I]=~ev+la⌅J()Bv=iݥ/n}r {_3/ބC?(r'h܍oOEm#E OH~#i<~Fte[JqTHFfJ7o*RR1w(&Lr6B!ϼ(VLK sdSū8&PWqv%<"k+ LU <}GTI+z{tfy;}2ބɲkdݦ턄>C__v-й} NkƟ>KMԯGO?ϟBSeJNp%(>QѱXXzde:z@n< yʑcOHĦ5{uK_ gʍ\~ u556e?F>ٲvoH$*|(Z6m#'(emSsYǵAdg`W,}<:ho+ׯ=INNg6cb!*&n}3XLMmLFF1gJ,\)~k˞iT @Rr2mԹHJz-d,9nN<ۨh8ڗg}:{ePQQރP!HRԭW.a,_&^ VqM ktρ9Y˹r6[7_/"P2320Cf4mT?Rmm {۵er <Ğ:#CT]ۡwUO0 5[wRkWM)FA]]{799+{env;@A67ʔV'FFbWo">>ccԬ@n~w>:.ҿzBgD>yF~)͠ݱ\L۰b¥kI$TpcpLM E>$%%hI+8|4˼Ɓ5OKUgtW|tuxHe734hcGk]TUUX~"))ҥ-v ܓuzcy<cR:.C3u45VTDD0g]<мI֯cK$(Hhd㌟͒yqvoճ3vl8ycg 2qFM/?7<yʵ[HKOǽSk\*9hxG'TŹs>3/g@owNj"F@psa[ֆVW%Vb_D"qk/`hkk.%cg.?EWWoB1l46G˦<}c_X艑AuGeIXY1r 5?Oζ_S;FQ1LY0k,}G0;@"QsP;e>_bP_R]6oͰQ6vgߡc 艹 #uzRBgCUEisҩ/xD|oE_On'S҂)cRM i9iB,=?JXϽKI ] ;ƽ/pmuiG{ʔ*![Zxޖ^vv<{δY=}I3ӱmszG__|m.3 폛:]]]Y"Z=KZ1uRg }=)Q +O`̈hjjKSQ\Ά,s-jjj1G`[VK}|8}~gFI2vQѬ\Ǽū?clzRəU뷒:sR].\&KFoܺΎMnQxL@-x.t^V¥Ix'[FB"S.;մiјzkM3/2 %-6Г Vt$L($R+D2 #016J%' gC8;ؑf@:V1+:;p+>*ݸ;۲%UkKh~bn5c9uu5Z6o$[zeXZ%jV1)hs|_.`dAȀC018w2_px*WtK~}6*=:PDekyeJ~|,7 jG>Hjj*󦍑Z5\3h46\<b3:RGƕkv󦏡KlJ[cGC름<~l?YAHȠ{{~nX?ܹǕke=IN~&Xȣ'٨6/[ #IHHk]Y* /*:eS0r.\ƕqr(OLlw[6>˖+;cdd ~] eKKK{{5ZuHPB7;懸aeMYz224@_f[~6?7/?EcCe5~xzgʬ%Gz~+11#=#jzqDJj*wPفGǶuYL~+'+n>'>*?տ\u_x1J6^bZao^*Wp`^kF>~y8@__c9;﨨a? 0 WHob/Qc ѨhbIl1c+b/Q{. "f;ZY}~~w;KL`ei&pE">^D< <1Yԫ#l\#zGzFYw o`.H6z2N!==m62GNbbZ2ykKsbx)45It]fW'1=޾uQ;"psūР/ }A]bܼ6-y)-'2w?M,-n 3ID<2Ɂsc}+4bnj"}~W[j!uW/}ǫ|-̉KPX999~J7jFfNG=edf#[")/lֈpZ", 23J\HJN47iKL-7\XMBBRzV#C}n}7i_u}x$qҘGe2%?->`YCJJ*/^DE:TT߭K_k-$$.~=J #?Xi6,$LYv=o6jvD"zg/HIME"Y{TϑHr9u Z/ZVJHym$--MM+^HOϠEE2otŪ%| ?Ɗ!iPG`8r)`I܏x,QmZHs***,3dlھV8\G_AHIɿ.[2R_D*y~­\zkh6Wў=ݔGeⰢ2,=>~UxPV+VVƥ/!N8tsuurcX B ^щfʝ) cC > =tw!RI?ēa&M1qlF?[9x"1)8 ~P>>2%.>hh?蠫y??СFUO1ݼ)3bLkYqD*ڼ#-7c#Rd\~ӽsvl Wm&>1g%* q2˰YYY$%۱)\yUt&S68'QlX9OfI=Qj FkӨ~m<|o60Yڸ _owv&Zs{ }hk B(s9үAzÓ8mQiZ,[bxǍ@U$ۃ+aBWGU+ԇ8\ZL+K۴*EBky}WRP,2p!-7H$ݸc=]QWWwJlDC,ٱO"12U&wڍ<~\Z̬,r^؍;H%LZ9CVVwtJH<9'SŶ2x:>8y^ #H :STѽskN>ǘfҹט Woޱ3 X1WKIʀ>]Yqbn.x5wY!>W-6 p%Wn2"(kj[Dޏ3zҽQֶwmekXr&&6;Cl#rɳƶ53u(ﶵB$y>vl䦢:!Bֱ5zzZqX[2k8N_q8X5} KÅ%sq-Y$'sSnްLM؝- Mػx&FKMצw,YĤdl2$6,=Vmd΢Ui޴>S'bܤ_J}~A!JدLzaŢi\yKV}5͞TSFt2UlXl}Ϧm{ٻ1hPԄ{> v6̜:v6t<Ѐgdž]^T R2iw IDAT8+tOHdɊ $%`O:^ س1g;w@6-JO5Ws)l bs/Lٺv1,*$6*kzڬB\|v !G.4H#Bڶt)o}%1`(k6*ӻ*_{YޟI_*/{B2*k7ٴ}=:eܩ勫ׅ++>df[Cu cUsVꗻhh@[KB7z@N _7o]t)ӻ*_?y.}?!QCGjϓghӽs//^CSSx5Y܆~.?+o9y?Uhdi ^.r.z_Lݿ$.+ɺG* ٰuO#Q&  cC$ ?N[deeI*EWG[ZƮX)C!p,ZEz@NN{ mf@]MβeW(1Уs[ڷ@2D,-׳3 hd>o3Scw_>II)Lu)Wn#anf*SZ W)WgF me+}}eۺ%a'Wn*A]F `YWW>3]㡛9t4ٓu ߼G׎ ԓY󖣣S /wذdp4󑖙CHQw1Ңiꂺzdgg~k:Ǹxtqqɘ04ȝ}v}ov%WoYa;7G-fu끋f 3|Gzr~WҿGU ~'NcüzMM U&p@O\ū-mZ6a˜ tdQe]-ˆvh֐=پ{?ErJ2ի2f@WUʖRS?fN^FbRѥ-_HzϬy10Уe_Q_1kwlR?xC'z jTȡ}qQUWg}\v5U\_%ZQ;6zjczi?fޒ5<|}EPQWw^͖c(܆boy(OsA>bgcPWS/RؾbbbkMР^wWgҐУ;x<<[k끟-_УHsIGHe.dž;yOҨbg=el,/nyRgHIIaˮPFu碭oz?꥿UIZn\ps՛p-={D|<]F==ا8uR7gGb>!c#v=/P->i Sf.ҜC`,C(l&Z5o̬NJ5ۘt ~$ /뷌==]ǘ3ٴzL^1gҪy#ڷjƋWoXq'1q,5Ii|_cmeaWٺH*>e454O\o~%Wk6bC'^|ú-<S`C`} @%MMFue_1O)[ΖH<^}ˠ=073{p%IɩtJZ֣'Q\rjHqQDz٭O}RDve<c1ųjv/$kEuH,ymV.KIot+\~QA+aeadKxb";e6TDUU;2e"v[4L&^d=zi6o_gx֖rmF?DT6({ӗD97C4iGf/\IJjjd~ᲵkՌ .:%9%Wg}aPh_]f,7Uڗ$k;3tO[)ҕI]m l"#ϊB2~K0NL?Bz͙߲ȟ sSQUaan*Um1x9ŵwԶ%;$1)=]nyXKNHLbՒYҲ]jr n '~t#9{*lm)b:(:>  ȪɖHP~7o3֏zP s2la|=ܯGn'톪*i ̓'ЪycTĪ%Hg)jrhvő$'allϿ,~c|k+ =M֕g`3nTn޾&xaGUTtv#dff2\7CF-7 1 &Ɔ%$+'20gPWW}h%'uk{uu14ȭLl+uk{|ݛKu)- V"KWor~L=Cv'## [wӱMs {;xԯ8?W|_CG /7F)ɬސ%ZQ(;C^| ++Ѭq=~>IJkaz舊BanSehWRGbfNN:016d跓x 7g.\ ՛w,u ^.R[vl'OQ}N5Y-xLffȾݹ&FV=\e/Ϗq˅/O[5%}r+Lff}=]=\|nztn+󜞜** =F"H̬pI៺$$&A}eH$X2C#))%WJ~Q19E婧+]zIIMp&!bՒYl >`kcŐ~4#Hnź|~#_N)\*6rMLv_cfjk!~[U5wF@$ߊzw[GBK˅_Q[NIM6O"bbbTO>ɿ.[2Β{_&RENymV.KIY}\V'8z喕,Ul9G#R`_i6V+7|eKQ >AaD @DRm**X-IH̝"[݊OLs*. @c%[l\-=]I(ݢSۖak_&6.Afځ>|ΘfҤaldpOtf鼟M[dϛ]'Ò:JqSVQ}FAG[[& KY")9CL4bXy7Sf.dŢTwN4k\MOO,[̛X] g,7}ا;v.D*RpUr`-͖tܓD#'Y|=C hP/tuxSڗة]Ύ5 $2#?C[ɓ<*2[E~@KKKfOiyElF[[lM[Xf TTeK FJqVfnB +ӜRSdlHT“ 3&Ū2KgE a긹8ru17Gʳ4̔ ;tq ^nܺA,''YСN&w͉OK~MDO掝Mi\ˍ"Ĺ WҪD >%O/^;Q-&F$%%1)&kyUt,]I})C}L]MM W劣nEptJj';%>͸8)-<]bWsSzuN[޾TkkkQʂk7n<{?ⱌ~TUUZņ7nqf߼+{ .V'==Ё8 VТYRRRٴ}/thB=9t4U*cei4^ՖQMҜlWnPדoY"{eỦS8{*z:TVȲcq)<]4}>SŶ2x:>8) c`jym47lS:07ҜBlmX̙WzRb.!16y߈ժɀ>]Yqbn.x5w뉫sM wի١!sUr$0nl~ CL,o߽9Vn[s&L:y&IytϙWxgG{ x&0wpq;^+Lb^XcB$y>vljiߠ4[pד 3榄ݼK? Spy~jei.%fG S'd^z"۸~mfL˶^X'{E⭢[455X4{ ȜEӼi}NŸI"6Yc Az-Ӧ%#cᲵx9TފKqǶ"da>5F f5G\\"fߡ?lEР,mꊱ{g߁X'brܮ%!Gٺ3 U8XoSZv W{*fOE1krǰlςO۲:vԡmeާ' ( dp/J_*G | KÖʬ AOFe+ A ", CN49.N66_o7A@B2* bk.ssA  ꍪ  g{FdT@@@@@@@@@HFdT@@@@@@@@@HFdT@@@@@@@@@HFdT@@@@@@@@@HFdT@@@@@@@@@HFds! ;J;У_DH#?Ө~: cPn޹_Y3r4 $;{8VCNӤMO!*)s0[3גSR1gie w̅O} 0AxM$}B\‐XYZ`dEECCZZk?ku22ҙ7c"S'}5H;utleږz1oD6Kbb2-ѡ:KĄb!#Fpރ.L{[F~1uy?Igffq-\kkuxa{$`3n2מF>Å~>k?$33P׎ʿi ^i~?|{!&;+F=}_5fH 1VL4FkpYn]na`"^b`O-Nzy10Уe_Q_1kwzq9v=̫WoԠ]eɞWogX2 3Scq6c㘻xsҌ~;uFZ|fOsXp:.NEdCHQw1Ңi]UEw IDATꂺg_amdeeMz:bdPUWSĩlJtt &ܖӬ]oMmE `̝u|<:>7>dddo{;,-Է;ԑI~#4_4kTOF#$O!9%jUl6WIwHQz&p`O4bVZ;͂pV^fDqivh-YCuW7n3a|=  3ذռ2dfҶUS\j?NO@v_o223rwAWWĤd8N˯R- b ܛҦeٰk!jT`ˎ}|J}c]lھ.WX[=DѬQ] q=BepL;b3#4{u}$%%y>jybnj{v^YBEn#\v #ꊛKM9kx:}:ѾWxGhբ1ZxQ_ѭSk:oɫضk?_5NoFN4mX[wI:nX.Wfaс^ۓk邹 5p:׮aҌXZ1AI>O;tlۜNZ"eg(bu5]sm烕s >O@'ڵjFbb2[w写 ի)-ظx/KNq8xM"_.l֐Woޱe>jy`nfPv9dt#S{8wBθȉ3 kyH9u"g/\e t/h 9ߍ,fjl)}ya'/IGw#Qjp6PqKSoE0ڣ*{? F6ͥEC,3==], rvѠn;#3ֱܲw>ƆbG<^oKOW}ŕj,}.5x7n쨴tu2g/s垻gkcE#xS#|=>7f9g/\%<-b13|(O?&Ɔ vO"YZHM]wivR]߽GpsvDU$IJkaz舊J,uWT.I){:0Ȼ߼̟#TbC~#9~:[~2Qfˍ$H ɬްlU xGn"7/'J@D€]F.!oޣg@aԷ?mmmX)E<;}hws]vHzwux{p?ⱴvJǏuu122644Zw16g+/^\|:m--D"Rc`=&j/Yڵ0ݡGqKKQ榈hjj}gߋKd| Kl3Ύ4mX8kh+S"S$)#{:{;hݲq)V%~a4fVjGy<];R())?FZZ:~}=]_4yMū7x-7/G[[K4{ Spi1e?uCHx9S1[R41Μ>sIzKTў <_-ܜk$!̤HPm--̱gdN*CMxkHII-vv? YYY+$~Dܺ{_:X[UUUL_6y&feX2435RP:2kyJSVxc23WGV5y0R]eƪY%s&11wmWe"ry0vwZ@Ta"n$&ɞvmeeFvv6 I{J$I./roWߖfRVF_(h z:hiU­U 3JS>^naNlKe$\?UUU175!6lqLfYUU:>D]{۪MZ=HEFu}2[3pv!].*zCU]m -rMERaq+Rtl =F"H,L:iyΑ3G}?MD"R4ghӲI1ӑ+ݶwvU&Ĥܤϰ/IIOϠEEeY¬ȉ8^yKZZYYr+\?J^r$ҁ~Q[4cPD.Cq@~ٺl]]DL0Wn!&LҤ-_TɫL3ɸvdbl$[}cHl NQ꒒t*"QE}~^Z2mlm_:]qv>OHF"")9:<+L*ϔJHLL~cKNIQNUN6-quɉTE4i'$_ $Bi%>۸~m,_Ϲ073!.>yKܻG'5. bme^jL &/t'qn܅HET"֢q:"-jȥk7ثTgK "$W y77U^O>|ΘfҤaldPEe 3&ҼȠ oЀln%=#Dޣ]!vUֺ&}G Ir~tutf鼟d ׃AIs~6OJ --- Jo:髴6cܸ}A}^m-F7Ĩ؋CL4bXy7Sf.dŢ8;֨иOP{bmesY Ee.:Fz@NxlWR<.|,1hl762P#,EcdMXrii}2*%V\!~cJ*QχsrUܜ]qvgTbSk}O%Mzu>?ț1KKO/-pN},6*~4䀆X̅eD"А+a7 ɖ0qlΎ]uu5^yWDOy^~CN3~P~3У (R;Ჿo@s3 +e5!8)L=sfddyWq.^;Q-&F$%%IOUIMDY#GViT•0:mA& Ȑظ2L(,v.V']AxnVVw?ѡR1JMM2n* Fr6)oQ/y>{Q֖>cs}/_c 3e<<\z*wP+p@٤"\h?ɹ޹-cM4!&6 CAZ4k9Kѡ_2 ɳy6CSS1}^9Q/pv@'ϹXLZ֚GNRͮ2Itߖߺ:>E 'te]j8l܁g֢ O7 !*|KKs%.^A_O^flm-wb]'$G7Ң]f$%0isME+Y|t IU$b]g`gcw% %(] ( Ԯۃ#Hpv'11q<]4}>SŶ2x:>C4szKs3#-@ sSf[FРprQ/K|$Rԗ"X[sbb;1ɟ2VGU'$}~<\10Г71yw@_GG)ỦS8{*z:TVEn޾---WCC,ūH$2_1)";ѵc+TMLPUU՛8:T#)){v%Ĥd-Ś ;eR4))9qc~I_cblH|B"w2t` T4FjUҤI:lܶm-rB2бms2wObgk͸Qٰ5gkr&q 2ߴpaɜ)lܶyKV#Ԅ7,\S#v}+-==ssF6͋}f SP ;BYe7#Kg{v뀮Cy> hӲ)l:>~TjWgڏ? )qё%+6zJ?U^ꊱ{g߁X'mVo`Dķ?h3r4quv`Ɣ ;Uijjh~[9V!VWyL8q~)|K*Z_,YЬAú̘<)acmɬ㤉1_Ϯ}9V ;$} "lm9uUloldw#_{a#"2DܳZU?*n\Vw*UVuG]" dA&?0$,}?ܓs͹##s!L~}z(F ;c<>>>F аo<>T*ŷoDffaTٟ)}Sb\@V/e{2RuKk#{8}z(<;:dff@ݿŎ_@*95H'ѝ>g x, V.`cT` G*y0v/֯\Xc(#{,GO燝y dHsur/<[?m"55 BRs F!"?Sin?`I5ZБKx+ DDܽyKV@_FȳE_kFQ""""b%""""Q"""""Q""""b%""""b%""""Q"""""Q""""b%""""b%""""Q"""""њ6cWy/&X GnxMŞJ1ѽB"|>KL zgwy!eoh|{\`= p=Qap; 11}z0+\DK0k'a(և)^y\9Uvj6"b}^TjM}rsr훽2c0v0pl.m `sߋthS$Vq2l5`RXn$tR}s9 .uCKMy"xh)}]ک- )9TUU1~;V}; ,-t$<|RbYq1g CDayIDAT⌅HObL+7Meaշ>q#aW`~W8되 /Hy ; Zm-hkS3?iPU-bdh1|sNHLJ2Ҭl}ւ !lߡXl\ZXY`p/DDރ^7ðbyid^\ GGii/%0Z r1qX/N ĞdotCMMuMYUڷqƘ (;^J 8˵+dz$N}ZԡR}s?B!?Ա XD%ԄBH$/^/((+PyBEO <@ aSqʺu;NnQQQAmq-Mon HIMDFB&SCJdq L /yVD"5zmb}XYn)3o6O[X ??iij{PQ\/rN=h˃up"LXDrsЩ}ko;wcկU=]^6 x>uT.BSC v\w5PiZ;y.N:83~ }O dH(((@Nnn Fnn HUcu^dd>/7+J_O9ʆRY_OWo&YSy_itu Detdgg?b__9R~FUQVPIy ׾t7]f<}GL{y2}cblaؼa™TUUέ1'c0ewYS=a(և@ -۬ ')X1>=EWWm̜0~{yP֑yjԄBDj**okjj$/w)ްeKUkc#1]s/kW}/Ǖk'035eD0Z+X7DjA{077E~A.^m[ᣧOP K-k~65 'OÔ~024@jaw1k7hzhؠ>?(('`o6D"F\#LY-meblvOA!Ħ"cq_Uζк#|>CJ3۴]mܡ561n0Bȿ Ys! "s աK035u :ڸr1*#z-MMĵ\4?FcF%ݷRTUUA'?DO.3/^5.c 0]is`׈aN֥}/bƔ1kG k6B ,0ze/O ߭ 6ǦՋCnl hҡk^9k7b2X7–Kb ,_ymjU>oe5O8;5ˑSpv܏N )%:ZAOnUv=[4 k6 ڹ-`R7b ${!hožS1nrA]]U# 5=>y&brGDVl ˁ04c`8 55!XW@+]@<~ Vm:6|JhI{:rζc#1|ivvLMA׻kiiԄ0:D%33Kf ~;_vđ=[DDE5D5ŞKKDDizj=;A} S}>Txh;(UF $%=Gn^ꛛbѽ kfj %""""Q""""b%""""b%""""Q"""""Q""""b%""""b%""""Q"""""Q""""b%""""b%""""Q"""""Q""""b%""""b%""""Q""""b%""""b%""""Q"""""Q""""b%""""b%""""Q"""""Q""""b%""""b%""":D&o"--3DDDT#xh%hff6-`iiϫDz@ٙDDD0Z> 44D k~Y"ɀ.g8i JN@"ɀ!!ՂE$d@ `Q Д4DE=X'?%)2'OR?nJ'""" 8Vtvn"m ϔV4XY+|ZZFF %""",9Y|Bǎ]ߓUTNǎ]Px)'""":<7*I1pf45E _XV1Q5U(9YNw3׭J DDDT83Z" Q_ śh-Cffעj ΌV )shrgx44D5sDDDD dh N,6z5~]nތ4mjŎ$""ZE%33KfPޫOelm 4׊(+FaaFFaaFFaaFFaaFaaFFaaFFaapЭVIENDB`apt-swarm-0.5.1/.github/workflows/docker-image.yml000064400000000000000000000035021046102023000202110ustar 00000000000000name: Docker on: push: branches: [ "main" ] tags: [ "v*.*.*" ] pull_request: branches: [ "main" ] jobs: build: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - name: Expose actions cache variables uses: actions/github-script@v6 with: script: | core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL']) core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']) - name: Build Docker image uses: docker/build-push-action@v5 with: tags: apt-swarm load: true cache-from: type=gha cache-to: type=gha,mode=max build-args: | UPDATE_CHECK_COMMIT=${{ github.sha }} - name: Test the Docker image run: | docker run --rm apt-swarm --help - name: Login to github container registry if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push the image to `edge` if: github.event_name == 'push' && github.ref_name == 'main' run: | docker tag apt-swarm ghcr.io/${{ github.repository }}:edge docker push ghcr.io/${{ github.repository }}:edge - name: Push the image to `${{ github.ref_name }}` if: github.ref_type == 'tag' run: | docker tag apt-swarm ghcr.io/${{ github.repository }}:${{ github.ref_name }} docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }} - name: Push the image to `latest` if: github.ref_type == 'tag' run: | docker tag apt-swarm ghcr.io/${{ github.repository }}:latest docker push ghcr.io/${{ github.repository }}:latest apt-swarm-0.5.1/.github/workflows/rust.yml000064400000000000000000000075131046102023000166650ustar 00000000000000name: Rust on: push: branches: [ "main" ] pull_request: branches: [ "main" ] schedule: - cron: '0 9 * * 1' env: CARGO_TERM_COLOR: always jobs: build: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Set up cargo cache uses: actions/cache@v4 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo-release- - name: Build run: cargo build --release --verbose - name: Upload binary uses: actions/upload-artifact@v4 with: name: bin path: target/release/apt-swarm build-macos: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Set up cargo cache uses: actions/cache@v4 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo-release- - name: Build run: cargo build --release --verbose repro-env: runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: target: - aarch64-unknown-linux-musl - x86_64-unknown-linux-musl steps: - uses: actions/checkout@v4 - name: Set up cargo cache uses: actions/cache@v4 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: repro-env-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }} restore-keys: repro-env-${{ matrix.target }}- - name: Install dependencies (apt) run: sudo apt-get install repro-env - name: Build run: make - name: Print sha256 of binary run: sha256sum target/${{ matrix.target }}/release/apt-swarm - name: Upload binary uses: actions/upload-artifact@v4 with: name: bin-${{ matrix.target }} path: target/${{ matrix.target }}/release/apt-swarm unit-test: runs-on: ${{ matrix.os.target }} strategy: fail-fast: false matrix: os: - target: ubuntu-24.04 flags: --examples - target: macos-latest flags: --examples - target: windows-latest features: - name: default - name: none flags: --no-default-features - name: git flags: --no-default-features -F git - name: irc flags: --no-default-features -F irc steps: - uses: actions/checkout@v4 - name: Set up cargo cache uses: actions/cache@v4 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo-debug- - name: Run clippy run: cargo clippy --lib --bins --tests ${{ matrix.os.flags }} ${{ matrix.features.flags }} -- -D warnings - name: Run tests run: cargo test --verbose --lib --bins --tests ${{ matrix.features.flags }} deny: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: persist-credentials: false - name: Run cargo deny run: | docker run --rm -v "$PWD:/src" -w /src alpine:edge sh -c ' set -e apk add cargo cargo-deny exec cargo deny check ' fmt: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Run cargo fmt run: cargo fmt --all -- --check apt-swarm-0.5.1/.gitignore000064400000000000000000000000101046102023000135210ustar 00000000000000/target apt-swarm-0.5.1/Cargo.lock0000644000003523010000000000100107310ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "advisory-lock" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6caee7d48f930f9ad3fc9546f8cbf843365da0c5b0ca4eee1d1ac3dd12d8f93" dependencies = [ "libc", "winapi", ] [[package]] name = "aead" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common", "generic-array 0.14.7", ] [[package]] name = "aes" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", "cpufeatures", "zeroize", ] [[package]] name = "aes-gcm" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", "aes", "cipher", "ctr", "ghash", "subtle", ] [[package]] name = "ahash" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", "version_check", "zerocopy 0.7.35", ] [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anstream" version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", "once_cell", "windows-sys 0.59.0", ] [[package]] name = "anyhow" version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "apt-swarm" version = "0.5.1" dependencies = [ "advisory-lock", "anyhow", "async-stream", "async-trait", "bstr", "bytes", "bzip2", "chrono", "clap", "clap_complete", "colored", "dirs", "env_logger", "fastrand", "futures", "getrandom 0.3.2", "gix", "gix-object", "hex", "indexmap", "ipnetwork", "irc", "log", "lru", "lz4_flex", "memchr", "num-format", "pledge", "reqwest", "rustls", "sequoia-openpgp", "serde", "serde_json", "sha2", "socket2", "tempfile", "tokio", "tokio-socks", "toml", "url", ] [[package]] name = "arc-swap" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii-canvas" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" dependencies = [ "term", ] [[package]] name = "async-stream" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", "pin-project-lite", ] [[package]] name = "async-stream-impl" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "async-trait" version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" version = "1.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" dependencies = [ "aws-lc-sys", "zeroize", ] [[package]] name = "aws-lc-sys" version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" dependencies = [ "bindgen", "cc", "cmake", "dunce", "fs_extra", ] [[package]] name = "backtrace" version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", ] [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "bindgen" version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags", "cexpr", "clang-sys", "itertools 0.12.1", "lazy_static", "lazycell", "log", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash 1.1.0", "shlex", "syn", "which", ] [[package]] name = "bit-set" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array 0.14.7", ] [[package]] name = "block-padding" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ "generic-array 0.14.7", ] [[package]] name = "blowfish" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ "byteorder", "cipher", ] [[package]] name = "bstr" version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "buffered-reader" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db26bf1f092fd5e05b5ab3be2f290915aeb6f3f20c4e9f86ce0f07f336c2412f" dependencies = [ "bzip2", "flate2", "libc", ] [[package]] name = "bumpalo" version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "bytesize" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d2c12f985c78475a6b8d629afd0c360260ef34cfef52efccdcfd31972f81c2e" [[package]] name = "bzip2" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" dependencies = [ "bzip2-sys", "libbz2-rs-sys", ] [[package]] name = "bzip2-sys" version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", "pkg-config", ] [[package]] name = "camellia" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" dependencies = [ "byteorder", "cipher", ] [[package]] name = "cast5" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" dependencies = [ "cipher", ] [[package]] name = "cc" version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", "shlex", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfb-mode" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" dependencies = [ "cipher", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", "windows-link", ] [[package]] name = "cipher" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", "zeroize", ] [[package]] name = "clang-sys" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_complete" version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06f5378ea264ad4f82bbc826628b5aad714a75abf6ece087e923010eb937fb6" dependencies = [ "clap", ] [[package]] name = "clap_derive" version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clru" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" [[package]] name = "cmac" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" dependencies = [ "cipher", "dbl", "digest", ] [[package]] name = "cmake" version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-bigint" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", "subtle", "zeroize", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", "typenum", ] [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ "cipher", ] [[package]] name = "curve25519-dalek" version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", "rustc_version", "subtle", "zeroize", ] [[package]] name = "curve25519-dalek-derive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "dashmap" version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", ] [[package]] name = "dbl" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" dependencies = [ "generic-array 0.14.7", ] [[package]] name = "der" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", "zeroize", ] [[package]] name = "des" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" dependencies = [ "cipher", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "const-oid", "crypto-common", "subtle", ] [[package]] name = "dirs" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ "cfg-if", "dirs-sys-next", ] [[package]] name = "dirs-sys" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users 0.5.0", "windows-sys 0.59.0", ] [[package]] name = "dirs-sys-next" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users 0.4.6", "winapi", ] [[package]] name = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "dsa" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" dependencies = [ "digest", "num-bigint-dig", "num-traits", "pkcs8", "rfc6979", "sha2", "signature", "zeroize", ] [[package]] name = "dunce" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" [[package]] name = "eax" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9954fabd903b82b9d7a68f65f97dc96dd9ad368e40ccc907a7c19d53e6bfac28" dependencies = [ "aead", "cipher", "cmac", "ctr", "subtle", ] [[package]] name = "ecb" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" dependencies = [ "cipher", ] [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest", "elliptic-curve", "rfc6979", "signature", "spki", ] [[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "signature", ] [[package]] name = "ed25519-dalek" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", "rand_core 0.6.4", "serde", "sha2", "subtle", "zeroize", ] [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", "digest", "ff", "generic-array 0.14.7", "group", "hkdf", "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", "subtle", "zeroize", ] [[package]] name = "ena" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" dependencies = [ "log", ] [[package]] name = "encoding_rs" version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "env_filter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", ] [[package]] name = "env_logger" version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", "jiff 0.2.5", "log", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", "windows-sys 0.59.0", ] [[package]] name = "faster-hex" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" dependencies = [ "serde", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ff" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core 0.6.4", "subtle", ] [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", "libredox", "windows-sys 0.59.0", ] [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fs_extra" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", "zeroize", ] [[package]] name = "generic-array" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c8444bc9d71b935156cc0ccab7f622180808af7867b1daae6547d773591703" dependencies = [ "typenum", ] [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", "wasm-bindgen", ] [[package]] name = "ghash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gix" version = "0.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "736f14636705f3a56ea52b553e67282519418d9a35bb1e90b3a9637a00296b68" dependencies = [ "gix-actor", "gix-archive", "gix-attributes", "gix-command", "gix-commitgraph", "gix-config", "gix-credentials", "gix-date", "gix-diff", "gix-dir", "gix-discover", "gix-features", "gix-filter", "gix-fs", "gix-glob", "gix-hash", "gix-hashtable", "gix-ignore", "gix-index", "gix-lock", "gix-mailmap", "gix-negotiate", "gix-object", "gix-odb", "gix-pack", "gix-path", "gix-pathspec", "gix-prompt", "gix-protocol", "gix-ref", "gix-refspec", "gix-revision", "gix-revwalk", "gix-sec", "gix-shallow", "gix-status", "gix-submodule", "gix-tempfile", "gix-trace", "gix-traverse", "gix-url", "gix-utils", "gix-validate", "gix-worktree", "gix-worktree-state", "gix-worktree-stream", "once_cell", "parking_lot", "regex", "signal-hook", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-actor" version = "0.33.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20018a1a6332e065f1fcc8305c1c932c6b8c9985edea2284b3c79dc6fa3ee4b2" dependencies = [ "bstr", "gix-date", "gix-utils", "itoa", "thiserror 2.0.12", "winnow 0.6.26", ] [[package]] name = "gix-archive" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d22c6ecdb350461a975159ebe514294064b9542a4cbc4a12d00c3f46a1107ce" dependencies = [ "bstr", "gix-date", "gix-object", "gix-worktree-stream", "jiff 0.1.29", "thiserror 2.0.12", ] [[package]] name = "gix-attributes" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f151000bf662ef5f641eca6102d942ee31ace80f271a3ef642e99776ce6ddb38" dependencies = [ "bstr", "gix-glob", "gix-path", "gix-quote", "gix-trace", "kstring", "smallvec", "thiserror 2.0.12", "unicode-bom", ] [[package]] name = "gix-bitmap" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1db9765c69502650da68f0804e3dc2b5f8ccc6a2d104ca6c85bc40700d37540" dependencies = [ "thiserror 2.0.12", ] [[package]] name = "gix-chunk" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b1f1d8764958699dc764e3f727cef280ff4d1bd92c107bbf8acd85b30c1bd6f" dependencies = [ "thiserror 2.0.12", ] [[package]] name = "gix-command" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb410b84d6575db45e62025a9118bdbf4d4b099ce7575a76161e898d9ca98df1" dependencies = [ "bstr", "gix-path", "gix-trace", "shell-words", ] [[package]] name = "gix-commitgraph" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e23a8ec2d8a16026a10dafdb6ed51bcfd08f5d97f20fa52e200bc50cb72e4877" dependencies = [ "bstr", "gix-chunk", "gix-features", "gix-hash", "memmap2", "thiserror 2.0.12", ] [[package]] name = "gix-config" version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "377c1efd2014d5d469e0b3cd2952c8097bce9828f634e04d5665383249f1d9e9" dependencies = [ "bstr", "gix-config-value", "gix-features", "gix-glob", "gix-path", "gix-ref", "gix-sec", "memchr", "once_cell", "smallvec", "thiserror 2.0.12", "unicode-bom", "winnow 0.6.26", ] [[package]] name = "gix-config-value" version = "0.14.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11365144ef93082f3403471dbaa94cfe4b5e72743bdb9560719a251d439f4cee" dependencies = [ "bitflags", "bstr", "gix-path", "libc", "thiserror 2.0.12", ] [[package]] name = "gix-credentials" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf950f9ee1690bb9c4388b5152baa8a9f41ad61e5cf1ba0ec8c207b08dab9e45" dependencies = [ "bstr", "gix-command", "gix-config-value", "gix-path", "gix-prompt", "gix-sec", "gix-trace", "gix-url", "thiserror 2.0.12", ] [[package]] name = "gix-date" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f" dependencies = [ "bstr", "itoa", "jiff 0.1.29", "thiserror 2.0.12", ] [[package]] name = "gix-diff" version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62afb7f4ca0acdf4e9dad92065b2eb1bf2993bcc5014b57bc796e3a365b17c4d" dependencies = [ "bstr", "gix-attributes", "gix-command", "gix-filter", "gix-fs", "gix-hash", "gix-index", "gix-object", "gix-path", "gix-pathspec", "gix-tempfile", "gix-trace", "gix-traverse", "gix-worktree", "imara-diff", "thiserror 2.0.12", ] [[package]] name = "gix-dir" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1d78db3927a12f7d1b788047b84efacaab03ef25738bd1c77856ad8966bd57b" dependencies = [ "bstr", "gix-discover", "gix-fs", "gix-ignore", "gix-index", "gix-object", "gix-path", "gix-pathspec", "gix-trace", "gix-utils", "gix-worktree", "thiserror 2.0.12", ] [[package]] name = "gix-discover" version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0c2414bdf04064e0f5a5aa029dfda1e663cf9a6c4bfc8759f2d369299bb65d8" dependencies = [ "bstr", "dunce", "gix-fs", "gix-hash", "gix-path", "gix-ref", "gix-sec", "thiserror 2.0.12", ] [[package]] name = "gix-features" version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bfdd4838a8d42bd482c9f0cb526411d003ee94cc7c7b08afe5007329c71d554" dependencies = [ "bytes", "bytesize", "crc32fast", "crossbeam-channel", "flate2", "gix-hash", "gix-trace", "gix-utils", "libc", "once_cell", "parking_lot", "prodash", "sha1_smol", "thiserror 2.0.12", "walkdir", ] [[package]] name = "gix-filter" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdcc36cd7dbc63ed0ec3558645886553d1afd3cd09daa5efb9cba9cceb942bbb" dependencies = [ "bstr", "encoding_rs", "gix-attributes", "gix-command", "gix-hash", "gix-object", "gix-packetline-blocking", "gix-path", "gix-quote", "gix-trace", "gix-utils", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-fs" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "182e7fa7bfdf44ffb7cfe7451b373cdf1e00870ac9a488a49587a110c562063d" dependencies = [ "fastrand", "gix-features", "gix-utils", ] [[package]] name = "gix-glob" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e9c7249fa0a78f9b363aa58323db71e0a6161fd69860ed6f48dedf0ef3a314e" dependencies = [ "bitflags", "bstr", "gix-features", "gix-path", ] [[package]] name = "gix-hash" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e81c5ec48649b1821b3ed066a44efb95f1a268b35c1d91295e61252539fbe9f8" dependencies = [ "faster-hex", "thiserror 2.0.12", ] [[package]] name = "gix-hashtable" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "189130bc372accd02e0520dc5ab1cef318dcc2bc829b76ab8d84bbe90ac212d1" dependencies = [ "gix-hash", "hashbrown 0.14.5", "parking_lot", ] [[package]] name = "gix-ignore" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f529dcb80bf9855c0a7c49f0ac588df6d6952d63a63fefc254b9c869d2cdf6f" dependencies = [ "bstr", "gix-glob", "gix-path", "gix-trace", "unicode-bom", ] [[package]] name = "gix-index" version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acd12e3626879369310fffe2ac61acc828613ef656b50c4ea984dd59d7dc85d8" dependencies = [ "bitflags", "bstr", "filetime", "fnv", "gix-bitmap", "gix-features", "gix-fs", "gix-hash", "gix-lock", "gix-object", "gix-traverse", "gix-utils", "gix-validate", "hashbrown 0.14.5", "itoa", "libc", "memmap2", "rustix 0.38.44", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-lock" version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9739815270ff6940968441824d162df9433db19211ca9ba8c3fc1b50b849c642" dependencies = [ "gix-tempfile", "gix-utils", "thiserror 2.0.12", ] [[package]] name = "gix-mailmap" version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "017996966133afb1e631796d8cf32e43300f8f76233f2a15ce9af5be5069b0a6" dependencies = [ "bstr", "gix-actor", "gix-date", "thiserror 2.0.12", ] [[package]] name = "gix-negotiate" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a8af1ef7bbe303d30b55312b7f4d33e955de43a3642ae9b7347c623d80ef80" dependencies = [ "bitflags", "gix-commitgraph", "gix-date", "gix-hash", "gix-object", "gix-revwalk", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-object" version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc4b3a0044244f0fe22347fb7a79cca165e37829d668b41b85ff46a43e5fd68" dependencies = [ "bstr", "gix-actor", "gix-date", "gix-features", "gix-hash", "gix-hashtable", "gix-path", "gix-utils", "gix-validate", "itoa", "smallvec", "thiserror 2.0.12", "winnow 0.6.26", ] [[package]] name = "gix-odb" version = "0.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e93457df69cd09573608ce9fa4f443fbd84bc8d15d8d83adecd471058459c1b" dependencies = [ "arc-swap", "gix-date", "gix-features", "gix-fs", "gix-hash", "gix-hashtable", "gix-object", "gix-pack", "gix-path", "gix-quote", "parking_lot", "tempfile", "thiserror 2.0.12", ] [[package]] name = "gix-pack" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc13a475b3db735617017fb35f816079bf503765312d4b1913b18cf96f3fa515" dependencies = [ "clru", "gix-chunk", "gix-features", "gix-hash", "gix-hashtable", "gix-object", "gix-path", "memmap2", "smallvec", "thiserror 2.0.12", "uluru", ] [[package]] name = "gix-packetline" version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e5ae6bc3ac160a6bf44a55f5537813ca3ddb08549c0fd3e7ef699c73c439cd" dependencies = [ "bstr", "faster-hex", "gix-trace", "thiserror 2.0.12", ] [[package]] name = "gix-packetline-blocking" version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1cbf8767c6abd5a6779f586702b5bcd8702380f4208219449cf1c9d0cd1e17c" dependencies = [ "bstr", "faster-hex", "gix-trace", "thiserror 2.0.12", ] [[package]] name = "gix-path" version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c40f12bb65a8299be0cfb90fe718e3be236b7a94b434877012980863a883a99f" dependencies = [ "bstr", "gix-trace", "home", "once_cell", "thiserror 2.0.12", ] [[package]] name = "gix-pathspec" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6430d3a686c08e9d59019806faa78c17315fe22ae73151a452195857ca02f86c" dependencies = [ "bitflags", "bstr", "gix-attributes", "gix-config-value", "gix-glob", "gix-path", "thiserror 2.0.12", ] [[package]] name = "gix-prompt" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79f2185958e1512b989a007509df8d61dca014aa759a22bee80cfa6c594c3b6d" dependencies = [ "gix-command", "gix-config-value", "parking_lot", "rustix 0.38.44", "thiserror 2.0.12", ] [[package]] name = "gix-protocol" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c61bd61afc6b67d213241e2100394c164be421e3f7228d3521b04f48ca5ba90" dependencies = [ "bstr", "gix-date", "gix-features", "gix-hash", "gix-ref", "gix-shallow", "gix-transport", "gix-utils", "maybe-async", "thiserror 2.0.12", "winnow 0.6.26", ] [[package]] name = "gix-quote" version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e49357fccdb0c85c0d3a3292a9f6db32d9b3535959b5471bb9624908f4a066c6" dependencies = [ "bstr", "gix-utils", "thiserror 2.0.12", ] [[package]] name = "gix-ref" version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47adf4c5f933429f8554e95d0d92eee583cfe4b95d2bf665cd6fd4a1531ee20c" dependencies = [ "gix-actor", "gix-features", "gix-fs", "gix-hash", "gix-lock", "gix-object", "gix-path", "gix-tempfile", "gix-utils", "gix-validate", "memmap2", "thiserror 2.0.12", "winnow 0.6.26", ] [[package]] name = "gix-refspec" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59650228d8f612f68e7f7a25f517fcf386c5d0d39826085492e94766858b0a90" dependencies = [ "bstr", "gix-hash", "gix-revision", "gix-validate", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-revision" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fe28bbccca55da6d66e6c6efc6bb4003c29d407afd8178380293729733e6b53" dependencies = [ "bitflags", "bstr", "gix-commitgraph", "gix-date", "gix-hash", "gix-hashtable", "gix-object", "gix-revwalk", "gix-trace", "thiserror 2.0.12", ] [[package]] name = "gix-revwalk" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4ecb80c235b1e9ef2b99b23a81ea50dd569a88a9eb767179793269e0e616247" dependencies = [ "gix-commitgraph", "gix-date", "gix-hash", "gix-hashtable", "gix-object", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-sec" version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d84dae13271f4313f8d60a166bf27e54c968c7c33e2ffd31c48cafe5da649875" dependencies = [ "bitflags", "gix-path", "libc", "windows-sys 0.52.0", ] [[package]] name = "gix-shallow" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab72543011e303e52733c85bef784603ef39632ddf47f69723def52825e35066" dependencies = [ "bstr", "gix-hash", "gix-lock", "thiserror 2.0.12", ] [[package]] name = "gix-status" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "414cc1d85079d7ca32c3ab4a6479bf7e174cd251c74a82339c6cc393da3f4883" dependencies = [ "bstr", "filetime", "gix-diff", "gix-dir", "gix-features", "gix-filter", "gix-fs", "gix-hash", "gix-index", "gix-object", "gix-path", "gix-pathspec", "gix-worktree", "portable-atomic", "thiserror 2.0.12", ] [[package]] name = "gix-submodule" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74972fe8d46ac8a09490ae1e843b4caf221c5b157c5ac17057e8e1c38417a3ac" dependencies = [ "bstr", "gix-config", "gix-path", "gix-pathspec", "gix-refspec", "gix-url", "thiserror 2.0.12", ] [[package]] name = "gix-tempfile" version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2558f423945ef24a8328c55d1fd6db06b8376b0e7013b1bb476cc4ffdf678501" dependencies = [ "dashmap", "gix-fs", "libc", "once_cell", "parking_lot", "signal-hook", "signal-hook-registry", "tempfile", ] [[package]] name = "gix-trace" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7" [[package]] name = "gix-transport" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11187418489477b1b5b862ae1aedbbac77e582f2c4b0ef54280f20cfe5b964d9" dependencies = [ "bstr", "gix-command", "gix-features", "gix-packetline", "gix-quote", "gix-sec", "gix-url", "thiserror 2.0.12", ] [[package]] name = "gix-traverse" version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bec70e53896586ef32a3efa7e4427b67308531ed186bb6120fb3eca0f0d61b4" dependencies = [ "bitflags", "gix-commitgraph", "gix-date", "gix-hash", "gix-hashtable", "gix-object", "gix-revwalk", "smallvec", "thiserror 2.0.12", ] [[package]] name = "gix-url" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29218c768b53dd8f116045d87fec05b294c731a4b2bdd257eeca2084cc150b13" dependencies = [ "bstr", "gix-features", "gix-path", "percent-encoding", "thiserror 2.0.12", "url", ] [[package]] name = "gix-utils" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff08f24e03ac8916c478c8419d7d3c33393da9bb41fa4c24455d5406aeefd35f" dependencies = [ "bstr", "fastrand", "unicode-normalization", ] [[package]] name = "gix-validate" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eaa01c3337d885617c0a42e92823922a2aea71f4caeace6fe87002bdcadbd90" dependencies = [ "bstr", "thiserror 2.0.12", ] [[package]] name = "gix-worktree" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6673512f7eaa57a6876adceca6978a501d6c6569a4f177767dc405f8b9778958" dependencies = [ "bstr", "gix-attributes", "gix-features", "gix-fs", "gix-glob", "gix-hash", "gix-ignore", "gix-index", "gix-object", "gix-path", "gix-validate", ] [[package]] name = "gix-worktree-state" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f5e199ad5af972086683bd31d640c82cb85885515bf86d86236c73ce575bf0" dependencies = [ "bstr", "gix-features", "gix-filter", "gix-fs", "gix-glob", "gix-hash", "gix-index", "gix-object", "gix-path", "gix-worktree", "io-close", "thiserror 2.0.12", ] [[package]] name = "gix-worktree-stream" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f61b0463c3cf4d07f2c72a10bdb03a2e4d70a9c26416c639346ad67456834485" dependencies = [ "gix-attributes", "gix-features", "gix-filter", "gix-fs", "gix-hash", "gix-object", "gix-path", "gix-traverse", "parking_lot", "thiserror 2.0.12", ] [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", "subtle", ] [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", ] [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ "digest", ] [[package]] name = "home" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "http" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-body" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", ] [[package]] name = "http-body-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", "http", "http-body", "pin-project-lite", ] [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "human_format" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3b1f728c459d27b12448862017b96ad4767b1ec2ec5e6434e99f1577f085b8" [[package]] name = "hyper" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", "futures-util", "http", "http-body", "httparse", "itoa", "pin-project-lite", "smallvec", "tokio", "want", ] [[package]] name = "hyper-rustls" version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http", "hyper", "hyper-util", "rustls", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", "webpki-roots", ] [[package]] name = "hyper-util" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" version = "0.1.62" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "icu_collections" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locid" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_locid_transform" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ "displaydoc", "icu_locid", "icu_locid_transform_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_locid_transform_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] name = "icu_normalizer" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "utf16_iter", "utf8_iter", "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] name = "icu_properties" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", "icu_locid_transform", "icu_properties_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_properties_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] name = "icu_provider" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_provider_macros" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "idea" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" dependencies = [ "cipher", ] [[package]] name = "idna" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "imara-diff" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17d34b7d42178945f775e84bc4c36dde7c1c6cdfea656d3354d009056f2bb3d2" dependencies = [ "hashbrown 0.15.2", ] [[package]] name = "indexmap" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown 0.15.2", ] [[package]] name = "inout" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding", "generic-array 0.14.7", ] [[package]] name = "io-close" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" dependencies = [ "libc", "winapi", ] [[package]] name = "ipnet" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "ipnetwork" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf370abdafd54d13e54a620e8c3e1145f28e46cc9d704bc6d94414559df41763" [[package]] name = "irc" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1be91867682072063576cac1279b7838f1cdfa87a346de8f8b1dc93cfb337b8" dependencies = [ "chrono", "futures-util", "irc-proto", "log", "parking_lot", "pin-project", "rustls-native-certs", "rustls-pemfile", "thiserror 1.0.69", "tokio", "tokio-rustls", "tokio-stream", "tokio-util", "webpki-roots", ] [[package]] name = "irc-proto" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "259640031f2f3e6d9fa632c7b314ba1eb5d1f88b3583bd2dd2e8f17155a19b5b" dependencies = [ "bytes", "thiserror 1.0.69", "tokio", "tokio-util", ] [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] [[package]] name = "itertools" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c04ef77ae73f3cf50510712722f0c4e8b46f5aaa1bf5ffad2ae213e6495e78e5" dependencies = [ "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde", "windows-sys 0.59.0", ] [[package]] name = "jiff" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", "serde", ] [[package]] name = "jiff-static" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "jiff-tzdb" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" [[package]] name = "jiff-tzdb-platform" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" dependencies = [ "jiff-tzdb", ] [[package]] name = "jobserver" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "kstring" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" dependencies = [ "static_assertions", ] [[package]] name = "lalrpop" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" dependencies = [ "ascii-canvas", "bit-set", "ena", "itertools 0.11.0", "lalrpop-util", "petgraph", "regex", "regex-syntax", "string_cache", "term", "tiny-keccak", "unicode-xid", "walkdir", ] [[package]] name = "lalrpop-util" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ "regex-automata", ] [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libbz2-rs-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0864a00c8d019e36216b69c2c4ce50b83b7bd966add3cf5ba554ec44f8bebcf5" [[package]] name = "libc" version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libloading" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", ] [[package]] name = "libm" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags", "libc", "redox_syscall", ] [[package]] name = "linux-raw-sys" version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "litemap" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "lock_api" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lru" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" dependencies = [ "hashbrown 0.15.2", ] [[package]] name = "lz4_flex" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" dependencies = [ "twox-hash", ] [[package]] name = "maybe-async" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", "digest", ] [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] [[package]] name = "memsec" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492" [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] [[package]] name = "mio" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] [[package]] name = "new_debug_unreachable" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] [[package]] name = "num-bigint-dig" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", "rand 0.8.5", "smallvec", "zeroize", ] [[package]] name = "num-format" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ "arrayvec", "itoa", ] [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "opaque-debug" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "p256" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ "ecdsa", "elliptic-curve", "primeorder", "sha2", ] [[package]] name = "p384" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" dependencies = [ "ecdsa", "elliptic-curve", "primeorder", "sha2", ] [[package]] name = "p521" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" dependencies = [ "base16ct", "ecdsa", "elliptic-curve", "primeorder", "rand_core 0.6.4", "sha2", ] [[package]] name = "parking_lot" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets 0.52.6", ] [[package]] name = "pem-rfc7468" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "phf_shared" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs1" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ "der", "pkcs8", "spki", ] [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", ] [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "pledge" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "252599417b7d9a43b7fdc63dd790b0848666a8910b2ebe1a25118309c3c981e5" dependencies = [ "libc", ] [[package]] name = "polyval" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", "opaque-debug", "universal-hash", ] [[package]] name = "portable-atomic" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "portable-atomic-util" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy 0.8.24", ] [[package]] name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "primeorder" version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ "elliptic-curve", ] [[package]] name = "proc-macro2" version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "prodash" version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee7ce24c980b976607e2d6ae4aae92827994d23fed71659c3ede3f92528b58b" dependencies = [ "bytesize", "human_format", "log", "parking_lot", ] [[package]] name = "quinn" version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" dependencies = [ "bytes", "cfg_aliases", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", "rustls", "socket2", "thiserror 2.0.12", "tokio", "tracing", "web-time", ] [[package]] name = "quinn-proto" version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" dependencies = [ "bytes", "getrandom 0.3.2", "rand 0.9.0", "ring", "rustc-hash 2.1.1", "rustls", "rustls-pki-types", "slab", "thiserror 2.0.12", "tinyvec", "tracing", "web-time", ] [[package]] name = "quinn-udp" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", "windows-sys 0.59.0", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_chacha 0.3.1", "rand_core 0.6.4", ] [[package]] name = "rand" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", "zerocopy 0.8.24", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core 0.6.4", ] [[package]] name = "rand_chacha" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core 0.9.3", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.15", ] [[package]] name = "rand_core" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.2", ] [[package]] name = "redox_syscall" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ "bitflags", ] [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", "thiserror 1.0.69", ] [[package]] name = "redox_users" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom 0.2.15", "libredox", "thiserror 2.0.12", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ "base64", "bytes", "futures-core", "futures-util", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", "once_cell", "percent-encoding", "pin-project-lite", "quinn", "rustls", "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", "tokio-socks", "tokio-util", "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", "webpki-roots", "windows-registry", ] [[package]] name = "rfc6979" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac", "subtle", ] [[package]] name = "ring" version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", "untrusted", "windows-sys 0.52.0", ] [[package]] name = "ripemd" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ "digest", ] [[package]] name = "rsa" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", "num-bigint-dig", "num-integer", "num-traits", "pkcs1", "pkcs8", "rand_core 0.6.4", "signature", "spki", "subtle", "zeroize", ] [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] [[package]] name = "rustix" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys 0.9.3", "windows-sys 0.59.0", ] [[package]] name = "rustls" version = "0.23.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", "security-framework", ] [[package]] name = "rustls-pemfile" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ "rustls-pki-types", ] [[package]] name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" dependencies = [ "web-time", ] [[package]] name = "rustls-webpki" version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "schannel" version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", ] [[package]] name = "security-framework" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "sequoia-openpgp" version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e858e4e9e48ff079cede92e1b45c942a5466ce9a4e3cc0c2a7e66586a718ef59" dependencies = [ "aes", "aes-gcm", "anyhow", "base64", "block-padding", "blowfish", "buffered-reader", "bzip2", "camellia", "cast5", "cfb-mode", "chrono", "cipher", "des", "digest", "dsa", "dyn-clone", "eax", "ecb", "ecdsa", "ed25519", "ed25519-dalek", "flate2", "getrandom 0.2.15", "idea", "idna", "lalrpop", "lalrpop-util", "lazy_static", "libc", "md-5", "memsec", "num-bigint-dig", "once_cell", "p256", "p384", "p521", "rand 0.8.5", "rand_core 0.6.4", "regex", "regex-syntax", "ripemd", "rsa", "sha1collisiondetection", "sha2", "thiserror 1.0.69", "twofish", "typenum", "x25519-dalek", "xxhash-rust", ] [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "sha1_smol" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha1collisiondetection" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f606421e4a6012877e893c399822a4ed4b089164c5969424e1b9d1e66e6964b" dependencies = [ "const-oid", "digest", "generic-array 1.2.0", ] [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "shell-words" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", ] [[package]] name = "signal-hook-registry" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core 0.6.4", ] [[package]] name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "socket2" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "string_cache" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "938d512196766101d333398efde81bc1f37b00cb42c2f8350e5df639f040bbbe" dependencies = [ "new_debug_unreachable", "parking_lot", "phf_shared", "precomputed-hash", ] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] name = "synstructure" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tempfile" version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ "fastrand", "getrandom 0.3.2", "once_cell", "rustix 1.0.3", "windows-sys 0.59.0", ] [[package]] name = "term" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", "winapi", ] [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl 2.0.12", ] [[package]] name = "thiserror-impl" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thiserror-impl" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tiny-keccak" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" dependencies = [ "crunchy", ] [[package]] name = "tinystr" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "tinyvec" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio-rustls" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls", "tokio", ] [[package]] name = "tokio-socks" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", "thiserror 1.0.69", "tokio", ] [[package]] name = "tokio-stream" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", "tokio", ] [[package]] name = "tokio-util" version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", ] [[package]] name = "toml" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "winnow 0.7.4", ] [[package]] name = "tower" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", "sync_wrapper", "tokio", "tower-layer", "tower-service", ] [[package]] name = "tower-layer" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twofish" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" dependencies = [ "cipher", ] [[package]] name = "twox-hash" version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "static_assertions", ] [[package]] name = "typenum" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "uluru" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da" dependencies = [ "arrayvec", ] [[package]] name = "unicode-bom" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", "subtle", ] [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] [[package]] name = "utf16_iter" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ "try-lock", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-streams" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] [[package]] name = "web-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "web-time" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "webpki-roots" version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" dependencies = [ "rustls-pki-types", ] [[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", "home", "once_cell", "rustix 0.38.44", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-link" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] name = "windows-registry" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", "windows-strings", "windows-targets 0.53.0", ] [[package]] name = "windows-result" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows-targets" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", "windows_i686_gnullvm 0.53.0", "windows_i686_msvc 0.53.0", "windows_x86_64_gnu 0.53.0", "windows_x86_64_gnullvm 0.53.0", "windows_x86_64_msvc 0.53.0", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" dependencies = [ "memchr", ] [[package]] name = "winnow" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] [[package]] name = "write16" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" [[package]] name = "writeable" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "x25519-dalek" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", "rand_core 0.6.4", "zeroize", ] [[package]] name = "xxhash-rust" version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yoke" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zerocopy" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive 0.7.35", ] [[package]] name = "zerocopy" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ "zerocopy-derive 0.8.24", ] [[package]] name = "zerocopy-derive" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerocopy-derive" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerofrom" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerovec" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", "syn", ] apt-swarm-0.5.1/Cargo.toml0000644000000070670000000000100107620ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "apt-swarm" version = "0.5.1" authors = ["kpcyrd "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "🥸 Experimental p2p gossip network for OpenPGP signature transparency 🥸" readme = "README.md" categories = ["command-line-utilities"] license = "GPL-3.0-or-later" repository = "https://github.com/kpcyrd/apt-swarm" [features] default = [ "git", "irc", ] git = [ "gix", "gix-object", ] [lib] name = "apt_swarm" path = "src/lib.rs" [[bin]] name = "apt-swarm" path = "src/main.rs" [[example]] name = "mkupdate" path = "examples/mkupdate.rs" [[example]] name = "p2p-launcher" path = "examples/p2p-launcher.rs" [dependencies.advisory-lock] version = "0.3.0" [dependencies.anyhow] version = "1.0.68" [dependencies.async-stream] version = "0.3" [dependencies.async-trait] version = "0.1.64" [dependencies.bstr] version = "1.2.0" features = ["serde"] [dependencies.bytes] version = "1.4.0" [dependencies.bzip2] version = "0.5.1" features = ["libbz2-rs-sys"] [dependencies.chrono] version = "0.4" features = [ "serde", "now", ] default-features = false [dependencies.clap] version = "4.0.32" features = [ "derive", "env", ] [dependencies.clap_complete] version = "4.0.7" [dependencies.colored] version = "3" [dependencies.dirs] version = "6" [dependencies.env_logger] version = "0.11" [dependencies.fastrand] version = "2" [dependencies.futures] version = "0.3.26" [dependencies.getrandom] version = "0.3" [dependencies.gix] version = "0.70" optional = true [dependencies.gix-object] version = "0.47" optional = true [dependencies.hex] version = "0.4.3" [dependencies.indexmap] version = "2" [dependencies.ipnetwork] version = "0.21" [dependencies.irc] version = "1" features = ["tls-rust"] optional = true default-features = false [dependencies.log] version = "0.4.17" [dependencies.lru] version = "0.13" [dependencies.lz4_flex] version = "0.11.3" [dependencies.memchr] version = "2.5.0" [dependencies.num-format] version = "0.4" [dependencies.reqwest] version = "0.12" features = [ "rustls-tls", "socks", "stream", ] default-features = false [dependencies.rustls] version = "0.23" default-features = false [dependencies.sequoia-openpgp] version = "1.21" features = [ "compression", "crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto", ] default-features = false [dependencies.serde] version = "1.0.152" features = ["derive"] [dependencies.serde_json] version = "1.0.92" [dependencies.sha2] version = "0.10.6" [dependencies.socket2] version = "0.5" [dependencies.tokio] version = "1.23.0" features = [ "macros", "rt-multi-thread", "io-util", "io-std", "fs", "process", "net", ] [dependencies.tokio-socks] version = "0.5.1" [dependencies.toml] version = "0.8" [dependencies.url] version = "2.5" [dev-dependencies.tempfile] version = "3.4.0" [target.'cfg(target_os = "openbsd")'.dependencies.pledge] version = "0.4.2" [lints.rust.unexpected_cfgs] level = "warn" priority = 0 check-cfg = ["cfg(fuzzing)"] apt-swarm-0.5.1/Cargo.toml.orig000064400000000000000000000041231046102023000144310ustar 00000000000000[package] name = "apt-swarm" version = "0.5.1" description = "🥸 Experimental p2p gossip network for OpenPGP signature transparency 🥸" authors = ["kpcyrd "] license = "GPL-3.0-or-later" repository = "https://github.com/kpcyrd/apt-swarm" categories = ["command-line-utilities"] edition = "2021" [workspace] members = ["fuzz"] # https://github.com/rust-fuzz/cargo-fuzz/issues/372 [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } [features] default = ["git", "irc"] git = ["gix", "gix-object"] [dependencies] advisory-lock = "0.3.0" anyhow = "1.0.68" async-stream = "0.3" async-trait = "0.1.64" bstr = { version = "1.2.0", features = ["serde"] } bytes = "1.4.0" # we don't use bzip2 directly, but enable the libbz2-rs-sys feature bzip2 = { version = "0.5.1", features = ["libbz2-rs-sys"] } chrono = { version = "0.4", default-features = false, features = ["serde", "now"] } clap = { version = "4.0.32", features = ["derive", "env"] } clap_complete = "4.0.7" colored = "3" dirs = "6" env_logger = "0.11" fastrand = "2" futures = "0.3.26" getrandom = "0.3" gix = { version = "0.70", optional = true } gix-object = { version = "0.47", optional = true } hex = "0.4.3" indexmap = "2" ipnetwork = "0.21" irc = { version = "1", optional = true, default-features = false, features = ["tls-rust"] } log = "0.4.17" lru = "0.13" lz4_flex = "0.11.3" memchr = "2.5.0" num-format = "0.4" reqwest = { version = "0.12", features = ["rustls-tls", "socks", "stream"], default-features = false } rustls = { version = "0.23", default-features = false } sequoia-openpgp = { version = "1.21", default-features = false, features = ["compression", "crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto"] } serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.92" sha2 = "0.10.6" socket2 = "0.5" tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread", "io-util", "io-std", "fs", "process", "net"] } tokio-socks = "0.5.1" toml = "0.8" url = "2.5" [target.'cfg(target_os = "openbsd")'.dependencies] pledge = "0.4.2" [dev-dependencies] tempfile = "3.4.0" apt-swarm-0.5.1/Dockerfile000064400000000000000000000016511046102023000135370ustar 00000000000000FROM rust:1-alpine3.21 as build ENV RUSTFLAGS="-C target-feature=-crt-static" RUN --mount=type=cache,target=/var/cache/apk ln -vs /var/cache/apk /etc/apk/cache && \ apk add clang-dev musl-dev && \ rm /etc/apk/cache WORKDIR /app COPY ./ /app RUN --mount=type=cache,target=/var/cache/buildkit \ CARGO_HOME=/var/cache/buildkit/cargo \ CARGO_TARGET_DIR=/var/cache/buildkit/target \ cargo build --release --locked && \ cp -v /var/cache/buildkit/target/release/apt-swarm . RUN strip apt-swarm FROM alpine:3.21 # install dependencies RUN --mount=type=cache,target=/var/cache/apk ln -vs /var/cache/apk /etc/apk/cache && \ apk add clang-libs crane libgcc && \ rm /etc/apk/cache && \ mkdir /data # copy the binary COPY --from=0 /app/apt-swarm /usr/bin COPY contrib/apt-swarm.conf /etc ARG UPDATE_CHECK_COMMIT= ENV UPDATE_CHECK_COMMIT=$UPDATE_CHECK_COMMIT ENV APT_SWARM_DATA_PATH=/data ENTRYPOINT ["apt-swarm"] apt-swarm-0.5.1/LICENSE000064400000000000000000001045061046102023000125550ustar 00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . apt-swarm-0.5.1/Makefile000064400000000000000000000003311046102023000131770ustar 00000000000000build: aarch64-unknown-linux-musl x86_64-unknown-linux-musl %-unknown-linux-musl: repro-env build -- sh -c ' \ RUSTFLAGS="-C strip=symbols" \ cargo build --target $@ --release' .PHONY: build *-unknown-linux-musl apt-swarm-0.5.1/README.md000064400000000000000000000133031046102023000130210ustar 00000000000000# apt-swarm An attempt to make a secure public p2p protocol that gossips about signed `InRelease` files to implement an update transparency log. ![Screenshot of a keyring along with the number of known signatures](.github/keyring-screenshot.png) ## Running a node Packaging status Install dependencies (Arch Linux): ``` pacman -S podman ``` Install dependencies (Debian/Ubuntu): ``` apt-get install podman catatonit ``` Create a systemd service at `/etc/systemd/system/apt-swarm.service`: ``` cat > /etc/systemd/system/apt-swarm.service </dev/null || true kubectl apply -f contrib/k8s.yaml -n apt-swarm ``` ## Configuring a repository to monitor To ascii armor the pgp key use this command: ``` sq packet armor < contrib/signal-desktop-keyring.gpg ``` Then write a configuration like this: ```toml [[repository]] urls = ["https://updates.signal.org/desktop/apt/dists/xenial/InRelease"] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 N+O606NOXLwcmq5KZL0g =zyVo -----END PGP PUBLIC KEY BLOCK----- """ ``` ## Status This project is experimental. PGP is complicated and p2p security is difficult, running this program may use up a lot of disk space on your computer if somebody finds a way to bypass the vandalism protection. There's also the risk of a false-negative, the pgp implementation used by apt-get may consider a signature as valid that we consider invalid. If apt-swarm considers the signature as invalid it won't accept this release into the network and it won't appear in your audit logs. apt-swarm can't detect network-partitioning attacks and doesn't intend to. ## Trivia As part of this project, a [bug causing the pgp parser to crash](https://gitlab.com/sequoia-pgp/sequoia/-/issues/1005) was identified in Sequoia OpenPGP in 2023 through fuzzing. A bug that could in some cases lead to [silent data loss](https://github.com/tokio-rs/tokio/issues/7174) was identified in tokio in 2025. ## Funding [![](.github/lolgpt.png)](https://github.com/sponsors/kpcyrd) ## License `GPL-3.0-or-later` apt-swarm-0.5.1/contrib/apt-swarm.conf000064400000000000000000004020611046102023000157670ustar 00000000000000[[repository]] urls = [ "https://deb.debian.org/debian/dists/bookworm/InRelease", { content="https://deb.debian.org/debian/dists/bookworm/Release", sig="https://deb.debian.org/debian/dists/bookworm/Release.gpg" }, "https://deb.debian.org/debian-security/dists/bullseye-security/InRelease", { content="https://deb.debian.org/debian-security/dists/bullseye-security/Release", sig="https://deb.debian.org/debian-security/dists/bullseye-security/Release.gpg" }, "https://deb.debian.org/debian/dists/bullseye-updates/InRelease", { content="https://deb.debian.org/debian/dists/bullseye-updates/Release", sig="https://deb.debian.org/debian/dists/bullseye-updates/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 gPHbwrvsY2t9BCsT+PgnSn9biobwX7bDDg== =55bs -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://deb.debian.org/debian/dists/bullseye/InRelease", { content="https://deb.debian.org/debian/dists/bullseye/Release", sig="https://deb.debian.org/debian/dists/bullseye/Release.gpg" }, "https://deb.debian.org/debian-security/dists/bullseye-security/InRelease", { content="https://deb.debian.org/debian-security/dists/bullseye-security/Release", sig="https://deb.debian.org/debian-security/dists/bullseye-security/Release.gpg" }, "https://deb.debian.org/debian/dists/bullseye-updates/InRelease", { content="https://deb.debian.org/debian/dists/bullseye-updates/Release", sig="https://deb.debian.org/debian/dists/bullseye-updates/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 =h7gb -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://deb.debian.org/debian/dists/buster/InRelease", { content="https://deb.debian.org/debian/dists/buster/Release", sig="https://deb.debian.org/debian/dists/buster/Release.gpg" }, "https://deb.debian.org/debian-security/dists/buster/updates/InRelease", { content="https://deb.debian.org/debian-security/dists/buster/updates/Release", sig="https://deb.debian.org/debian-security/dists/buster/updates/Release.gpg" }, "https://deb.debian.org/debian/dists/buster-updates/InRelease", { content="https://deb.debian.org/debian/dists/buster-updates/Release", sig="https://deb.debian.org/debian/dists/buster-updates/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 lYnY6/AhjXn308njCW0p4horBjpIYl/Uy28/Ln8= =usQh -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 xhTUxIOrOKuMKwyZqfAeAmFLVONcT2HClEFpgn3myawQNO0gsIkCTgQfAQoAOBYh BG7W9ctfpvsvRgroju2g0jiK4iupBQJZIzGlFwyAATCZEb6pZtBhMFMEVxG05f8V sP2CAgcAAAoJEO2g0jiK4iupW14P/0NjlEQWA3W7lpzAoWcEgStiCLlk0EP0wMxP M5Vo1WrnUemLTfrI4rIs17Ocs6opX9nEYPxfIoVGxqqNqvuj3Hej5JnglPctbJ1+ ttNXfuB6yqsa/wANPOC5qAVy+u4MY1ljyKSTCtc9kwc+K2Vjr/TrRDDq/o2xrmjC 4JwP3IpPr2dolGsBUQ3+HWAeLgBhqH3e4sYL5DLQgav+2cv39ez9jGp4FMZ0nztk y+hiQ2zHSyYzTzYzPc3775H7LMnH39b64DO0MfREJb+3Wbpj3hCBNn8zdSE807Tx 5XeXdQbIynXafFU5CR3AJbCuzs8RjdMXpeVlvad0OOStbjFDNpGmeKXgbD0A43dd CUj6GKAlWLX7J7pN2OKkQmewZWgRmNEXIAaorUR3GXClORMzeUTYopQLazHIkXWH 1VWO4Yqqew7K3LkCF2eMA8wj02fjyMtb+8I+xoj4wEHROSDQGGf90fcHgfoPWZgv jgvps2egpO19X8zMTVvZW8VoNDeiaeMSlLLEVBhMHYwiB3MpQYXfnkfLjhKmhvil 86Jgt0F/CTzTRdd8JjtwOsIC6TtYcZPsZGyDFBvx/K8lOcN2t5p5VZMnFQm0aCV2 d6r00nD5HexDPBMq3Lvy3vm5zmwJxM072SU69k5qEHCKERYyfyuNrhA4VxOm9Uqn DcDIlwpetFBEZWJpYW4gU2VjdXJpdHkgQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmlu ZyBLZXkgKDkvc3RyZXRjaCkgPGZ0cG1hc3RlckBkZWJpYW4ub3JnPokCVAQTAQoA PhYhBG7W9ctfpvsvRgroju2g0jiK4iupBQJZIzDxAhsDBQkPCZwABQsJCAcDBRUK CQgLBRYCAwEAAh4BAheAAAoJEO2g0jiK4iupWUEP/Az929HCCGTGBZajoEfN2FNq OWZ4pdKN6a4pPwnY2Cg7FeKqsXcYG2EM+Iuea2MK2IIlA2n5LYr6VIjLWfQJkkRo eZwoQNTcb7fE5nBF/mUhqYovm4mSbDgmL/c5EVk7iqL7YDUE+fYWyIbGipIPKVHv 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 NKmyBJ6vM2T7+nah6/vfHNbs0H9t4g== =MT7k -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://download.docker.com/linux/ubuntu/dists/jammy/InRelease", #{ content="https://download.docker.com/linux/ubuntu/dists/jammy/Release", sig="https://download.docker.com/linux/ubuntu/dists/jammy/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 YT90qFF93M3v01BbxP+EIY2/9tiIPbrd =0YYh -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://apt.vulns.xyz/dists/stable/InRelease", { content="https://apt.vulns.xyz/dists/stable/Release", sig="https://apt.vulns.xyz/dists/stable/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 =1yYd -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://updates.signal.org/desktop/apt/dists/xenial/InRelease", { content="https://updates.signal.org/desktop/apt/dists/xenial/Release", sig="https://updates.signal.org/desktop/apt/dists/xenial/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFjlSicBEACgho//0EzxuvuCn01LwFqGAgwPKcSSl4L+AWws5/YbsZZvmTBk ggIiVOCIMh+d3cmGu5W3ydaeUbWbFGNsxO44EB5YBZcuLa5EzRKbNPVaOXKXmhp+ w0mEbkoKbF+3mz3lifwBnzcBpukyJDgcJSq8cXfq5JsDPR1KAL6ph/kwKeiDNg+8 oFgqfboukK56yPTYc9iM8hkTFdx9L6JCJaZGaDMfihoQm2caKAmqc+TlpgtKbBL0 t5hrzDpCPpJvCddu1NRysTcqfACSSocvoqY0dlbNPMN8j04LH8hcKGFipuLdI8qx BFqlMIQJCVJhr05E8rEsI4nYEyG44YoPopTFLuQa+wewZsQkLwcfYeCecU1KxlpE OI3xRtALJjA/C/AzUXVXsWn7Xpcble8i3CKkm5LgX5zvR6OxTbmBUmpNgKQiyxD6 TrP3uADm+0P6e8sJQtA7DlxZLA6HuSi+SQ2WNcuyLL3Q/lJE0qBRWVJ08nI9vvxR vAs20LKxq+D1NDhZ2jfG2+5agY661fkx66CZNFdz5OgxJih1UXlwiHpn6qhP7Rub OJ54CFb+EwyzDVVKj3EyIZ1FeN/0I8a0WZV6+Y/p08DsDLcKgqcDtK01ydWYP0tA o1S2Z7Jsgya50W7ZuP/VkobDqhOmE0HDPggX3zEpXrZKuMnRAcz6Bgi6lwARAQAB tDFPcGVuIFdoaXNwZXIgU3lzdGVtcyA8c3VwcG9ydEB3aGlzcGVyc3lzdGVtcy5v cmc+iQI3BBMBCgAhBQJY5UonAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJ ENmAoXRX9vsGU00P/RBPPc5qx1EljTW3nnTtgugORrJhYl1CxNvrohVovAF4oP1b UIGT5/3FoDsxJHSEIvorPFSaG2+3CBhMB1k950Ig2c2n+PTnNk6D0YIUbbEI0KTX nLbCskdpy/+ICiaLfJZMe11wcQpkoNbG587JdQwnGegbQoo580CTSsYMdnvGzC8A l1F7r37RVZToJMGgfMKK3oz8xIDXqOe5oiiKcV36tZ5V/PCDAu0hXYBRchtqHlHP cKWeRTb1aDkbQ7SPlJ2bSvUjFdB6KahlSGJl3nIU5zAH2LA/tUQY16Z1QaJmfkEb RY61B/LPv1TaA1SIUW32ej0NmeF09Ze4Cggdkacxv6E+CaBVbz5rLh6m91acBibm pJdGWdZyQU90wYFRbSsqdDNB+0DvJy6AUg4e5f79JYDWT/Szdr0TLKmdPXOxa1Mb i34UebYI7WF7q22e7AphpO/JbHcD+N6yYtN6FkUAmJskGkkgYzsM/G8OEbBRS7A+ eg3+NdQRFhKa7D7nIuufXDOTMUUkUqNYLC+qvZVPJrWnK9ZsGKsP0EUZTfEGkmEN UzmASxyMMe6JHmm5Alk4evJeQ31U5jy7ntZSWEV1pSGmSEJLRNJtycciFJpsEp/p LkL0iFb30R9bHBp6cg7gjXbqZ9ZpEsxtZMBuqS70ZZyQdu2yGDQCBk7eLKCjuQIN BFjlSicBEACsxCLVUE7UuxsEjNblTpSEysoTD6ojc2nWP/eCiII5g6SwA/tQKiQI ZcGZsTZB9kTbCw4T3hVEmzPl6u2G6sY9Kh1NHKMR3jXvMC+FHODhOGyAOPERjHCJ g20XF2/Gg462iW8e3lS7CQBzbplUCW/oMajj2Qkc61NLtxxzsssXjCKExub2HxCQ AYtenuDtLU73G75BoghWJ19dIkodnEI0/fzccsgiP5xeVgmkWJPo9xKJtrBS5gcS s7yaGY9YYo71RFzkpJpeAeLrJJqt+2KqH1u0EJUbs8YVGXKlnYeSNisg4OaRsldW JmDDCD5WUdFq2LNdVisfwirgjmwYpLrzVMbmzPvdmxQ1NYzJsX4ARSL/wuKCvEub gh1AR5oV7mUEA9I3KRH0TIDOnH4nGG3kqArzrV2E1WtnNzFII0IN9/48xY7Vkxs7 Oil+E+wCpzUv/tF4ALx5TAXoPd66ddEOxzDrtBpEzsouszt7uUyncyT3X6ip5l9f mI4uxbsjwkLVfd1WpD1uvp869oyx6wtHluswr1VY/cbnHO8J6J35JVMhYQdMOaTZ rX6npe/YOHJ4a7YzLMfdrxyzK1wq5xu/9LgclMTdIhAKvnaXBg41jsid5n0GdIeW ek8WAVNyvuvoTwm3GG6+/pkTwu0J79lAMD1mhJsuSca6SFNgYnd+PQARAQABiQIf BBgBCgAJBQJY5UonAhsMAAoJENmAoXRX9vsGvRgQAJ4tWnK2TncCpu5nTCxYMXjW LuvwORq8EBWczHS6SjLdwmSVKGKSYtl2n6nCkloVY6tONMoiCWmtcq7SJMJoyZw3 XIf82Z39tzn/conjQcP0aIOFzww1XG7YiaTAhsDZ62kchukI52jUYm2w8cTZMEZB oIwIWBpmLlyaDhjIM5neY5RuL7IbIpS/fdk2lwfAwcNq6z/ri2E5RWl3AEINdLUO gAiVMagNJaJ+ap7kMcwOLoI2GD84mmbtDWemdUZ3HnqLHv0mb1djsWL6LwjCuOgK l2GDrWCh18mE+9mVB1Lo7jzYXNSHXQP6FlDE6FhGO1nNBs2IJzDvmewpnO+a/0pw dCerATHWtrCKwMOHrbGLSiTKEjnNt/74gKjXxdFKQkpaEfMFCeiAOFP93tKjRRhP 5wf1JHBZ1r1+pgfZlS5F20XnM2+f/K1dWmgh+4Grx8pEHGQGLP+A22O7iWjg9pS+ LD3yikgyGGyQxgcN3sJBQ4yxakOUDZiljm3uNyklUMCiMjTvT/F02PalQMapvA5w 7Gwg5mSI8NDs3RtiG1rKl9Ytpdq7uHaStlHwGXBVfvayDDKnlpmndee2GBiU/hc2 ZsYHzEWKXME/ru6EZofUFxeVdev5+9ztYJBBZCGMug5Xp3Gxh/9JUWi6F1+9qAyz N+O606NOXLwcmq5KZL0g =zyVo -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://repo.steampowered.com/steam/dists/stable/InRelease", { content="https://repo.steampowered.com/steam/dists/stable/Release", sig="https://repo.steampowered.com/steam/dists/stable/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 r9mb/lqwAgAD =zYXg -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "http://repository.spotify.com/dists/stable/InRelease", { content="http://repository.spotify.com/dists/stable/Release", sig="http://repository.spotify.com/dists/stable/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGNyEIMBEADYyd1k7ItqwpSVEzmwWd7uk0MgUlByGJ/8utgxeEX9QrYiResE uQRun/7WC0mTN70UFUBBLHpDTN8NdN2ODNrOku6WxdYHMxBdCctiQTfctGY+gBUD Li71mxu+hjhsZ3Nczqj7ySssXKHLNA5qqGpOHbr3dzOpbft0c2l3e/UCDSDHiMJL DOZG5VI+aOfNOlxPxgMdkTFlZtz+EoouNyA5uqv7j2yjzdmpJRGqLK+l8knH/kmS 2ETUFds6XUYHiOikK51A7FXOA6v7sV0cFBQ5pt/jDhEQmxd5KECl5bfc3IzqCHui mASNagm8xovHQnTE4QfEIdXHGTCqX0hTFQc7WGdH7b57nrA9MV1Lizin31VeF0iU AkzmcM5b5PvmFwOIEEh9PvIh7cv3xXI7u9wuG8+lNZU1xYWsw4z0ZLDu/mwKatB8 pertdrJR6jujB6vQ/hStP+lCoROacf6spGRcHtUVAFWUfoVpRqi4RIjXnxYlQZ7n QVUbe74yXVuPXpfNZnyBAvXQ2UC8T6b/m5gdgHGA60To6PQTj+bh/1CGvZYoqmcy EZwCAmLJ/1xfPRb3fj8BmQsoloQk3QipY4I5L05pnop9E9zwMabiVtg/cPOISan0 BQmP9F2xI3UAUIzvwZyNyVCFb0SCkRkF6jGJMX6waoySd6ZluNN66j3E9wARAQAB tDdTcG90aWZ5IFB1YmxpYyBSZXBvc2l0b3J5IFNpZ25pbmcgS2V5IDx0dXhAc3Bv dGlmeS5jb20+iQJUBBMBCgA+FiEE4nQJ9R0bZjN/LS9Bejp2L6/UpR8FAmNyEIMC GwMFCQJRQwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQejp2L6/UpR/0Yg/9 EsqCXY4IlMrQLooJx/hYXOyfkiN7UqVGkRkJ+fQR16y7QBJUL7u4jgDkMkbXxYmz J9qydMguR9Q9x45xa49SQETJoWHGKZ2GEAHiGlTSaJKNV4yASt59cHrrckYMxxGa Ad+2N9lE53IrB+LQLNMWEgk/1vgt5H6UFfQIRodkJ9MU4w/Q3MthB3jZrOAt1E2D t4DIwl9yvX2wB1vylwWF4Qkt5Ysu+/Ui4vsOevoJmQR0RypDiOt98E+W+oKnD1iP SmQolJhkMFlcQarpO7wjv1NQUaCd0t4jPuNWVRvsWIPO3hiC8Aq+ADIGpIH8k1qK e9j+wO/yl9VMh63fkRcZA5tYhKKLaVaQIjaqqBj4TPmKVNoCWqigmrS++oWvcepm muBJmwo/pPrRQT0d6GROdY0sKoT42Tw+MWOFp/ou0duCekaoGMWbKKh2IXDWYwVI V3NkzqwBog/ZurYdiriFGo8KR86Wsgjbs40Sk6zkvdvC+DyBBojrHbNEn0S2M1to cuwNiwB9B2Uo3t25CjuUko4m3omMJQEyqTe4YAfJIuhE0ACMvuOKQazFVVrw83oG YCLjJaNDsYUvLub9kYWMpMP5ErmMgpBjUnVihzS9eLF0ZPtXEgmqJwCucBXaT2Rz vVH6BQchKqQU5D3F0elkoDaKaLdIqvvpJbw+juf2uEE= =fd7f -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ { content="https://static.rust-lang.org/dist/channel-rust-stable.toml", sig="https://static.rust-lang.org/dist/channel-rust-stable.toml.asc" }, { content="https://static.rust-lang.org/dist/channel-rust-beta.toml", sig="https://static.rust-lang.org/dist/channel-rust-beta.toml.asc" }, { content="https://static.rust-lang.org/dist/channel-rust-nightly.toml", sig="https://static.rust-lang.org/dist/channel-rust-nightly.toml.asc" }, ] # Rust Language (Tag and Release Signing Key) keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 Mve696B5tlHyc1KxjHR6w9GRsh4= =5FXw -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://deb.torproject.org/torproject.org/dists/stable/InRelease", { content="https://deb.torproject.org/torproject.org/dists/stable/Release", sig="https://deb.torproject.org/torproject.org/dists/stable/Release.gpg" }, "https://deb.torproject.org/torproject.org/dists/testing/InRelease", { content="https://deb.torproject.org/torproject.org/dists/testing/Release", sig="https://deb.torproject.org/torproject.org/dists/testing/Release.gpg" }, "https://deb.torproject.org/torproject.org/dists/unstable/InRelease", { content="https://deb.torproject.org/torproject.org/dists/unstable/Release", sig="https://deb.torproject.org/torproject.org/dists/unstable/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 =S302 -----END PGP PUBLIC KEY BLOCK----- """ [[repository]] urls = [ "https://packages.sury.org/php/dists/bookworm/InRelease", { content="https://packages.sury.org/php/dists/bookworm/Release", sig="https://packages.sury.org/php/dists/bookworm/Release.gpg" }, "https://packages.sury.org/php/dists/bullseye/InRelease", { content="https://packages.sury.org/php/dists/bullseye/Release", sig="https://packages.sury.org/php/dists/bullseye/Release.gpg" }, ] keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- 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 =gNGr -----END PGP PUBLIC KEY BLOCK----- """ apt-swarm-0.5.1/contrib/debian-archive-bullseye-automatic.gpg000064400000000000000000000207741046102023000223620ustar 00000000000000 ` 2HBRs|c!d0*!vpB]8ĒIx\lt}~&=a X<'2b$YnNT*\(K{8m_юH˃qvdm/(o'-bQm+e6L9ɽEY|c'ӟ:3ĩq,~?N 8!>̖s{y6` vJPH?7"Rd s{y6,C.3 :$ cD9j^d("l_n o' jG*]óנƷ~"+m>ʷ 1@0yWRI+6iEl.Q b5t+!IU}V[kΕ]|)Rd30g%ȷMO&W!'YBFAdG׹EfbtqoҒH:P==Av q6enyu ׁÓ(ЊVeP?7L|e2 yY z"tHI/"K%9h5HPTlC_Y:=z"V%!̏ č ho3LN U8D6 + Zi̖s{y6` Aܕ[ٺn[%% s{y6i J3]@4ъGT(W)k^O4hx.4Bؾ@4P;S^Z+->r vїUpcnex';\^x@9N(&K.ڟZ(fm<U_‚ŽUˢv#46nKq0q2ȵ ya.47հЂ8S^_˗a8ú&DVoN߱E!2ߥ-\R'ވR>.;_gռP_"dndK MpϮLf< HDCWl)r } xQ2%{^k&HLO?d-}f眸GɋIU8>𕙍J&h|D! gh@:ˏ}Ȁu4˘XeHx/{' YJը"U,uV.xU nN 8!>̖s{y6` =AcZ΍n p s{y6Bg H QsJa8țAp,wӨprK7 $c^{gG{Bho){pbz W"!&UںL[ӉCG()6cӁ^dF;ZlrKƞ>N;Y0< yѸBqͨ!Glq@Kyײ}*~;yLaq//}/`QҵQtsBGvgnKX~8E̖s{y6` 0fa0SW s{y67.7̈pZTe(Eszm!,0)bėO`l-j4{uv6"o#meJ^U╳6Ko0 ,ҁ iSڣዮL]NQ 5ݘEYF.v5gh#?I8l4d% yī΂:QGD0HhHZ;^vԌi<0t&7ܰӔd;#%dN$)GsӒPpct ^vർ62_dC$˓ʾ8ru3g`-0A^w)ƌɍDK`9>ұς26ip^fɱ>j\bBm$%:I SY3,%A&Y 03,WD'"2HO؈N,@ .}3u=Dk#.qAC_$rMkUs׆. q@7=RωN 8!>̖s{y6` Oj3R?Ygp_ s{y6,+- BdGy.JNzDsuӅij3.uSFy_%3?\ CKm֘lMBb'8`q=5-!EwMZ*Tш9%ӂgc(Igo뀠1]?\ GK׵z"5L2=K$+gvhIZr_7e9U0c8NVXvLye&G) ެvoPQÒ&X!ڛF+^WZ+7;aqC@.>iMOyil ܿ2fI,M; sϰE;L-^cYe"^S8ED8m v$PVz(OZ2D/ݤ4KWd NSL$"ȫ27l1zɜ$-54(ʝf-F6V#WQ%@TPW &Nxa@"tVIDebian Archive Automatic Signing Key (11/bullseye) T >!>̖s{y6`       s{y6o wJs0إ,œuI 'oUX2i.*Ȏr\a@8{c?U&B Q{ǫiE.dql0 `;Xq D T|8 R$.*4{ȹ 2 ֳf:uCYM9j&jT@\BN\X~?@Rv~??şħuEhTRBKЩrOi7)x_p 'aGOi]7|##67ގ! mc3re2gtH2& bˮZ#s! %/.cgP)/}!NU}3!R3 | Ao/]πjNZ2V9\L«3@p+~@w3^4v~\+{'s7-i2cO!-TF1 3 !X#a0<` 0<4jo'`8T0s# 2ݚ/zpS[fza9{Vv7Cd7yS)M%\Ué|~%j#SN&'Q.~L}muxX3uF^L6TO[ A`c鏂=r0+}zlƿN&~dI̼HSE1%!)Sj؜2欆{㌎a'pUYwzo"qdt?{6$zo4t4A9}nh=1)],~ctu4& H kvVU )l9Vff%"E^y(*h &{gr sbeI%/#WL*!hXz`eS2 H W=y5;hRVc]J$'U9!JmTeRPU}U(%d>pyYO5Cv3 !^a&]z#Mpʩm` MpʩmRgB4hst^$Gm^\Gs۸I 8buD`/üMsaeHC:Rg1("MA{PQt1_YԠ5ы"~ YC: SuRU#HoJ㰂HEY;j»*oo_CL1v^=y30tmqn{0$~3FLD}xQ7j:PyL*k,5~NsDGuHONpQ zyLM(Pשq4`z΁*]?xvP#k6ErׂfG6ib:w#[=tN;R.=ȯBiB/#J{o ĹI{EW ȒSIxMC֕".$|Rd=_xkbnto&|b@,P)Ҿd/^b9\ްc_~l1E )BO'apm=Nf+(3 !S R/2iIJ\]` IJ\]a~uSH!0sн $Լ.`*C 4@+ Քspr]uc3HChܩ#A)sLu&lvؔ|fd!ؾO47ݥCpVtcv:΢h^+K ܀E|QYRWM;"T+M8䲣y6A_'TY+EӲ>pc=|`W#Z PX:SJ$,*abP{#+`G`I=z*,IOeւwU#6cB\l6 /6ln Mkl$yXQi xZkI|%-wF2{. F#n!;Mcs7,-ϔK6J(c}H%\?K~vXx|g1ZHUX{:l~43U ?!Aܕ[ٺn[%%`2!http://gpg.ganneff.de/policy.txt [%%ħwq79O'H!uSGtu(Rֳ1LvR4,B8JmtMEL#=V>NY&HA)X|g' :'"~M*>~DŞK1Vq.u: NU$14WvdDXA/8Kce`RYdm ࠳yAEAx$j&ƇQÕaY]^G&[D0+?ˣ{$wsO ./K>߁*LjOgXT4]s'Qe3xMUa(s-eze@s0.sDg@3pq -|ahn$@Њ.g) ي :/5SuZca$GZNB6y4 ?Cv~A0xYw!oC6*Q#jw.;?-^ ` rg*ĊMھE4U׏d 4Y7("qE *z`lrL!$fêҰcǭ8z%"& ydTT(r6[]䑶%HtKL mUYEiҞpw {__NRRl M'~DEPf.!M лA/7"tdAhXcvXm {1>V]%t(͔WT7^WS}WRM洛cҭx-ss)0@Oyq( Sa*FVj]`5"{{(4szs$Wekz+Ĺ"ߵFz)5#LrG?WH~36BuX@: !i47H9qIS".INQ_Ò$Oz2p~S>C/|qMcPYfCW^, fymu.ڱǽa7Mr &!>̖s{y6`   @ s{y6t  !#hʭ'@M8o` @M8omn=rxa:@yi (؎ժ (ױ3"La$%2q =S*`Ϳ~]ɾ!3xA2'H^ĿKz((ՇUi2l"RߝB}ROYIa55XS0.%:& 9qon5&l@a_sZEyShLX$$>$\P\і5!"?nÒdS\=U/OyO`+?FV9C@X"sǠFka74Yke&tNss՜quW:5œ0$(q&F*nT Jj_K :ǻREelm+m7.%g=A@v qJmcqW('67"/;!!h"wvZ 6W6,UK2Ch41h1j?Ztāz,ݻx^TɲSW#}8ZXn4ne*PP& E )qtnzy.mH^ ȏ2W~ ܌cHs w-ٷ1WIthۣQjol}`Nʼn9 3L4CVOM/^v2AXD9[usS$gWppXWZĊLqw¯ SQ5ҲL;!8]Io2 Sqjɛʑg:uPIQuB 0_(J&cBp@T WV sa3uQCدfF g5;z:9y𒥾W 1cyK7MiTik^cѻꄆmBW-I)R B%%+tԓm&Vjڹ@E Vd"ʗBK;8D oZ%R|, fBV%apt-swarm-0.5.1/contrib/debian-archive-bullseye-security-automatic.gpg000064400000000000000000000210051046102023000242130ustar 00000000000000 `oAQ-ZX^h>>ՕR~̘Fy8V:6!=lƕ; {Zu\fg:bc*8wʳTm s`.zf͓!1+GYIl w v9GZ$.RwyLRQTon;# _6RrX$|./.Wy$"=|່00>3e4 (7ZLj`KZ(frO֦+R h>Wi~IP|m :ݖ_r !7Sۈ(:LNk8oB:U(}fR+Γ$Q'g8Hl6/[t^"^Wn:zBLJȫ@덛Y@J{p͞0eoB|{ޡS1BFL6Ic|Ȗ̻x'U&f9@N!d0n ~H[55"|IkN 8!S R/2iIJ\]` vJPH?7"Rd IJ\]gE)EPPveBGl5E0;3'6kݜ6a& jd?l¾Q=wKPzS hA~NpeKTvJUaz0k$caBax,A8 Ll„6U Eۭ/RUeTi}>o(mONz-!)1BOݤ tHV4iȭS,J_i`yl:HRԺQt߿B-c}8F#;{?ytD~X<)TFMũAK n?r30j/<މ l 0r)MISTƬҀp{I*_~JC1"y&a$s#K~g䛆Z^@r׼eZlWyT-Kp-Ξ_O#a˃R2DD~U2N 8!S R/2iIJ\]` Aܕ[ٺn[%% IJ\];ԴYͅ4/4cq=AS-87<"LRM{1NY@ڧ?qԲ]Fjg42Uɐ|f5#mXI]KH{t)j`Aݠ #{52F Ld_xyw^D4r!or@_+k)7}k*9&f#)Lb ?E2+z>QbA!mbi3#Z3G7L s5( (c*3f?<=ՇZ\LBRg3ð(pR zu| uǙoވ%,dCn |HJDy'4Եyn^ɂ vS9S+Oy\!+o c.x}y5j|'Q&d2S}=THd4 ?F) >>S)-)Ǻmvgż@ց(10Nq`]|hrx.!4"N 8!S R/2iIJ\]` =AcZ΍n p IJ\]|(mWCHuȕR@-ZCjK`!&~qVơaq^hC~~\+0[qw!b"wf<JvSOO{˽6Bo=-/ظ2+wY̠8AVuP`М™%p'penC@]t`oF%+yGhM P%~MLͨxO^$KC fBGd?3>l-0ߠّSOyqQ :ˊْNzhBt&-S;&p[T&;אwYt/Rw@8G_cu\!/o{SI乐&3&TJS3N'%A-,F* t("1U'} sz^CQ77:${@VM0a2jɓ^J[;"W]WN 8!S R/2iIJ\]` 0fa0SW IJ\]t/^/eaD.\a7%+1|@KA] Fl:mmąruǼ~|O2zLziUP~$FvVs+ gg*TBzj2{A$P ߞuawX@Dk\6̾3lmbZיýiv4HQ'w9}<ƏjE?>D5Hw$[V/Q:/&{arak >LN 8!S R/2iIJ\]` Oj3R?Ygp_ IJ\]&pq>i~qo!nRy>"]׎rYohTƘ$&GΡJMGk@$LP1 :t[r`%=(A}0߬8KѮ@u: +@WcUJIyqli++ÎlQ?}" lU" #zE_]4:r.J )c1ǭZXt'f#MTQ#zJKԶUXB2K'"@G9%' ^c6?Α%;kl:=ynKY-*(wo8U\h-!UbkKMז!L̫ikC,yxR]=0(; jc^$4DMe42cq%6L&8!FE`m$CC@KuF0 S;+Sw*+΋: IgqN>FG 2^(I-E;غ5}ᣯ6\RDebian Security Archive Automatic Signing Key (11/bullseye) T >!S R/2iIJ\]`      IJ\]t7JvpIiw ^h@\PwwW_|2R#˸O-02sǝhQ1<Zv=Gy xzW"-DF>#jC*4w^[ِ}cBCv d'ƶ(c1ӻvMK"P0>ļ&â/;/1,&xRqٔӸγwGxԠiRC~?pX{Vn}x3Z. &T&]%E;4 m\vXXAXet2c#º-̧j_oBmaT+g5S_;'0vʌcdŢ4z\VzxV&Q8hQ}\ti}'RyeZlыA)tnDKh6 G|rE0ͳO=|/!FgUbGډ3 !X#a0<` 0<QvVh'zʉāt^4}G ֑0k>UZ_& !P28ㆇ _9m!:w=l1¶A.Cz+ bvg ihOY~S̼3PJEs"Y~ub۽Dz]ZN'g/M`|mJf$:R[V֘h1#mĀ&n)Υ[&h*)e·ݖ:;ڜؙϨױg=ZP{'U$:-{#ϥ qEM0eFPL\/tQ&ܕgU5P /& 495S¯8OX#_xAm Ty^>q^O*+x/_[!(.}l~4&;3mY{TOR+,{&3 !>̖s{y6` s{y6+ZÄ[jzWE CUBbe`[A1ҋ2g$O:x{|p[&D/WzhLI1nE .Ȗwz@݅ ux ~H ZُeM?DPjKMz0,QkLz!M%2SE.1nаKՆMz9}M6*$C k71{\_ղ]7T1b[||]JC cg5P'o<ɩDrA[ o *e??fBmAeH0lP-ርG*DA3w|t/WC7!p)L\5Y캭@uؐi,lj`;y-w,% -1PDKch76E<:6Ή3 !^a&]z#Mpʩm` MpʩmUQ/ ݏ78V {2axŮ|O"%$Ku ־fxdJS&oaքhLxp[=歽~p0a˓ϊ8 Y:\T C/L5#؂4UyS/+*ի;oo_`T7F߯!&:4g--O9f =KnC4ΐ!_\I5m ;?ɣէd6%>M31YC_6:놩%6tH7sjMU8qӑ!'34nlm*0O[odO1vgB:e~}רu%4=ڎT%xx( %d'r_'t=pߎ&aaa:H.|jQSSehq,(=e90o&FrʟW&dvɾb8/Mg//V%!svaePYPzԎec /T?2dy)- Zɉ3 !vJPH?7"Rd`" 7"RdTD@40ǂ\DpQc썴_3YW^h dX^梯}Xp~JZ"F ~I wĞ'+55'J,1ݡ:! Wgz*Dha鞔 6>8]3P@QP%k4RP9#]5cqFjmH&yUU:E3k\2_}~=WR'bsC:{"$i 1Fn*mEw_W&SU ?!Aܕ[ٺn[%%`2!http://gpg.ganneff.de/policy.txt [%%tgB 镸: LP#!{%zFnh}跗$vv\R%1b\cUjvfzv^u{p5`YKΙϫa,D _= 5<_I6lq Rd?uGsQod:]x/a+uxƂ L5 &s9syI ļIJiʵZt%C4x8,ӤO/#jyx3V#oK$UdRNؚ&=kʧ㕲q{޾!i"|YVv#I~}ȫKvα6S p' ͫ/*}#$=kE~b2^n,#Waҷ0J9FmUa"nz `{];P)lŇ)+\O[9PʫdzxuU%o$| o* ,34M FLJ| `XBN)NL[QXDnT7u#0o;< u!0nYyw';E_^EIP*MPE`(RD "0;pxСZY/dHvP;beTzLfa^R}a{嚃 Vqo*LF5~ %d5S<B qpOi/o_Uݓ*c e Q7H"{jNӲKߨG=Miɬl=ĝh=;@ a1:[ӥG7< _?T~mU!BO 7CRvi&ҺLV0fJTɚ:g95(}63wR3Idl SNuHX7EA)fcŽǥ~W srR{3Ng`6/A)G6{B*TؤG (aq}pKr &!S R/2iIJ\]`  @ IJ\]t  !T?( lT@GbS` T@GbSJ8=՜͏!ln GzYlp0msNl "\-;m ODpΖG̣~l;k-.pi ** k; ba;\ә # t,׫N cQDN>N[]i^+$ s5t%S+1͘b0fk+|ȵWd9'eQVk)]hNK`~0}Y z:pqzZܶ8BKvڮWi<(LKbyUưݒQ_xxK00q$s}Y@5q'O|~>Mumv`*ksӮXh%(_6$%`2,(*{".i9h %.#8%\f)tՖ(RS`bhM?r~V%y.!W_=x(:napt-swarm-0.5.1/contrib/debian-archive-bullseye-stable.gpg000064400000000000000000000046251046102023000216430ustar 00000000000000 `(N4`CiEf鉕v.%!!c5hٹ],3u~b7 }2KL!U15$gʢمX`KN<}p1hCh<7! 'y7 ],Ej#„Zaxse+}=џUoyӌ hΘ@?Ǧo1 ]'zpt出KvBp#}U34@سM-S\:&],'e!ܗ{(%V0u&ĒTRÿ\x<갪 wY|^)[ǡnv}R69}1FO*IDebian Stable Release Key (11/bullseye) T >!(R{`b`\f l`(N      `\f llUffKcZp29 JtC䦻"MXUD+A1kek=2{]6K(A2o+O~6:@}aH/L.hq‚h܌-Kˆ(Փe&+Dal#+q+~ (_d_GͼO3Wщ תr`KNgP(AOK|TőSM}>nîmtӝPx؁#P kg(Î'L_#F Fؓidb0"ݚ,hys)vGcO|e|UGmO0fYHkzυ Wsy;ݫ:tXaN8Oa TX6$$R 5l b,+ۙ:`&L- EE☵ _%NKO+_MޮүLwG|?[iga-䠵jԀ0C(7;++]mb93[фتQ0PZTTS} e/ KǣNp-ɵ9&IŞp ay2J@S3 ! U#9BtSGRLQ`6 SGRLQa%}@1p,@fܴ5H@C4p_J-gׇJJ7I50dg7?fk Z;l)j`$t,dxk5oq&ܡmKk*3y5& lqI)i?No9Y]M8[ː`dIN 8!X#a0<\l vJPH?7"Rd 0<[%my>㳷 Xo)|hT !#[biL[,c`WYN 8!X#a0<\l Aܕ[ٺn[%% 0<(A"iǹ 58(-aNquUsU0ZWג UD\T֫E8`aT#m Tu#1"fǡX@-[#MZDJb "i*\qM(fm'G1WˊѶ:ZڟmTxĻBydfC{LjGZ7+τY#HMk::I|7,ojvlE(FL][z$bmU NqSM5 $a$7bœ:49ad;)Fpؿ;CSº):ӣsO&_qZkScO_OȊݽ"3 ~CɌj<}*/qEЍ{_ydU%d(U )gTOH"3d櫍-:m%;7 Ik#x'^(/?Ab_wjԉN 8!X#a0<\l =AcZ΍n p 0<2qFǖV.]DnYflB >2Mgz#z&7.3u&_ɤŨ OQHb5g7*jK ZR/$3֙#v Hg;^Mʯ PȝwhtlDAa}V.so ajƟ IئuwtQ<uZɭSHc۱j!f"ͦCkHOXcޭ0`hN 8!X#a0<\l 0fa0SW 0<8)i Tl F, םˁ#rSv=}@F\4iӃ@T:;Phѣ9S:.G2 7r)L!XA( (89VTcS'XцN,.VBKs\DibˋC`]^p6fNH)C\rLp9"?X$ yY!N.0W^ˁv=O2%H^^9rycbO-{߃FB6܏=2Ҝ t"{@ Њa'˾[>|MR^fqJ# b?lq8hiqBDoem mn{f7ڬ9"5ՆwGX l7`mzFv w3c2H?N 8!X#a0<\l Oj3R?Ygp_ 0<H4̞61m0lQKUTGab3S >СsT" WH6xEYRHN;G6fMrH:618\*X~s3֩ZGg÷Xeβ9;y8{tI7,&L~ Հ5< Ԝ3 nb]slUuB :T a@ E%7<1hWޖo7ckVA?1XtKET3q3#@ 8)vȈ%+*(\t4ycsJ|#hGj " ~j` ^p={X׋p3 ?l NIn\Lv}[aIMf1D+hUb+:g1*.|CV*w䳇0]hdWHU1,jF"6Sp,[WvMۤa_~vGDebian Archive Automatic Signing Key (10/buster) T >!X#a0<\      0<  ̞3]SuGmнwAaL,\?Xz˯/yZc玱Qiw_J<7+ŸSUjum3ukS v)0RloY1H@5z,;гg&/p;PQue*3NsĒO: 9#}_vу'"܁bp̳U9^) @OH\A͘NZo.ڿ5: 4-^~-h'm >u1pܐy,SEv_ذ|HLW4s"((f.$>]k:icg$l6 䁝l?6ͻr &Y2Zx;w&ShWފx^YL OVr[uJTBzPoF}dT׾OK`C:SMP iҔ{n˧Z[=[5P]Cc /MXu桄9JT׏bX]-''mjr +EMj]Lj0fUӬ6&bma:Ѝi L右"|MF.o ȕ5';hzEktwKn;i0]8\JX[DD8+!p@4h BoXJ:rq;},Ky6r6 1kvʼ5 y 9P< ->kSe\tezd- fyՄС| Ry/#WtuA2ImA|oޱQ#u_E)\Qy.k~lLI$Ϊяhubd^ύ`;ǹN?;n'<(ٓr+Z[05ET(e/h$sZ!tU۵a󻚨*~ҩ#"a R%|Əϱ/z4r˴qu-=XHaM]l2v6v<TH2em '<-/)I5Вb.@,BF0!⊬1Wb*@ORO,d7ToDUbj!Ļ䔚zR}64(a27µKq%79#F1ӼNSiKQ{ya){!Zz8H.[(K^)e3 !vJPH?7"Rd\ 7"RdzRޡO!w7\3\#5Y]W܎:o7~>"}~0]ΟTC,3<~{0RZlWhX0 VJ+MhӨ`Ccϣ7sϲhR讇@^\VCHw ca)粡Oͬ"JPUlS@t@gR9b $`9m5% %/h/^~/K n R%Hջsd*Fs=7CAr}<{2Y ;Pՙ\VpL)hK7&ejZ?RB,-0 ]#2AjiEG"jɌb=C5pw%CJRCV/i؆Qd#&*[5Q[X.\ӥnZK$֑GR^MbB`C4(;WDdR1xU ?!Aܕ[ٺn[%%\k!http://gpg.ganneff.de/policy.txt [%%ĩiᵘ6oyKAxD cG?)J- K O)_-R5^B%oVPv!2x_OV!|9?v]4D0nU@Kw0Z=s#w z!7EјkPN-aO}4oƀ+Qs >hj{z4\)ƌR\!0+A9+I悝5']M"2SǴ9:tU.Y'bY3o&r8(y[TLiwrN6W }SB ؉jU™@rydI!qc@>\USRU%)޴..8N9+Ѧn2֣BZ`))NՈ[J] {8Og)Pmh?FeGuT \ 1k<3W؅j'(g+*qמ?&dՏyM=I6B;+'^Ju'F{& g5;4ŒhŔ2j[H/$~i+G^{5TZZ/bfia{a'3+4T4* ӼEi< \n%f2)igVWGt( BWVyͨbAN#1)xqbh%`ԯnFZBag.˧:=Mb/'=EtڑUQ7&t'QZkI_gQmp_۾Б<"0J~{ѦNr0`{YK ᎈ˝h7!@KgExljɗ/w-e2:#l$`GȊwsn]F$sw`7/xlqo[*<7d5 ChqOk.Z$W(&[5bge.Ňd3IW65C׌lN!俀uxA!nLfRb~ʪ F>PRI=w<7apt-swarm-0.5.1/contrib/debian-archive-buster-security-automatic.gpg000064400000000000000000000177151046102023000237100ustar 00000000000000 \ӳƒ\[#/#cy+/&*U; ! {\r|HYi:gT8.oRFG ne\*%g6r)eFшO6,Sۅ6тT-8uB{xO6QcX6x!Z޲zĈ)@ٔaeٿ21p*H_Bc P 4-lW!n ς; ?e5iޮWcu&]dqBtDeТ3`TX^8]C&m8iځ *hS8N6.c9D/=aK=jʑZaX]Keo-AH:h͗ G)k _s&U5N 8!^a&]z#Mpʩm\ vJPH?7"Rd Mpʩm%~V {/W6:Z`9 ZAtPKr62"֤[62oV_ XeSM XP}u{ukvlǴel9$NELZklÐ > *?/ggC%ø:: NF }_GK-p#s2U0ËxA#S$ZmYѴt6N`y )~F~k:Š@w4^H'yw*B< !Hܞ-6a!q^@=T7PGnR=9`\jʘ5fSqVQ?P~"XG`8y KŰМCYd|!I}H਌Dh]] Ԩ)Iᵯf*2~uSaܷ;< 4v)#f_f&{eNpA4!.ud AzyO:4i_XL)c=BA-?N 8!^a&]z#Mpʩm\ =AcZ΍n p Mpʩmf_j9_<@+/ >.qi]Ig6تsd5J"L6$cڧAo[^@;SrWt@bZ6Vh >WE` Z{Mˡ :f5jF$Yq8WshHe[Ec.g3N1hum4)n~Zn!bI.W\TOs@GPf0p&u'%=kigF7D:J^_8SpҒm7nU5F:]ފ, + e1`FYήK}9'IT,>3M=Ԥ< g0Wg٭a>mO9e'9-JQ)]5Ԙj[?-5.{K ?t,p~=nhj~gh>w5%ÀB )F_J*b>!N 8!^a&]z#Mpʩm\ 0fa0SW Mpʩmg=촔- 1e?kZ3=cKg o'I>+2f:>'4k~Y]@ vE喏P{!][%O=OuEeMsfۡc<"КE>?)[O7[)MC\]9v)״ A<Dy1?&G,ubM0eȉU}[U˽cԟh鋸x"+ow!5 i c=6NˆKYU?1A0GS~܏F|q)Al?#p=rgk׆DgK^_=c(ג+eGWLK*sDoEd(ƔB̙ARiT+] ԟ63?N 8!^a&]z#Mpʩm\ Oj3R?Ygp_ MpʩmyRmsgù9QA}'J!x6 O}g-RHAp/p&$%/2VNξ%]#F lsT\=$G(xoנp3cO wy`1|xhg^z``MkkϽdUzGŁ[ pDއJK ::kA馋,W% ,(`8\kttw_gmRV?A@I?ȢɡR`*([QQC=b!U*l+;P1/na_ddT^d XsÛ_"7UD"[;fL@^Gua5FȰ $t궃ݞ1e"F\<=?s9>CvԮ+٧TAp2Fw΍LefE 'G(DW𫗮`PDebian Security Archive Automatic Signing Key (10/buster) T >!^a&]z#Mpʩm\      MpʩmAϥVп #5%NpCek*ubf7Dc73XahS?Z+a/:ߚA0 *D 8$o{oi}" mSjf˘Vxo/jӜa*5~4%F|kr@B٨8L\CCY"0z6[ת/;C*.|z8QUFWm6G~30o?4QyTFm%u.VΫ<Ŀ,@x[RÖ*7a/ /KD]nb ݖKxNʊm_r&aBυu;gpur@bG=xQNp4^o$x|w3! 丞&Xj\ jǚ^AŨrUFt[.G H@sw&GZsgaD{ IE3N/}UrQV&DD @¼6iث>E0`)gl!p~;[ZbHG$W0.\~HTqgQݭ 턕 R+xt͓i{t2߱?J҂iU, NnG5qk^Wzh}2R=!SORepPcH+m6d)MRUt\m<2 $UioM!fӛS$C]˙IHwEbєdS#6LюloEa}SGV-MeQRUBx$<[f0ijV'İ/D&'[No1*GB)^DgsCh7:1a@ %ĊOcdDO~Xـ.Z[@=?1̾(7=e;jUWgp[Ŀp:n|l>G}'. !U ?!Aܕ[ٺn[%%\!http://gpg.ganneff.de/policy.txt [%%zF(\6d<ȹKΰaH<] K"ѦwixTϒ`s-䌕턹0jSUYo:;*YܞӅB`N۽tÎ^%g)t8=0-! ìu;v'b=O*fSH̪މqӎ8`_/0`ve g ;3L :AmTGMe:({ r%(u:AкnCy9 Uk&$1ܼyGl33O4*a^3-ϫeU=9S5]G"Kfy;xcpJb$gMzoFi  \3>zUJ& 'y{wPփ\pdmbgr”\ GyJSىJL F;y QQ=D: q0\,kفd - N6 aj [Dx%ߔ-°.$R֭FIJq}Ĵ@egGc IZP$UAȍ!x=hx'-&;b&vvOW祤M(:){OWk*XX#135'5Q*Ţ/u6?4zHI9 XSwo~O\ȗW'Yt72vV$brgLʒPcW z"vLf|Aˉ0!3@6H1 p۽oЍXӮXs^j7/)+4(ELtaDtn7gB ^Bf@JeIx{2r &!^a&]z#Mpʩm\  @ Mpʩmt  !R7t&b*\ &b*N?u0D)5B_f $(5ӳ5"+nF@Md !)э]%"e+|/jCCAn+%*܊6G4[\9;3"m)n*5N~ |e  Ę@E)c%B]Erb(shhh  .sf2aR<F NX`eVa|{Tql+a.5D-ŔIxXٿً3R>.&N"[\FpY6 [{䒴`h8H]L$8߭0kgC- k|K{m=MKfe6rcʇVnS)K,b<7Ta yYj/paR-|[);PRn,t[cJ<ޣC(ϻK#ܚ6^VYNA{I䉕68]r0iZ{즘iE{F;p4)#_I5cnMA >.\=7qHJyxT C JuU,𿤌o KRƬ[22bBE㽫t.Ƶx}/?[ns6ue;O,X@ (9EQ9^S%(ڀoG\n6Rn%.^yGu.C#@a$ICʌ@ggT FISҔ_XYL-G<Ֆ1#ef|cf3|2ģ*o|0]Q"PAsQ&]y CS@PMdpK .Tjۂ.!]`v᧐t]m!:~.4Ă orIvx!C2dw[fv!% < z}A.$i*ԟ7zALXs@!H:I@ʝ@k_C[}I&E쭉1}Q2apt-swarm-0.5.1/contrib/debian-archive-buster-stable.gpg000064400000000000000000000044341046102023000213210ustar 00000000000000 \YP5pGu7EIZĭfq1w_4x^'} ̻UPB:D<>*V)[T@Qk'+Mv-!Ct騋yU %~vGx Ѯe=yڀ 6ۧUAN$?o 0Jo2-h.~5E#ą4%9Mt*(^sRg d?7}~exp]MSOd$- f "[.1ixLzX/iShE X%{ش POS)B@&=xbƬ„'I <&i0vGe<&X fIK[+[B<0 C+*p{*395n zΧ쬟L(̆k?wlsQD& Ao[.NƵdrL0lO`,C0aV8Ɗ._'\1M@ˌCGDebian Stable Release Key (10/buster) T >!m3nݏA:w\YP      w kaO]Joh=<-]jq'$EDʞ(aXpO1h_ȽP/+ Xhqۺ|pa%\*aW2Q ?wzpnXR+S J2X~ )uF`,E&77 DN-8dTl)27HBkK~z[}Ȳ+lhEfhss{F+/@GUS ״6`x!!nV[uFqo ='-2f7ahq*t Âh縙7:PZH`Cky0,  47G6dHߜmc%ȍ,[{9 N$rw$25Lg`Fx!^Y\T?/}ݮ"hlCQ .]bF*1LD>k pV_M?IGOc NAE.&{kϖ &٨↙3!rc,rrQhO]BY\Yw ]BY( 8:lPE-*z9JfCdj|4vb:'qsR2YcĞP_!yM3ZKh= ?܅\\Q{:x^%2T7=r1^'`1A}s|,a ?p2m4%7͔?iaĝT2qޡ ^ {MֽH"xK yڮ?i)HՆ-j Z5ƖIt/36̄!-w0Er-WZmʾa}+>o>'=e8pv|R K*) XgudʭŊ7M_M@l BXcE͍>ի] j5m=Fr.3VϮwh3 ! U#9BtSGRLQ\# SGRLQJ4ݵ,'R)4G:LiN!UI*eMf_;i[zK*S8eFQQQĵK-C'U}R?Bn\P iA{5VqaZo7yϳ&,J4H!N?䟔}3J?!VmqQtTi#R3KOϊy{bj/b8?WxBgn|'}NSO_eЗ XщE3h#2Kx&JNof2k`e+Ӑ[|BH(:ڇ?p|K~dlNTF2x$%"[;B6oyCA[utMޓy۬f$Cߗ{$ _ҚUt|0ERl΂@M{ji,h똏ڔrl ܻǤ(e}vb@`MM!y m)+:Hb_o?.apt-swarm-0.5.1/contrib/debian-archive-stretch-automatic.gpg000064400000000000000000000164231046102023000222060ustar 00000000000000 Y#0N &-Ι衖T#F#A8s@ gpjs]‡9xT4yͅj|АcCd*H^SQT_#_:I[I qL؉)ak+u宎0=y_IsPzI"P;41g#_eL=-H#bR84i3 4|*;l=M+zz m#Q).Yǖ[.nJ{O $Q\ȼ4Vs$r];aK= !0utT-8ҺzL9Xd蟧:S/۴K-_j%aP}aOhX{N 8! 丞&XjY#0 vJPH?7"Rd j옂s7Ռ3xw6Jg*2\S-.KM1~|s摌B_Q4]cb&B"jw%e2[ރ4K6fel4YCYgJ^l`?9]NڸNΈZx0ugX?,|& gqdQ'eF:m/h]nҽ:i6$:6be+JH Ⲳhw'}}ϽP)UsYB׺eݷQD(kjmCs_lBJfm*{+2v,Tt5> !&Zj7_>A TlgH,ϝtr3k[\&3Kgn[U[UW9a]!=5A9BNEiuԕʔp[B52PN 8! 丞&XjY#0 Aܕ[ٺn[%% j옭_),3,6"uL1ѣw?ͽ7MDzB4rI#0(c޶Kicvq{;ܞ? f] iBD*wZv`U(tQJ[n0ȥrU^ џk!v568W_Ļs3+xHGSVsQ/E 9 `pkwT8yĐ@8'Hʭ(:MMPI[Ȝѕz;[#^-W`p|]C$2L>t$\9'CCAbԹD"@_{f !e>dKշ9)K'e=B-Pl[8%I07+xӷ=37Uw$!ez5H&2#t8߹!.y \>^JJΛ')!EGi{D])~˨%Y`yfr/eztA k1B};rx*rmG;N`)5|eECwGDebian Archive Automatic Signing Key (9/stretch) T >! 丞&XjY#0N      j(Zb0QB;ᓚuO%X=#w=xfMVs֛6C[2 Ϧ8K4?<"v_΢,_pWvrSٙZn$[mXtvN-G6Uv.udvH0(|պ" /c UD O4UOZh\tBoL K BHM;) SE1|ҤT!7dRKv4D#Gǩ 7v}ڏSMW/5#)[CM7Z?V5&Oܙ8#xPFx6+WAGygDMtoɆJ \*af\ffg02uf_!a:U &Dw fr.05K[-8*R?a##75A0ft/T8cFi&\#Qxg+6)(J˴F!Ts +Ս\ES{"ey1.^U?!Aܕ[ٺn[%%Y$u!http://gpg.ganneff.de/policy.txt [%%?|%,-=th8iW7lK;Ud*8ym'8S0JJu7;WLWkoR*^\U;1)$V} kR[%fgc`)Ϊ81Tr?6C pFlZ5Jvvpxz}"KDz2ώV+XAxI[TP&`+KqBչ~gVxkFa?Qlz?+oE%-Ølj@hpRiCkWe.[!}پDW.^+)%WM(k蠇 Ɣ1o3S}l%ҭ u顸6| YN+-k퐨d-ޱ<$w NP.sք\CD!o.LcS }ȵSOkECYFq8K>m;R2<8ief@2Vn#Nr FJ3 !vJPH?7"RdY$ 7"Rd¤ iI:1BQ[1ák :Z^ܨJ">e5B.Z.tP1TDl/:'WHr.IY1Qk1. ߧJZ_03*iƉ!; ql1jÚ}~ߍ~*q̻JԿ"^&L ;Bgk5ASyjy퉺5ɣT,}YqrsM%|#Og\.vo$n3JBP >7GHSf9 %Ņ6^C{1*_K' ik#BQ`kFܠĺ+QKof Bs2[Wu!<7Kba4 k 9C3W)< !p1~ jFW3kx1hž{!G\W Js`^VY8_"aˉ鐒\V=aZ,2Ym V.T䵉/sOsWÒ 3q>9qABE080fH),ù= (he(^@fA2C/FCu' Ю a45Q{RtZv4r'BL,UuO zK$;:|aWԿS;u/){O8CƳ!1[ < {)=5Rܻ]aHa P1zPu Y&Q v8D+#[0(|2{1= CkM1pygG[ ]ʳePE@֓)ޏ^sPQYyD_fG؀ObET9C'R3hxN/~GmW+{8&V6u4DrWj'A:ipsͫ9.` b:hR+`$ZQ-\3Љ?r0y5zJ)I 0EfA8pkBvNsq&?!@K'AjcXqv$`CxPzrN&w4e>I-bc xk8fp6 Y&Y mkWF/}SY۬ճÇZ8?rScCho kz2ױe;Vlx˫[-CG{-$58K/3^./2tкfL$2 /Owcd3_|![iʹ%,9:1Z?~6#vlb95"V3RPEnr z12s|G~7mm1Siq!tgqՙP7n/ygt~44ܣ~'fu9;?JZC6cL 5aNqbVT 2]+0_; 7(uO :m):@?jhF~nl+ EvgRwUUw*Q44_*F^ز/E! ].!ә%|89(A'rsZ:o%j@t-CWحa T.LF_j䲁ǹ'5aG/b^pA%1kOg_(8iŽ DcNa0'Ӂ[,Gٯi<<) p>b0YԈ n(QWmغZ7ko?u[K Yn^iA5r &! 丞&XjY#0N  @ jt  ! ?e2<r7SY#0N r7SrLP*M)ȕ0R OǮYjO_mFp WMY,At18Qu'}DsBpPPlZ%U`)Y(_ D(Bn4}b.KҞbN_Fnak?ѤNKb8FK TI^K#ܑ3 HgrAL7o\I֐"/f&r`]ӫ}M[{_Zu!81{~xdKc`DۺAG]L1^0\͂*䀻>H01#@8_11OQ} ED2?x`(Lw^۹ iA!M^כR$oC)%#As+đ]:дxv\ b<+6;οyӴ-LL<:XwF#1(j!bI,s7 | `TNwC_ܰ~R)!Ь* q0tRav et\xX${<\HXpJ^-/1mncI/~ǻ}{`|8TR y뙼@=!7SAonW> /$0n K~`!}$.h{f enV~OT3w8 N!h$% o5+$B_~NFDPSGo< cS~-2zyG$gO ,6yG6 .ܦڴ&tiyNDQ>LyCP~?QRG $n(da1.(g&B~8Cjaapt-swarm-0.5.1/contrib/debian-archive-stretch-security-automatic.gpg000064400000000000000000000164341046102023000240550ustar 00000000000000 Y#0n qTKzsҦSAYg3Sr7fBQk&@E,:|ֻ5|o|:-zNDLUJݮn軑.jӷ~)UP 5uNj]x=2, (Z>̞|*6Aa<#c_y"MˠW/q O%*H0No m5esP_ik tڶ{n%nI].4ck|һY'M+;tu;oQNH 6qM{eւ?pShX r@s4UfbJ;9Ϙ3f&n:@w. fbv=mes#6!YbY\D͔eV!taU_'yyr뤯X~ZTWhr+>ŋ4݋jTX0!g5N 8!n_/F 8+Y#1 vJPH?7"Rd 8+J#GgT3-K8vM Ipc3%DG9.mwPբLs\B<`rf`w+δC9XjoVJd3׭QmS8S1H+?/r :׎z\X[F6vd;aJ@*&r %rfC1V5Pꬄ~^8mb5?)Jd[k8"Jx{p/-eͅ;E.;!gGkV.Cv!rTc2"'B&˖ m~+L}P 7sM~FϏLרFpt Q~7 ~E~fa,NJ-7!휈;2ÝzZ)H RĦ66ToܠD 5h;Z8+wJIJz_7~r7 @|/;Q<7ռUN ̭(+ViagE!A޴<94Ȼ^d N 8!n_/F 8+Y#1 Aܕ[ٺn[%% 8+ߪVoƍ` 2FhPv聪Mkl+oփ7t1MSj'e"{MYK_̸KT$3ч6ir[S͘"vM?7 4 TA}f5j3X6YZ߳|0-Ggv'W~%)Qqߟ FL벡$i`+.%n1rA6bg-6|sh"fifW(#2!K@u>_"a~@"QSWNfw׫Lw;laPF-$hࠎ;CUә2z\YMgzOˈӮ?Z$D^\\5?wcZ;sK!*h[Or9dVv.XEѺ %$tiC3BE]e̥?ax|Oc٤M;0ː'8N,Xă8+ aKT\Oa”Ai}ɬ4 N 8!n_/F 8+Y#1 0fa0SW 8+[^CcDug+bdCO3hjQM,׳)_`_"Fƪw-l~W~zʫ <๨r cYcȤ =>+ecD0h܊OghkQ `.a} 2Ёjxt;dbClK&3O63=,31D%Yc63u!<Ӵwuu|U9 %et8n1C6xl=w] H%X'MBgeh Dwp93yDآ k1ȑuUኪ{ܹg#g[>ƈA9 gY/ g}_M[[h47iTL"s)AߞGˎ`A T >!n_/F 8+Y#0      8+YA dGSj9fxҍ)? (;⪱wa kc ؂%i-TY Dhy(@opEe!/l8&/9Y;`5ȆƊ)QI=[VDO gŚdSa:ʹ;FRG7p_HnҴ1ёV7ZC F[N > .oQo(1PϮT սKeVAUƒ'PcKmeI}/!{F.~Aorm%#v~'i{0&Mq՟ݷ{ |e۲=_`fd '3c8AfAabx&aS9iYNLW0| qM;XD:H8Lam]yv{=8%,yj^~-rSGjOt9=Y>0S+auiB1l^q?ݲ?J ?:d4{V"ZSNP}t(8>kU?!Aܕ[ٺn[%%Y$[!http://gpg.ganneff.de/policy.txt [%%:]YL[yI&b6Tv߮w/Dqsk8ǰCY5ћ,0R|(K{KxC$3K`, _n0Qn=s.oD"o(Rs#!ݠOA&[-ںjU/y'wBky<.ʪz+n6%>j60Hp-`KL$+}A #Rg-k*tTpemwMJ|q?v9% uYYVRE;'wz-4 \>I v֟jM<v2 {F@54NDCA})ىK\7؆oۉ"ҦdMuKg| 1_X"Szو˩;fY@ %Մ.\W7F Y;xHU"=xB5GQ oXBmҴş[8e[FpfOYzWCF" :umҧc?hV3 !vJPH?7"RdY$ 7"RdB@:$p9erFWt3#m18gN 4xJqsI'Gj(`i?IQYn4|G1z,pNhu%1Z}PkieޒE|"wR%XSq"_)A ZJCH[%/y3+DrB2q7˫M i+xCR[bQx,D$hPi(d"f)X~>iZ=Q@?gͷXA)A<Ɯcq~';^fʤQ~ρùS%kW\Cح0 b, /D cTκQ<:磽|M ^ xff.fʚ&|Ru'9I4xd`&D9gMo޼DFTCOzL3 kCX3 "Pd'dP1GJIE]lBXUz"B;eY% qAX4 ,hǜA?MvjRYX%oegf;ü&bSYqToKАכ[俍q$/1>}oMR"A]Mu˪,I`?J\~Mun֢PrE3Da"DLz`HSBb*z&<ߝo< c2끦4.>bMfDi9QGWy2WR1* & Y& v8D+ESfld~\hm ""ad\};5Xywn 5A7ㅊx;#Sj7NQlj\! 6)yT'|Aӭ]ĵ }B؁'!A\wּ_f]֙s H)e=~{yG:װ ] 5bR}՗ZU1FF;/wҝM"|!E^dT=Ȝűe^n P2JȬ2G,Jo:ЈTTσŬ' ZQ Y&3 mkWrw{ Y^$QMV"FKqU(o*"Q) lp?aTrPn6yƒ'e-z) ނΪ?hN75:'\ a:Iͦ EL'vL(`C:"]Q! ZD})vλ9Eb(پ>q߅`tkS`Xdd8%j m%]q ޭZ;0M7g0^Hmv qП΢OReRkBY^Z;{E8m)> mN}5]MϷB6PUnN8of qjbXZg#Eɾ"Vuô;- s[^L Y#0)Up>j@RzK g+-?vY7&ϕm.xٝe #Xx?W`)V @^K3n޵8B?NTf _u;LqOb0Nqk:: 6;X'|e.vƮ<)WDurC47H=%^65 Ev?8ck'9o2"ƃ I:9IYߤ3q>d QsaJ峨I{P]ϔ"׬.gg =@w~*Vpx+X5V[c!‘]sDѺ@lGх62톫]7S,jƐg/4Ki;* |\RNJ2'GF w!wC $T^\NwKV,2=$sdU*/c`UV7ܳN0Y%Z[h#r &!n_/F 8+Y#0  @ 8+t  !7ض`Urݪ3PY#0 3PUs]1pAA"M#@HJ,B{ ^rb鮋.$;%+DmHxw?ʀ#h V0?g#roəZ9 G4 Rʸ?»9p-W/Edxyf1rH3w[؏E$EAHrg YŹ!1;{*eoFJ{XLfP?oZp?gYJ_%K{(dKJΦOQ\Pv[jI@1~xZy}Je}vUqCo\/k (-ĸ/NBe*u:kiCYMk>dEy~X"H'D{^p-4QL٢Go"͌}mhN4=uiDvem$An+Lqdn"Z]ePIEyu,4ƂuϗO*PC|nD6K;Z\sk`SFX5 n{V$yTؿ}pXz#st<"K̈́D\-o!||݂xADkT_,qH3@АrS)ˮZjjHvStr?V$׉,TVGDebian Stable Release Key (9/stretch) ='Y       8*{e="q~HPХftNbzS Jڦ1ȹvsgW; A/Gbd^j:cu-4*- TR e3f0 (`KWl'&{oUk˭<d뼓vtslHX,W_GXR-C2+[C/Ы`E\( /jɄ0&WҭJى e ~zk"yTJj>#CοEȚmGF)CA0ED;AyO8ZzM܃`[u *}we иIĀGivV KAWDR!ְ9j.kU*l(C4A%uG=z!SR1Mb&HӁӖ30}h M%t@²c)f2h (Am_$r@ڴ"|Y%? 1  8ޑLi.`93Ll\2R;Вb :$\Ybp &G"4V˒Iv+`Mfkg`6@޴5ޟmۙQ `zrj 8,;Hrj9/,]#s*LɆC @w#VX6yVV ޞ5OOJzSZ I.knNk@ G(Cf__GF::9Y޵&3eOIta*fM_8Z|[NZ6;8N`1O@("!›Rk )l;]fXwm[EཎU ,W-xBjN^AVc ~`m$:Y$)ZN=jm`1tOy"XouZXvYzx'#*˕N1eHY' ]BY\t/?iF_o(hvBH@8 G`L0:b̛X7. ~MfeB @)`%lYd z ^@<+_ؽ~AjV]tҾ*$Bw'$gg$%/PЩVPWzeج0ĵGQVojby #WHˇ dRrjl{Cmq]Ԃd i+84T.<$C%n<(\ +諁Ǵ؃sT/}^ 6%O P^i=Ug ۦ',Xa{ UN@Y ^FON{ftjӁBI҅ӷK{5|'z=pwv:. [u;legVI"ųNR/!;8CQZ(YWXҔ(A+9iQ43dvmapt-swarm-0.5.1/contrib/debian-snapshot-importer.sh000075500000000000000000000010421046102023000204540ustar 00000000000000#!/bin/bash set -u curl -sSf 'https://snapshot.notset.fr/by-timestamp/debian.txt' | sort -r | \ while read -r snap; do for dist in bookworm bullseye buster sid unstable; do echo "[+] Importing $snap... ($dist)" base_url="https://snapshot.notset.fr/archive/debian/$snap/dists/$dist/" curl -sSf "$base_url/InRelease" | apt-swarm import apt-swarm plumbing attach-sig \ <(curl -sSf "$base_url/Release") \ <(curl -sSf "$base_url/Release.gpg") \ | apt-swarm import done done apt-swarm-0.5.1/contrib/docker-keyring.gpg000064400000000000000000000053101046102023000166150ustar 00000000000000 X*Z| s@uV-uoa2aM_TR` 弲)5䷎ڐXo^U.-Ӿ,PAnL ~,%>i5B@?"]/|B}H5X|Aȱ71bvzh܄VVsz;\{R)4XHrK ),4>\ Q4 rhaxB&8U˜ ["0[^m!u_VXDY 6S?^|)D"V\(rh~.呫/p\D-xTV$^b9!M4Tݤ:әAnV7+tkcP\R؍kY]9qHt/ 55Bp)}]XSx¿7 !X/    <͈$4&6_wQiAE^%ȒMLʝ&5HF1#qyb?Ύ',48OFܸ$Q[ձ9-0s{@/Uk,ODgwnlmP24<ߚ:8J$|g3FWKsO]i׵>*4fML-GK`G.{5UnCeFafRZ=?@* ~>O1uܒN@n#L <7?w}7Xf 5~#|V%OuFE0/4o< Bfy3A#A"#j ,>=QNCb|f`>;qCOV\k@V: ѡEH ]Vc=`K0wt6EC:çZfYqyX5Z |銠W :ΔgvwbNB33iK\?BYgwe76 jQ:(q ]ر1y:BQ%~2,5ڐ܇#a.;}uYȢ[UWǨbkG=UpxMWAhǞ08{@rLJtO=]m-bFbaiLp:Um>oٔЗW̜+@iAAE9 LQ|?1 Tှi0i/s'b;j`cTB \2k]o!jˈ{e )u-ݝhDz Й 3+H;0> X*) <͈] X* ~s`l  q덢3ə ⯘gU>nj\Gia&?fF#B~kl7{p|**[0{g;y )sw?Ulֵ="5yV1;3szk6L O笜eQ(o&6^9/YIFi F#k }Fk>]$8e6WEq-gB#^;ܥ Lp luB5x e u 8WC4 D4"x„-8ءh^"=-a+]zd7HZ?eS1]+l V[%vI5Ɍoѽiʞ KSКIWK{fe*zsZf+/0 .d^:"3B@ YZȘJHHlu*#gL 㲻/Yfo&UVpuD&*ՃWrD%4]ıuuv0ۈQ[ y}|zDqxS Ph 4VjtUޤ!4h [gx;&g]6•OߺEn:TܠVntwk6ҩ0wfo/f^܁8wYx<ňot+`ȷtSMO("`߳FZr8Q< { 2·G !t ~:amA2'r|›ύM?ۃXYKe>(p9lnΌ,\<͙zV@q-Nӗxԓ`~ju]bz1z'N }a?tQ}P[!؈=apt-swarm-0.5.1/contrib/k8s.yaml000064400000000000000000000017341046102023000146000ustar 00000000000000--- apiVersion: apps/v1 kind: StatefulSet metadata: name: apt-swarm spec: replicas: 1 selector: matchLabels: name: apt-swarm template: metadata: labels: name: apt-swarm spec: terminationGracePeriodSeconds: 2 containers: - name: apt-swarm image: ghcr.io/kpcyrd/apt-swarm:edge args: ["p2p", "--check-container-updates", "ghcr.io/kpcyrd/apt-swarm:edge"] imagePullPolicy: Always # TODO: how do I configure `init: true`? volumeMounts: - name: apt-swarm-pvc mountPath: /data volumeClaimTemplates: - metadata: name: apt-swarm-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: v1 kind: Service metadata: name: apt-swarm spec: type: NodePort selector: name: apt-swarm ports: - protocol: TCP port: 16169 targetPort: 16169 apt-swarm-0.5.1/contrib/rust-lang-release-key.gpg000064400000000000000000000074241046102023000200300ustar 00000000000000 RD<خx>17|i*ljg E 'ᲢBYuHRf \! {Xe~9^cX]fա5PU=IwBcQ1HÖ?p2MvzaA/I+G'-6}H^5 b!\n#JZ5-4g578<ojX ~;^y2+#>FL"carM#׀J!SN?z|jd "gv/\>f3سU. {n(*Q]jDTzjUg.Z'׋#9>yۗUU` >9O21bYĎg]#9BO*Wn2'[R# {]M|"`G;##(!^cElҍGѰ aMA r0wteӔ*|]68"RD   _aoP+SRgg|el Hh F@_h NtZ$ =UnW\>;:@h+P-U3M\:9ݯqYzP`Wc dz  ۣYa;E;O*i\V(CltRxujj[A??y$0DRZc resdžl84o*Rb3²@ʥv5i+5MUe&PFLCW.JLߕ=,dg{v7'h \KIF=Q=F, HE,\<f&eͭD8TLv>'}X cgm36&;X?~tKo*jy_2/;+׭tك~4|K9lxΕ:ŭg`׷eofm aYտX3%N wˇ[. RDry)~Aߣ78fFv̂@GԛBayLdwrjc$37Φٜފ8r*bl'r4P|:{]0A*wư/}|k+oFZ.E*@F)ϵLz$ޣ950Cnj2%G_qp)E=:D J!^%ac:PI2|@j$II#!L7zG v}m+p/edX,Nt0"=Bg.EVV2i4-l#(vno.;pVY(!t6ȍWmR)BUW >jp(h qh |Erj8LZ^tH:m I#+?7?6XX熢R P\ncԦp/V5p@n5Q|̮~%ceWQ2NŻke9ig4F<%ac)%W5iY`k^f2-`sƧbN's~fTM-5&s7CzR]j.'AXZ=}l,l6zS5a&(,"|o2"(T%&98$KO g awr<$Υގ Q`աމas4SFw "Z7h94O 9k?PSF:Xq|wK谍Ġxh 4U7Ͼ391E~aITlϩ Tdxѡ[S1x$/ CgwQfZ}egbhs3bA T}jIP)T/A;p"tQ`%AB~x]905\Fc3@HKq"Q;U4"?hws+/q\xnzp=]&![A((v6m4ϜWA]"6ջ"j[.(jqx잨Z h(8T-\S*yۿ)@ $(qI 77:Bi@ hT|yh[#D"rS?~? @ L Tdx) ] Tdx \4{; (ZZ7G(+fM_~^-ZE9G7sMWߚ^(?`[uy9h0!Zu#%5#z uE_nI8oT̴̏®DZ=d2PxG[-pZU'th|~NhW!>ܢ1LK:F dreZDV, 2b/qnz , 7iB6:[AߢIW! V$j@O]5ՃCNA5e/@!~'p$ vv5 8?{A,OGE4TcFd7yuRv_UmLpp p"CT (vBa&/'Dw}>sp=GdB/=t5c'E"Ⱦmڼi ek$JpVQ}y[&dAl"e$KeCߗr.%MO1k&6[) :;i6 iE.Q,2l>B- ͕bBQo?uḀ]]BH0͵3|Nf[8b[* 4W(γt ar-?t&|`./H)Ϩ̎f1x"˼JK QLR &wx0a&caCC-2 GN>)ELiiUߚ߲~4NF6tH,vr4VoeΥ,M!+dHjəLho^1-j(@䭅\0rE<)I@ssi dfzG7%0UwXJm$=L}0|OȖ<#Ⱦg1j\e4j^/A:??zۺrr^D?~ؠ2Rt_#l,yjc[\Jr L2yQsRtzёapt-swarm-0.5.1/contrib/signal-desktop-keyring.gpg000064400000000000000000000042571046102023000203030ustar 00000000000000 XJ'LMKZ )Ēl,o0d"T2Ɇ֞Qcl8X.-D4Z9r~InJ l_=72$8%*qw=J0)6X*}.zs،}/B%Fh3g( s Jlk:B>o nr7*|J/4vV<|N \(ab#ʱZ0 RaND,#!.f$/aqMJZD8F &0? 3QuWi^""_GMRjM"NC{ B;\Y,(I 5˲,RDҠQYRtr=Q 6в48Y7Z1렙4Ws1&(uQypzgO8xV UJq2!Ex#ƴYz 5՘?K@Tgl&nٸՒêA>1)^J1Open Whisper Systems 7 !XJ'    ـtWSMO=jQ%5tFab]Bhx[PŠ;1$t"+ Uo>k.V&椗FYrAOtQm+*t3A@'.R%Ov,=skS~ya{m alw޲bzE$I c; oQK>z 5>"\31E$RX,/O&+lEMa S9K1iY8z^C}TVQjس]V+*lTݛ55ɱ~E"₼K@Ge7)LΜ~'m ]kg71H#B <ŎՓ;:)~5/xyL=޺u0D.;{Ls$___.Ż#B}V=n: G0UX %S!aL9٭~8rxk3,ݯ+\*" v5ȝ}tzOSrO n @0=f.IƺHS`bw~= XJ' ـtW-ZrNwgL,X1x.9tJ2d(bbv’ZcN4" ir$hɜ7\ٝ9rAh 5\n؉ihbm0FAXf.\3cn/"}6j?a9EiwB t1 %~j1.6?8f guFwz&oWcb/¸ a`ɄٕR<\ԇ]PXF;Y͈'0)Jpt'1ֶÇJ$9ͷJBJZ 8SңEO$pYֽ~ٕ.EE3o]Zh!Dd,ch,=H2l ACjC m7)%P24Ot@Ʃpl dbZʗ-ڻvQpU~ 2u6fE\?fu`Ad!WqIQh_ 7ӣN\Jd apt-swarm-0.5.1/contrib/spotify-keyring.gpg000064400000000000000000000022401046102023000170420ustar 00000000000000 crdj”9YC RPr1xEB"En I7@A,zCL tݎ Β3] bA7ܴf>..8lgs\Ψ+,\4jjNw3mtsiw{ LjK FR>h:\O1ef.7 9l٩%,IID:]F+@U]9y(@܌{j ƋBt!0_HS;XgG{=1]K8U^HLp[H}>!r;.ϥ55ŅÌdl j|vQ;?Bqd\U~iFDן%AAU{2][^f|@OqDP(g2b\_=~? ($c9/Ni}1V?pI ]#uPPoD11~jwez=7Spotify Public Repository Signing Key T >!t f3-/Az:v/ԥcr QC    z:v/ԥbʂ]. X\쟒#{RF ׬@T/2Fʼn'ڲt.G=ǎqkR@Dɡa)ThWJ}pzrF ߶7Dr+, ?-~Fd'ax٬-M_r}[ -."z tG*C}OXJd(d0Y\A;#SPQ#>VUX 2Z{LߑXiV"6LTZqfI ?A=dNu,*<>1c.ۂzFś(v!pcHWsdάٺ GΖ۳<DD3[hr }e(ݹ ;&މ%27`"DAUZz`"%C/.cRub4xtdW 'pOdsQ!*=d6hH%>Aapt-swarm-0.5.1/contrib/steam-keyring.gpg000064400000000000000000000035311046102023000164620ustar 00000000000000 P=3 Zg 5QzPhK"!lINF@SDz3qli 絔fHBY#FO!9?o,VNA.iUO&TC[&RÀE”^cPuߍ}hLa^# O@L=+˫Jy 8"Pˣm   J꟰T=_-9*H"zֲLfwz۹ߟ%k<ɗ- 9֬T3 1q>b=%v,jduZiD֓w\k٨I/Al(H ɷ)gB9jb`J5#y%Fisgк,EC˱{Kڵ°8Jpmdip^>CϢ"q\lZV? cWs۫o0NC]!/qlJWk VȢ`P |+Valve Software LLC 50P˪a Incorrect company name J꟰T'`-f6zοO6&բ6R4ŰGhy޶Ugt(N{E\Rf= ab.BybS ae0"f&οB?dJ/-2XUGJvVÃyю}RsKVUSNB9-*a!{Qf[>!UXfR$X8"P=   J꟰TSiON~<`*k?*1g` A"?{uNg4s%B~^n $dd(;ye'Qq}3AD#9m WS,6k.tRdȾ&7G:HJѧA#|EĈ+j찟yuY1)V ʑ*j/+;US3lN>ms5+#h;&[W+n^4k +[ؖUXnfsErߴ P=ƲQNT[7!NU:պzXrԑ~BƵf5;/_}ٴ0m6uŀ0[QÁSy 1MD௵qBrh*d~E~~_jB?8&'(OU;6OsCztOfN߯x5^_]8ceN@U afRi)SyltZ$Sf2|ҿ?| P= J꟰T,~AO:q <єh\80Wx]/LQ:q.u.g>JN Ϫ3Ef<m]237gk \.qVtXC=O{b1랟Q%,_*|;<%Pkw24݈Ri_IO=s i~ 6Zódg mJ#i+C3wxn!?Ӌqg1ٛZapt-swarm-0.5.1/contrib/sury-org-automatic.pgp000064400000000000000000000033511046102023000174670ustar 00000000000000\o RKbd`Q=-cqV)0}S 0he,mHd6׈VD'@oC}gE| Ql1&FB_EKk:UzVU6HC} ]%liw}Y#r A?my٢AvVU_͹y7S~Qk_%`VOncC]KlvM}W}՜{nFg0531DEB.SURY.ORG Automatic Signing Key  >   !#]cⶕGC`+ ?h ⶕGCC )($MOI,r ^Wgv/϶ȧIHT$Atd9K }+- $Ź-5PeG6P,dC.)Ulնతsrr$g2÷=؝܈g@}f@ɠXe^'LqUݙt/<좪}3?x}~f7//Uu$iMz;ky : ِNןF\o 3]RaG_iX!?(*;nګE :h79k83\߱8KvFW0:UeŶ[Ce؋(gS@y vlݚgx5W$DZtl%(r#6t;QTL8o@I? (È/53JǡYjoo`ݪ݅{]vqb݌ d[@ t//0d,XٍC O؊ǝx)ܸ*2hxh򨑟F)ÓuII7p I'kDک|dI 7@;t16p0/`>}\2Ow & !#]cⶕGC`+ ? ⶕGCx D.SFi(Vڣ 8D) 1<ؾr! tO;yhYOUǮT{ 1[rw򐋂0Z\Jg#.-}f!`Pwi*<9iQ[:b.]R,KRےigST,c*Fck-q#Muk=FtTs ލx''ҙ)ܜU MGlGN RZ5(bT,BLqlbQV^ |@,%a_VbW\y7n"QpqNߞHn #d `~FEU~fz{᩻E#oֿɒV9u:0Z@M G߂S'6;-6YS~eeZ. -bUyx-=L Jt ew zn$lJ~Ye2?}>w$#&$gӴ8<& P>3n " m݉g52$9 eu)9-Pwcҹ ^/@ݻxΐ7%q}j|ȟq"Uqε[C^-"jy-wBξ6C:UJϓ#}%ge9ŏ$$11D/wC.6OJY+H+p:Dy4S_B$_]n٣^,S4 'F2_}<UeWfFJ2 Zj(:O'40\m][EëZy8+hXEFJ`5 ; ?1K' *$c숯y<&W[AiapϸjQK|^NFK} bO[*9Lp۱UuϿBXV Uu5C7쉄l>FK~/ NS8_q L%E?iOu4X)jmFL; &1'ȚK8 >;9i7 .)F zAa%4ҚnE^L k7,[T֌C)D;$I":=+eC%C?}|I'M7I;yL¾+`׈^N 9  16†o'=" ҋ/ Li٭z;9ήA5bوL| ^oBitWMu{쳯n-ku,I#4ڧ89?F=Y%Ua KT^ȓZWq'Ir~ ݠJV3 p^}bߗ`Lj c{]fk&Z ~+Sg'vC f5wuaՎjP`#xp Pl{Xe \4C>v=,G$eh㠴] *=ggJ)LXW>dY0#L|yI(Fw| \-qs$;8Iԏ5%"5K0Hn%ڿ 6b)mᒚEUN&Ō{CʿSdS!@LD N#)`nwۺιV2"j|tnDmh*1 .\2A4ߢV#xBP=X7rֹ ٧c6zcקMOGzYƥ(BѮ&ࣙ*q*0r|s/0]Ɠ*0 %ռѦ9P.+_yK!;Sz] WKXV%$v]aQB-Na]Wq+g ':JXKg  ?4W> [pCV§9>8Ћ mٹaiieF4% mh>GMο`Q[cG1FHגM bNyE mk嘐CPжЬA ӣ.s:mѡ$ܼG1>'VhTkޚ#hҷ"*ЗD#٬hgΫ(mh$'7Šʵ^i`V@L tr~3n)aWغ,6V̵`]Jlrr#h޴PbйYKqwtD% nݘ>~N[ s\oSIWD\6#+ TŰ&ZZ2%.q 5k9f ےZYJ3Zo)OIBIz=xvsʲ8=u ȹ|ZEX.u'? 3)']h|K(o6<*'ʥC c@ѽL>Zxvx]G(ve뀐>1fsouI;k6U+|O<|>ZNd 0Gb-&VqUfU7YS-U%q6[gSYN$IN}P-"I>ĺNvO@&Ƕ#vu:QKFҋ2Q:N_?)6,n9o1[7A_#FH.KNBE/?O%zgkgZ!?oQTT ~}3\Z-^~1tGc8آO=[=0~™%ƃ> '}d-]T)F85-MO,/CiX_G,LBtmn$/#Eu& |qa1$B҄a:˷_^)2փogF\].i՞PmEe!^ rr嫚S,=d}!;O" 'a&V̂=jt*A{wXWZuQ@9:){Cf< +~N1^H+-(sߗ.N'E^i=k |/ŨkFMzujSaHf&"SHfk.vQ[~&s //Oi$zq*FM_`=41ɠ;*JmRYPwyQc9(՘1|}HZsc`u>ZRfpMij= M 1wI$]aݸ9QvEr8Wx$xjRw-ل`@Ǵ)tḒ )Y֏z&a[ļE>L-JBtmQk- FSbGކi8bPzo0B ]v23`drW֣SLrbb}D)'GR|YOZVP{1r SCk ۥsu??wC:)W2\isny\BxQk?#v/[XK8 (3C03weEn ))  lϓcʬ ];-l@^f{gmr)tO.-r@9.|,V۰_T3xD-Y@䌆> bejDeaBy«-Fבs0I>#Dߞ0d6 5kZFw%kAv?snWv"(񌧭J=WSӸ~X46#z % YP^݇s <*;7M=mqZ^^x-vkլ6ܜX.IqCbxǡݟ%Wj=; Ӌگ&47LS7T̙EWe0#xONP]GM8&yfi'zŗetfv& ?A>{IGPpQpiA o#lJZW?~L܎3*5 bISVX45a4KݦQϦm7Z*Q Vùp但#ZAOuMœ\JH2( )Cw7VA ^80 WxXLu-@Dof+Jv%+'ZD[ =L*.وkĔ2|GZj?V\,bB\'Ez 4). 4^<KNoj*lj֍r6 Y9L1Z}SQVu;1V=|%pW*$뎓̛h9nK/Q'R.V'@9%5 Cx[ [eUUHKq's7ݾDzv w#jF45ddBB#@KWUpT$Qf-՟,1̵ZʭN "'Ohb%_)6p, qFbpLvΝ#DPK ΥfR2a \澎U;D5 A6w3JEaoγs<@xX~vI|qtx?y"d &aU! |܇ʓLnKA#ssbT=^~IRcEn\@b^BtO,_#^*lՈZu3M%sS_2-p<7(H$E*hP R 7# I9lqztLJ$߭|Ο^wE8O0İ'L՗.뉮{l<^O:#sku|ckA%-lZAj0\y^VEܟX%5l~MnYֳ>țA^%)&N๰&f/`G <UvŢ~,M%PmhgJ:Kd ucZS{v#.rEn%JK4$d7Eǧi>ej ,Gm@I cJ\qPX(*8G ~.}QL񑙝HvҥW<"0ᚘ[?brVHN.+$6q :Ĩ'͊;iB aRh袺ӎdIRnYJY|/]>==:Y\ו OoϠj PIdUu+c~Cȃ4 RH  J)^AozH xsC5YA1d+ ,-!3? S4⍸5@'FNgٕ/]'ECCK.V-LEu*Dpf3AIԪ_!GMKC&$ZaU"if+Xj,"NW(^hBj: d`[ iT3jsڎcn#~2OX|}&Io*ٚA>6< 0yb9!Vi 2#]}70-eB=o0uXJ_q^LR$+79I_ϫq_Eu$7 0bj&FZ<@ @*hvCp4o[ם h?HI+;Q׺' eUh!-;d!so0c<} thmh9`Ӯ2 :M\[$ [&:2P{1r SCk ۥsu??wC:)W2\isny\BxQk?#v/[XK8 (3C03weEn ))  lϓcʬ ];-l@^f{gmr)tO.-r@9.|,V۰_T3xD-Y@䌆> bejDeaBy«-Fבs0I>#Dߞ0d6 5kZFw%kAv?snWv"(񌧭J=WSӸ~X46#z % YP^Q< ",6DNEXK9,Rwb*$tT?%J≣hiAA$*ϴzOU:@ K Zop&@@ۓt4V-%A2ʊf"\0PwC[!!7w)@f_6EidL;$aQFb_@ɵa‰TLjDQať3llYeU 2 l9pj=SJPGñ68Z0Tk:*.v(pj/"ț(.9bM- r?zy;{hI Yލ96 ٣d%疯<evu/m}GU1A0&9a$p!y47#1HZwF(Lj&3#X+tܱaC؏'coL:BC?R9Pͫ%}tcȣDijpmc}CN/p<*WW|=mM<& TF G m݉׻F,+ݧ7.Ѳ9|X7qUT:N{ixۓĹb[p#٧#Tp!a1wIMФJ p{H1 (|:"r3:_moM+U~YCLաNҦ8dea(eY9'b(F%Dm DQ9H+تPN`ˆc8GcM'laa)w"` ňFSQ C1{Uj nRGM>EGDn7k3K9HAB V6 ^Sg NEgd0Kg {|8Gt9!nZ dxexOcf:W1Ǡn aѻa0 Sj N樆v%-m|w4&Sa3VV\CdYJ}-qV P[ ,ŗOAIJZ.$Vl1BD2{-Hg؋,Ԃ- d7IHcmGU U9\t'5´.3NcJxk,P02pvE*e GxhUP]C΍{PAԪ*~1N.7׺ F=|Z&v0*MÎ]S{ I09`:\\Tetwk ӍIRي+ H-f\vu R7Ӛ:{BR^Ÿ*Y\4օdx-Oj2wzһ)w xN2,v CX( 2hjR@sǀ]b n03sc> \!Lm/q3@/֯LZm/%Be6G ys|)3|-|V]bf6?C=VviA&(,HŊ7nztV'ZbDh^[PTrpB$_vcR{= Pf#ST{?,Fdܘnza&p>IjE/ amz݉Sq O.OS 8\_goQ_#7zٮ}Dw89?iOօ.G6L\v79ɸz/`VޛWT US+Br' Fío#zr#CFɚE ;ᰲR]4 t+:֗D6CCEUi/~!XXɌ\3)81sI[Ɣ}OCc{ܐc2I[+ŒYSOY^V>=e*);@k`_zzHkWO`isĖs5JNU"F( >sY5[=]?䊜.&JZO\Xf%wZ7=V5{ Sx D)WI dIgM6J[ؕz1k0P{aJ]xU3" vUL)&E7zFK{Nt}IuvP]]#vri&1#E5.@]jk>Yu{0]xxv*`ٵ#̋-I 5Rnة^>D Xޱ >]ņW~JQNs'\# 8]mZu̿uKv6%M2 kE5 g&[;Qn3 /'#fvw1Jm1s$ib{Ys(MP66ZEm8C$c>!njY)LuM=0=oM)nȡгD:|(0z =0.c=o/Չ Sx /G N&߃x&=ttJzD@]koi+lL;j fdP`}3j>UpBW̥~=z#0N>v507sw`rhgו(ݦu  ՑV-]B12jesMFKJ@Fx$O@y7s+ J7O(Lt-"bT^<$F?mbƫ#i{j*Cٜbs :rB c;p\ e<A'2 P  vp,#$Z_gpȳmvNM(<ΠmSF幒Xර\K6 S *CC 2w Y$#ps`j7'Mѐb-⍟#&/QhlWZ?%~&~.jy/I8i6J*[A\(, ==ނwwu!g{oC*^72F=ݎѱ- V`9Qö 7e ,čR.VzG,$vi.hh:CgĮW(ؾ]O=fRy dC7]\썚޻ܷ!0:`/mȼTީ3ZmػP3֏;if(&DC±2wgiQ䷂R= gSk#!msD&;"Qb"=|Ni=`ǣiϸ`U5/QEjkp0Ep6ʼ|!Lڲ&c_nGQ,oF5OɿE#++$=tP;E%fjwvEv:eMY%cYwd tSK:48NjM̵=DVTu]!wQ7 ON|Y7 $O>)W`O*CUd> #2_G(J;iI̶D m<t`{ú@ntf(eڧkDecIw5 %ғJQ/M`'gBx-i&.,3"0S XY*k%xo|!N]$3泩723D61R "'۶tN>mO3SjZQ \DPKaAVOIƗ.jiBoQ0uI*&TZP+ .m nwYM_}keT]3Im diէZErSˮ!^W,,2]/898(z//,R7$ %IʑO?fac/q*O>kȒg- 2ǞLoPo~K.Gj؛z9-]NߘG vsSqg&DG+fӮOφ me+ bP!196Pԅɇdb] Tx(Oorag\,@G-ݎ|TP޲TSSZA@7%-M'[/HO=PVs]{'zP({S ] کEԣj\. XF?i#]CVZ2FvaJIXH)AOQcmfJQ1E6Q:`Տ,Xrފ A6ņ _.fv ANɜO(Z$zx+dtSe\U͞> 7Έ=r&*RQ ai3*&/ F;5 u^xF)JHzmNA쨉SJj -WC& 3NZ @|ݒɪ9ibX۠(ȚS|ƀ]݌Wn0Q`.gmW W렅~ rB*+6a? Ц8nrv  ˜n;#;!> LA2ޞ2,+ ˲dK$)MRëBَ,,4btg{ɎElEam' .&Y-oa[>4pfg؂:2_uOVꘝvl.z8ZZ![cp$u^8hoʺvO8^Qq"3c\^On z!QUmLaCLjU~R3_z {FJDDlW[U*XӒa$mONɘĚ;ȏZ2dX@ύ4NS1RÐU yd|"vԯrwCq=(ݿv_\X5ӉSL xTNq` TB~L}OnQ2A i<V&Ei6uA|y"8T5tnBSuw) 9ezmlR_e9m$GMCtxHc5x0|BZ! c{7yґ 'bb %<)lu[cZ؍;Cԃ1SmPҐmnVz'ޕOn@ ޘ"~^0C8ߵёC1il/joBL\|D_Z~H?Лߢ[|:q?W~W}f4Π:U<#%r3.kU!n<~kO9b"b0j| Z~Qmɘ!Cԃv/ #Xtj\"MTc,<9s`Rk?%r#$5UnM#yJxAxҏXr1TsA6&*$]{^)Voin}VgqzxX?&oQH.JM,nKl_U]{P zPT1xc6,ı=E9y*dP;crS| ^)+2*k ' : {pzn& Qy3r:}J@[,^u,e,nLz+x 𤴩diҝ7flaR)ϡ2,ZtȋhDDT( ΟƪI&%3l lYPkf&O24/bВDW)QW͘j,\3r$(F(5cqy9Ns T9 Y. ì*b #ʀ"|h}Dk`ugkV+R.KBQ2K=#$eYQbְ]異Tױx*^?=<ܔklx$UF6Tt8@YYLH$tU;f!Wg+xҔ5h'k4Y] K;aL'y'Sxg2~+d9jF^Lլ&G('J.3s]`1Fؾ&DO57GDS:̃uwvcKqG)nuFp,$N l?B{YM3cL %EKf)*_E5C(ʚcT >zA{&3zs|I%'Z=xsӉT:$~ 4+)6 A|YIV&؇qO Q/ :Xv=v@GXŘfDJ/+و0/iRKb$V_^(\\$#ecc2ϮO :F͜.G6+}]n i]ҎٽOw/r@uCK@>kl8ѳFͼ)9ST ֐q0'AoO]6j}\ tztSKs4ۛ}P6KC[ Tuyf ;[ rwgw;Be13 }v7.ő[i#5Rߥ]{oH鴟aCC"gzuN #]-e8pZ.a3eWCIHt,`\#  A/am5u#Q%/^l|8Ř{ocTgI ͗L9Mc? 'y. Z #%[]ȍ}㭏2Vx WΨo;s04Ż3["k :Vۄ]%HMHD_jrUBq}VfnacHW$jPZ >9/T]):wl2 7[4C+P.^4~Ua4Q' bO*>S12%G:|0!TcxF.hq\Tk \aR פ]ubˠˇVyA_n2rN GK~r[YS.PL R1@,w]ځp Wk(PbudGLş]5u lll>JbŐ.UKg[zE'?pwa%xa)YF[]{c$g[[ "XB!F(1#BdߺDn$tjI<qz1F@}D67}~`̀¬/1ݏVi"zH.[$探k<?': n`dW*p59I`kL< vb鬚*]zKi\ĠvxiW0@_eN,uЩdqWqJyfoyÔm9ΈXr O,+CWIWGT v}gs;Q-NU{o_z m X1G9`@# C˂H1W#n;Q9~#m+=~וMhl џh0. e՟H*e::JA҉\Axu;PaG;9J.ڡI,A(zIByBd(^+FrWMb^ύ@iMk8+F/u5#h>%7®ZJ!S;1$A^1m6谌L&ʰ|Dkȥo^?s ))OG* %a]2Ѣtm19*NNov Wl)>5l`.0$$+~j#]1Q|p[ĭM*~,ֺ. SL  ZƠ}d5*pɶ,8Tn׮›l$as fx9J:u ;k%[RQꅺQ-~kKn{%4kX,fBPƓ]q6t)YwV U~)PE{C e+^ŇdDt9o\|3!<`+S'?!5vJ#W}jk_ /wƾw!kg=$N8x'9gMkTzә]"#,]ZuehtJsK`_f'rc ?vn/휛ZS. m S a;D(:yۇIɀ5Ջ@)*U];:v})'a43рP⎜!稷Wtڰ>bVy~s`t[3XÚƤp,гH-)CoMi\K]i`1¯-R4p`U,SPD0u!~-#5Zfu.5+i7/UZ\?p^ֲT.a٘ L'0CH5_퓌Aby5T;5h7:6zHm:Bg-Ѫ*8h;>Ŏ'B$99M w};K&Έ6%efPV%D횿B~a{+Ol" S 0 ]pGYu V>9߯/ԃ M~ qY":R hݠ]\Mgol3h;[Fk0y%kRs=v:Z^~lrh$)p[ӴSV7tI _GlerR.b (Z|So:zM~W!…fF-El"{2&gsT ۊm /]5OH<%Y^w'R)G`̕L|r$`xu4`PbG&aRJ;HCww%g]Ē>9sv /wLYu3ZyI)}-8:AboD;{TU0v7QR\neYNI-=m$ 74~XQ%&%KN0 6^"jV S9 t7jGo So%^W|uKP9$VAG#)fTBd^P~ֺk*Y>=LʷG; GwnZZ7wI4%g"Q S J}O [6r^$)Q$ĮpNZ/gOMIH*vaˆ؏r."UNS⹐;Ʒݡ_$?k& 1zgJQE]Ö֑M TzM_MP7x\:S\12Z\;"-2F6Y ̜Ǩ7%I\ߗ!߶ leMJ+Z_PEU #Ħ/r`6fuXJ\Ȧٺ?t$Qq 6 XxI zviUZ9PPd܄F FW?Fxqua( 2~哀~jXۛ_s@9}lhro<6#"8@1fD1vȋ $IFUFRR ) Ip FG{?f./۴O5-;IT0!E_X^Ub _ }}bZgz0"呔Њ9Q;9Ep+7.afF&cJ=sK̝ b:w/WU2 ^~DJ.^,̉lg1++{u'ޔ\:Y3'*AC-mI6I >'li`PKt"S=)oCpC$?,f}!vMA2L299F'Y`NHG15.XA22l޹)Iզwyܠ0F_lYٯGxrGlYhlhxe@4N 7f;3->ƥD_;Vs `c[xة9p1˚h_2E=UdEcᆤ#e+E39CMZ9PƵ'`NsAQB[ -w%Vu<%7ҠQ>$>0wz^Mx%7 b!!BUf6'jW #&GnLpV hЯ-hxD}s"skudx@Z  q*oziaVuL ư] TBiitEV n|떱?|KL}PEBv}b}؝,mm? XpᐊA6<ϡƘEm%\kљW8yR_lɑAiU&@q9(zyp*Ñm OSӞ5 #VkdU`#΋lxJkSHRQ$9()0mރ`C! P0RVļp PD=9uQ"|EvBzqDoar7y!1Kj7ca}HYo`{,+<9ym&ȴKg%~hrڕҩiOFBU(oo7G+Lxt*+'(v| ͪtWűb ƹmC?dߨruI(566 SVMqw_4j=f0Ulay=+{H&ֶ@rh<'Fz#|WC Zy$&n7 #5z@w9x F jİ'F@~ww-:U ,CgnǶ*@‹+{93|ѽ=fmjS H}-]"xI0(] 9 oݝk*4f~^:a;Dd97״y?>`9%43sGٺĮLZAa]xM߀W%ɋz33>8Y]@:BҍyA^f߉X(  e[%nx}'g+~Rvx77oz8%\ r ' qix)J]f2ːlB_y;9åFndX@%IQ5>!Pr3iG/$INgaG7YD<'Pdm֤磓4 z'jo~%|s &b `{U!!Ck"bdrJ+g}ȒEo'9U0*f|o4odٛ`ӼOX /$d4# V5 DbtF,<$x$L\d?@SĻrڦ<ޗc32k߯J,T6Ģ=J_̋_Y5|->w\ Kr' t gDd:)E!in֚?_ӔDj6aLhعU:R#_KHE~6qQ1穣;qCY>Fpmݐ^ Rs{_.w]C#'Hʪ '}d-]T)F85-MO,/CiX_G,LBtmn$/#Eu& |qa1$B҄a:˷_^)2փogF\].i՞PmEe!^ rr嫚S,=d}!;O" 'a&V̂=jt*A{wXWZuQ@9:){Cf< +~N1^H+-(sߗ.N'E^i=k |/ŨkFMzujSaHf&"SHfk.vQ[~&sV1 1Sx)]O4/&˻dx!3j3MȒEřLpSK΂"ktnYd4؄$,0ᆊsvH񴈐,3 \RfA ˶Z=G֚j8^[ґh&!qêij˿1!kT=H7Uc$@y hz;. X3cbpXTy|V^D7CaڶeCZqz8t6nEEbEmPfؓ /YgRtbzsQyM ߡ`?/o Cf;|[Q$W@i%ͲI+~XCodObd! C+=̃<#iBTȃyIY ԉWB x!{j_ܚok~ęEG *풹|Dc. Mz @M;ݿavz,)7'+ѧhR@DH$9'~T#V]yH= U1Ht8ii~ZHgۇ ѡrf7gL}=$e?y"AqG/&C+e(_I3=™WC׵@vk&^>xm4e,/)"XZ+`Y*uNOYy-#H.Y^!QhWL}!Cۄpʫw61F|iU`?4NJfz܏v:C6ߝTJqz^\xͳ920`ݬy})6HWHx(q2Ⱥ:΀ncwxDqԍTZog(YަøY*j1:RbkĶlMo4+!ޛqزX~؜ U} [;`:iG4>GFpN3yg7NʟTT0܁y}v&V+:*/d!C9I+(u8#^}ZVq[&dw6=@Y.:.B*?dTx^rө}'!EFX'5R~&k$KkW UmOC[Xsɠ˿~Z* a/oh[mk[НZRVAdK>E_[bq!霡5ZyG>9Pcd t4e$&s#2l>VGVMCh] ?XʫqOGc/Hvb+Rj\bs^vzcXx?ʉ Y bl-6kL!XG B9~t,oq#*NpD0>06<&Ts|섅iqE*r/oq<0,]XbݒDsIPߚV`K([@j DU+ G*Sje1tf0F!?H)({&ir&򆕧D\+Q1^xᓯy¢ quJRȑ;< o<0.Ec#dZ xX}h1NUvwbH.+fVϮ3i[/.vN5 J^(5oP3E%D:mxvA BNwI@8>-#~mfy {qs*%Oɋ7P@Dye\SX}=B1Q(OCDӟgy[6?WX"U vqrѕ1?S '֗ SK~(rEK <`>fo,Y8 Dc~BD.X<:/Lڛ62i-݃Zd29%ЅF")(Z,;"he.9M /QQ7zEwfwle"2gylXl zcv"ζ,?Uy(>tr7͊ThWTNnpn#^#yRVK f>Fk8/6Wx1_ZJ[U \~7}Nޟ GoLpWhh+R^Ap3`k>o.+h~R %z+_TX=cSRNX( Z NX( Gp}݆sa?Y㞗C2mO$CsȜ]Hqm$*CAc*41!ڒd 2q..B@ TýAꢯ#][vCb5,'2H H|$pĢ - ʘOږA;<6@-!悳i]n.{q׵O9?eϻrJIWah#[p%b,H"G7>c;qED@Kq/' `)x%l+qiV*),ZMvXq.N*gPlVlM 2戫mpCA~sL6h+$w"}3 !&Ѯj5J"Z̦ j5J"<5_ƽǞ>BrROZrcZ2 ogݰMbHƵRP/@|.B G-Y/s}\;%XQdOyYq!•zhtokg!R| ԃqoФJɫ1pcGweߓ HWئ]I>'^I=J]ո&׆9 ^ݐK&j|<ɻ ڮΨMt)6a#aYnZЇqi7^z%J&LD%KnD:sɩ'ϳ"|"٭V4|JIw'@~JT'@D$Կ-I3NG\\+\_d!/ 7(l9Nn3Ze1 HNОȞh۪R&~d+WnpbBV ]]bjW"BWU_1ugl]KG|S= !yʢ,ۨm݉[g< K m݉!|/W?OX^طHgs=%ovQ#imEeljǽa,O<"j^a$y8UK=29hȹCÀY_f0J_}Dvl% TDưtOS-2?`]hISwŨ t5צHM +fIGyx$[o0s\,潖aR[2 l-I8΀FJDO'^O!q-u1.|[ ,~\9)3D_cy8пV3!G}=F.$ҙ\9 $ҙKʸa)1y-@,8v=p55DhCF8 -0ľG| 5J?kJk9"(Aj8DR3sD<^EG[B(L!7q 0]Ű1'90lmw*2 /Q~Gbg_8cIl?=L'P1%/8M)6eE vF&בc;'3]$~ÂבdwsyZ}Ӧd6C ~bm j'4$CTsO]qPY.cDF\.kC?ټoyUhb6)Ms*^?g ~03dNF#H8 iU]͉(-0) i8P,&4Td./!9?LZχ L^c2eZC9@֜L˚ɧN*@+:*v6\ 6yEL8] Nɶ<8@M =$}9 #!)JFa[x +g[4S>  +gzVv6`8,}Z0sqBC[r)1L3 VWs偗]},<^ 'x|.+hF ,D*Oi]XTI3\ [ Gi=}l^zX3P?䞀^zN"j܀eyPey^S3nGz(r`?)m(`nLoһ:,,QLBxo˂DmT~d%^sj%YpWB%\Z0Ѐ^&+g[.{LhܐfaSiuekBReEv./쾞`FtS = !yʢ,ۨm݉bi| Gq m݉=#Pbo*:O| A堲8-mZjOl1me,j8$`a.r[ Eqd@Em"[6)0׍Zv6&ݑrX JI݉;SP;qI A}\%S\jSr>_h`~;h#G3č3syHrX,a4Aݡun"/+SɘjZy~r&ve(M,9k]r8:.J%DCbXdmܹufnė[:°yśR.cW:| %uT23.3둓#|gdQ(?/w sa㬍DJ ) m݉] J tA!D0 ,foYZؙtb{\ mn-"YXMKJ| WrzZE둿C%1Vkg9o雸J}S ozA4m '궭xN{\ŽS0bvIxi313.ff-yMARtze v /&"9Տo>W&SyC3s _)] J tA!D0 ,foYZؙtb{\ mn-"YXMKJ| WrzZE둿C%1Vkg9o雸J}S ozA4m '궭xN{\ŽS0bvIxi313.ff-yMARtze v /&"9Տo>W&SyCW&SyCW&SyCſ b'=i?z̈́5y"HpryK 8t*Fr!w_ C&\YɊ`;ؑ@QiJ7M0kz5G#޳[ &!yʢ,ۨm݉_ ]B)] J tA!D0 ,foYZؙtb{\ mn-"YXMKJ| WrzZE둿C%1Vkg9o雸J}S ozA4m '궭xN{\ŽS0bvIxi313.ff-yMARtze v /&"9Տo>W&SyC0^ȦJCLAQFjBEʹ13c^O-tz!*5fqwN𢢗8a=/]Dyp @s<=\ p4ȥh3FO`F,z>I-1p*ۮ7~Y|Q4CեpPt@|PfTwe aLQnk \<^hwwn8䏚`_ ʉ[ &!yʢ,ۨm݉bi| na)] J tA!D0 ,foYZؙtb{\ mn-"YXMKJ| WrzZE둿C%1Vkg9o雸J}S ozA4m '궭xN{\ŽS0bvIxi313.ff-yMARtze v /&"9Տo>W&SyC, #[arg(long)] pub commit: Option, #[arg(long)] pub secret_key: PathBuf, /// The binary file to issue as update pub path: PathBuf, } fn get_commit() -> Result { let output = Command::new("git") .args(["rev-parse", "HEAD"]) .stdout(Stdio::piped()) .spawn() .context("Failed to run git binary")? .wait_with_output() .context("Failed to wait for git child")?; if !output.status.success() { bail!("Git did not exit successfully"); } let mut output = String::from_utf8(output.stdout).context("Git output contains invalid utf8")?; output.truncate(output.find('\n').unwrap_or(output.len())); Ok(output) } fn sign(data: &[u8], secret_key: &Path) -> Result> { let mut child = Command::new("sh4d0wup") .args([ OsStr::new("sign"), OsStr::new("pgp-detached"), OsStr::new("--binary"), OsStr::new("--secret-key"), secret_key.as_os_str(), OsStr::new("/dev/stdin"), ]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .context("Failed to run sh4d0wup binary")?; let mut stdin = child.stdin.take().unwrap(); stdin.write_all(data)?; stdin.flush()?; drop(stdin); let output = child .wait_with_output() .context("Failed to wait for sh4d0wup child")?; if !output.status.success() { bail!("Git did not exit successfully"); } Ok(output.stdout) } fn mkupdate(date: &str, commit: &str, data: &[u8]) -> Result> { let header = format!("Date: {date}\nCommit: {commit}\n\n"); info!("Generated header: {header:?}"); let mut buf = header.into_bytes(); buf.extend(data); if !buf.ends_with(b"\n") { buf.push(b'\n'); } Ok(buf) } fn normalize(data: Vec, signature: Vec) -> Result> { let signed = Signed { content: data.into(), signature, }; signed.to_clear_signed() } fn main() -> Result<()> { env_logger::init_from_env(Env::default().default_filter_or("info")); let args = Args::parse(); let date = args .date .unwrap_or_else(|| Utc::now().format("%a, %d %b %Y %T %Z").to_string()); let commit = args.commit.map(Ok).unwrap_or_else(get_commit)?; let content = fs::read(&args.path) .with_context(|| anyhow!("Failed to read content from file: {:?}", args.path))?; let buf = mkupdate(&date, &commit, &content)?; info!("Full update: {} bytes", buf.len()); info!("Generating signature..."); let signature = sign(&buf, &args.secret_key)?; info!("Signature generated successfully"); let mut stdout = io::stdout(); let buf = normalize(buf, signature)?; stdout.write_all(&buf)?; Ok(()) } apt-swarm-0.5.1/examples/p2p-launcher.rs000064400000000000000000000113571046102023000162350ustar 00000000000000use apt_swarm::errors::*; use clap::{ArgAction, Parser}; use env_logger::Env; use sha2::{Digest, Sha256}; use std::convert::Infallible; use std::path::{Path, PathBuf}; use std::process::Stdio; use std::time::Duration; use tokio::fs; use tokio::io::{self, AsyncWriteExt}; use tokio::process::{self, Command}; use tokio::time; const LATEST_CHECK_INTERVAL: Duration = Duration::from_secs(180); #[derive(Debug, Parser)] #[command(version)] pub struct Args { /// Increase logging output #[arg(short, long, action(ArgAction::Count))] verbose: u8, /// Path to executable to run and maintain exe: PathBuf, /// Signing key to query for fp: String, /// Arguments to pass to apt-swarm args: Vec, } fn sha256(bytes: &[u8]) -> String { let mut hasher = Sha256::new(); hasher.update(bytes); format!("sha256:{:x}", hasher.finalize()) } async fn query_latest_exe(exe: &Path, fp: &str) -> Result> { debug!("Checking `apt-swarm latest` output"); let output = Command::new(exe) .args(["latest", "-A", fp]) .stdout(Stdio::piped()) .output() .await .context("Failed to execute apt-swarm binary")?; if !output.status.success() { bail!("apt-swarm did not exit successfully"); } Ok(output.stdout) } async fn random_suffix(path: &Path) -> Result<(PathBuf, fs::File)> { let dir = path .parent() .context("Failed to determine parent directory")?; let filename = path.file_name().context("Failed to determine filename")?; loop { let rand = fastrand::u16(..); let new_filename = format!("{}.{rand}", filename.to_string_lossy()); let new_path = dir.join(new_filename); debug!("Trying path for new file: {new_path:?}"); match fs::OpenOptions::new() .write(true) .create_new(true) .mode(0o750) .open(&new_path) .await { Ok(file) => return Ok((new_path, file)), Err(err) if err.kind() == io::ErrorKind::AlreadyExists => (), Err(err) => return Err(err.into()), } } } async fn update_if_needed(exe: &Path, fp: &str, current: &str) -> Result> { let latest_exe = query_latest_exe(exe, fp).await?; if latest_exe.is_empty() { debug!("Could not find any exe yet, keep using what we have for now"); return Ok(None); } let new_sha256 = sha256(&latest_exe); if new_sha256 == current { debug!("Already at most recent exe"); return Ok(None); } let exe = fs::canonicalize(exe).await?; let (new_exe, mut file) = random_suffix(&exe) .await .context("Failed to create new file for exe update")?; info!("Using path for new file: {new_exe:?}"); file.write_all(&latest_exe).await?; file.flush().await?; drop(file); fs::rename(new_exe, exe) .await .context("Failed to move new exe into place")?; Ok(Some(new_sha256)) } async fn run( args: &Args, mut current_exe: String, child_slot: &mut Option, ) -> Result { info!("Started with current exe = {current_exe}"); let mut interval = time::interval(LATEST_CHECK_INTERVAL); interval.reset(); loop { if let Some(update) = update_if_needed(&args.exe, &args.fp, ¤t_exe).await? { info!("Updated to new exe = {update}"); current_exe = update; if let Some(mut child) = child_slot.take() { child.kill().await?; } } let child = if let Some(child) = child_slot { child } else { let mut argv = vec!["p2p"]; argv.extend(args.args.iter().map(|a| a.as_str())); info!("Spawning new p2p child process: {:?} {:?}", args.exe, argv); child_slot.insert( Command::new(&args.exe) .args(argv) .spawn() .context("Failed to execute apt-swarm binary")?, ) }; tokio::select! { exit = child.wait() => { info!("Background child has exited: {exit:?}"); *child_slot = None; } _ = interval.tick() => (), } } } #[tokio::main] async fn main() -> Result { let args = Args::parse(); env_logger::init_from_env(Env::default().default_filter_or(match args.verbose { 0 => "info", _ => "debug", })); debug!("Reading current exe..."); let current_exe = sha256(&fs::read(&args.exe).await?); let mut child_slot = None; let exit = run(&args, current_exe, &mut child_slot).await; if let Some(mut child) = child_slot { child.kill().await.ok(); } exit } apt-swarm-0.5.1/repro-env.lock000064400000000000000000000467301046102023000143430ustar 00000000000000[container] image = "docker.io/library/archlinux@sha256:068aa6bfc1e735cdf9be3dbf66327011f99126656f479168f479d68b28181106" [[package]] name = "aarch64-linux-gnu-binutils" version = "2.43-1" system = "archlinux" url = "https://archive.archlinux.org/packages/a/aarch64-linux-gnu-binutils/aarch64-linux-gnu-binutils-2.43-1-x86_64.pkg.tar.zst" sha256 = "cd9065d56c56570322c9d0b63411d86ba95a1f23932100ca2107840363622f8a" signature = "iQIzBAABCAAdFiEEjhmSFnRl21+wRVV8sChU7XU+Dx8FAmc5MB0ACgkQsChU7XU+Dx+VfBAAlw+yFzHoBqm6xIHwF1Q4iR6M2x1kgQstlfaHnP7nL6EwunhmHGQIDf/4Zc2tNqE5q5v8lmHv+YSBO8L4MybyxN/sFG2rv78fAlyJx/UFER92DbMJvHZtZoF2cvX+pvaczw6/rIX77x9PhnzKQASIKXWKsu4Uy9jbZuZLd/XCILFl9kPwFqzNDxNL7pRiakYUsSM8xcXZFUg8wOO5DogGhB0lo2v9mbDmNIkMWLuPB9RqxSk3MkXaU9aETx12bxCbrdmHQHlBlDvEpfDw7wKGUOQTmqXB2h0OUYbOQ7xieyJA1CJ8/K7UL8XEKcmjNa8jaLClPaaOOGju5btEB8VH/GQqsUJXI4rGyFDMJOlcX2+AdBJwSAVO2j2LWafg4Mu+tyfjYzOALvhhEHewyZmYZih2YpcSOdTfdXakeN/gMsg3zNyM/PJn0K1k6CP006ILSSVJHKDIi+CkI7eEv+tbgAj2h0RJxue+YoEqa5M64nJTbPyBV/F9X2L2E4sOLr36z8wGRh2tc2nxWsdntHu3+XE4Jks1imYq6GJUTDUpOgbwnDmUY0eiyQSd8CSvAWdRS32mPBgwOSYbmxCZBK8+MioXEvvg0PWH30o7B0x8MSlb4ZW9EkCvmxhUfWfOzsBW82lVKnwbfg1JBfeZpWBzetI7hqpmGippwPfwleqSet4=" [[package]] name = "aarch64-linux-gnu-gcc" version = "14.2.0-1" system = "archlinux" url = "https://archive.archlinux.org/packages/a/aarch64-linux-gnu-gcc/aarch64-linux-gnu-gcc-14.2.0-1-x86_64.pkg.tar.zst" sha256 = "9f68a3a00ec1a4d78d416a0f20487de0bf3d57a35f3a537062b4a0d072c19c19" signature = "iQIzBAABCAAdFiEEjhmSFnRl21+wRVV8sChU7XU+Dx8FAmc86w4ACgkQsChU7XU+Dx8uQA//cuxU1P/sWJyhMU+DdBvDJmbdcDWpdCeMce00XIHuQcJSQv5NP9u/rTj/VuVZfBlok8djbp6r1LM47UEYemVPo/0EIEjEV9mYBmywi23+toF++2Wos+qi6UstuDf4hBMSjnxPpcSWWf3SB/gjpMz/IbVwTfk4KeTYy8L/PlohlFlScd6uqADmdfZFKIA0qKOqHMMiKKP1PA+hIcsy3giV3axiK/TQnppRwogigrCHVk92zrGK2achxvWpVvD47ij4V8BrIdvClBfAmMRWDGVqXVhGKr5+EgnCZ/jWdOSQckryvTDe1rKvmiy+CQ/UonAKR/uvUsnZ2r5an1L+Xn7aNLBSPXHrv8qRpmmxSsWYaTiCR5VY7ckaAU8u78IpjNcxmnOcZVdhqnUDuxRWNVvsg6GWvMnowoa8/xlxotz+HxDFiS7mvnf9QITTygzXjXPsVM9ufkP181SSPUEwTrn/V6MCl7NAWuWkTWvZ/h+WdCvil0ymZgulDAU5oeXxYcg1UO2OF2bmEUoi5uOomv+7Rz523wgwOZ3XzQiJN/dEQ4q911vIcDWu9xtW1f5Lvy4lDp1kt37IJaFmXnCX8LLOod6VrGquP+nkMQTY4TA0YhUW/XfoWqWAQ215WUiwXkKbPo48gBFouaZrlgfqI6/kRY+a/uLMqUlWPb1iavgUO3o=" [[package]] name = "aarch64-linux-gnu-glibc" version = "2.40-1" system = "archlinux" url = "https://archive.archlinux.org/packages/a/aarch64-linux-gnu-glibc/aarch64-linux-gnu-glibc-2.40-1-any.pkg.tar.zst" sha256 = "0e410d29c37ed5af0a4ce0e90103cac5cd78c114d238d7770543b0b35e3c313a" signature = "iQIzBAABCAAdFiEEjhmSFnRl21+wRVV8sChU7XU+Dx8FAmc9CIYACgkQsChU7XU+Dx9XYA/+NqMAx/f/orVvkyx2hG1H4Aygi2LVjIG3ca8hAirA3beppWTOGeMSbLRPiOvfH0wGWAbOipqng/312khj36N3EHI8X80IqwyOkxpO24aEuEOFQMH+FgVgSfSiCF5uF1hjspvm0WDc8/mSDsej1vryGacIqh6x0JqzdlXcp80D/jpKvewa3JGheHWei3CAgktKw6jONVBsGiLlkhTm3XrOiv+NNSh81bw3ofGme74j4uQEi2T0TJgw4+LyJ203v30/dxGYtT7A5hYd4+L5vxXtju4Hz7YH+xtQiiRMhR2pcfTS/gdk29c93Uetfb5PHJKhxleG+hOXqwrOfmWPCOZ55mgXDzLHgsI/ZL/gVtasyKorNnYNDZcuC3uIV56e+3GQpn0oeFI8wqT6gEgMi2wbFXsUQqeTlTCSx95CCkR8LFvoIDLQexP6Tu9iC+UYCetF59BVCZLUEVCUP0N6ZpMmk21hesCKAaPk7foNNuXdmOzduZZ2JPcsdNy76DJIR26nbk95jxgxEPEawDhum9nTE+1c/16trcFidNzTTMmwhWRa81qZPQYgZ97TeK8QJrjT+6vXu/+HNfjl5SQ2CFxHWoS/wTFmY3gWyerTM+C48l/4iNg7pHF1chNJXEvzPaDypLtFDt78ItN/5Q0g4usQIJnoNZqV0Sn3SmKNW2BeEvY=" [[package]] name = "aarch64-linux-gnu-linux-api-headers" version = "6.12-1" system = "archlinux" url = "https://archive.archlinux.org/packages/a/aarch64-linux-gnu-linux-api-headers/aarch64-linux-gnu-linux-api-headers-6.12-1-any.pkg.tar.zst" sha256 = "500d6df001985aefeb2305d5061ebde6b5cc7f67d764827f99d2e9de19498450" signature = "iQIzBAABCAAdFiEEjhmSFnRl21+wRVV8sChU7XU+Dx8FAmc74MYACgkQsChU7XU+Dx8dPBAAimRTvl2Kgm+AV5rnmsb2rceOskQ9L4dfcB4iJA/dKGtHB4jnzlGfYez3v4T4JjlwVsbfWcFN47CdbYChHP5wPOgNYNo76B3Qy6eMjpzu7+I/wkI6f8G/oKqYfksaJWp94z1Br5K/Mf09HQCgkLNHtNFCUo/ZEePRKYw9Rcb3hOUZZ02pEcNMy1VtGP25+2beWTr+K9MYgW/rxCTjoRlEVgggAbYU7MECTBZlnauP1VsOqwuBl1EaPXzlcBJX+KODnM088TRMIuLIP4mOVDje2cxhtTyhkMirLn+YYhOhPtqm2r0VgEQgApDYsd3zOujN26lVvefn/Y1i1EUTaK1Ej//K1KGUYEUtouIgXInI0a2PfjSOXn+21c9vTydBZaP9A1qHaw8SA/P8lr+vTkxhW03KPzZ6yMHohzdTRL34lrVjAV/H+yYpDHcAFuLEnHAOs6rnpCwSEGd9yfbieO66lmxNMUdYw/RaLZNtkjIGd2DNOZ2qky5LyxuNx6ibu3MSx9kyFQJFQAqtTSgK2bttbbHVfangSEcV4WK4GHUZ/Ljjb+8qf/Sma2OSbpGBCZQ50Jh5W9ogQ7Rb0lsUhD3OU9NNxOjs2EM2NhXd+3o/7kYjoU2JUrpkDQzCkvgrpPzCg5EPa3shrVuM6zXKT7W8/ZLvONVvhi5ntPTHyMzfo4w=" [[package]] name = "binutils" version = "2.44-1" system = "archlinux" url = "https://archive.archlinux.org/packages/b/binutils/binutils-2.44-1-x86_64.pkg.tar.zst" sha256 = "8c14a56397669fefff067ec2c08aeccb944372be4f4cdb6fed0991ca18c4fb02" signature = "iNUEABYKAH0WIQQFx3danouXdAf+COadTFqhVCbaCgUCZ6dOK18UgAAAAAAuAChpc3N1ZXItZnByQG5vdGF0aW9ucy5vcGVucGdwLmZpZnRoaG9yc2VtYW4ubmV0MDVDNzc3NUE5RThCOTc3NDA3RkUwOEU2OUQ0QzVBQTE1NDI2REEwQQAKCRCdTFqhVCbaCjeoAP9btSaBFNMd2M64KII1QXneh2x9+xVvLiz3YZ1kbNMknwEA4+KjPA7GZGgq1HWZsjLuTUWzu4M2D6WBXXfH9HLbiQ0=" [[package]] name = "ca-certificates-mozilla" version = "3.109-1" system = "archlinux" url = "https://archive.archlinux.org/packages/c/ca-certificates-mozilla/ca-certificates-mozilla-3.109-1-x86_64.pkg.tar.zst" sha256 = "253ec0fd18a3743d15f70b384ebf1cdbe2528b16bb53b1c08821166c1fb7fa34" signature = "iHUEABYKAB0WIQSDvIiJNRtd67toQW64rAhgDxCM3wUCZ8S+bgAKCRC4rAhgDxCM33m1AP9ulEF1HWvIpOYCe+kOZroLHjYkGyncod0dEtK9q4sk0QD/TZRmGgQOu29qfpgSQBQqpAtgQ3r+EpN/7KitQ8jv9w8=" [[package]] name = "coreutils" version = "9.6-4" system = "archlinux" url = "https://archive.archlinux.org/packages/c/coreutils/coreutils-9.6-4-x86_64.pkg.tar.zst" sha256 = "1dee123bd0fcec4a4bc8cd4f9b82932b88508657baf43ed7eb8fc591a0012a27" signature = "iQEzBAABCAAdFiEEW34/txt/EDKaHAOrdx32Yn7faB8FAmfKA+EACgkQdx32Yn7faB+cLAgAx2whLV1u+NdKB/E5agdS8IzdDFNSGE8sLjAXumZbm/vKXJbe42a/lBXNjDozsuP/SnAzlLzrJtuWyX9Dh4qH+AmPvkrEPu0dUa/1kA1KEQbJZShAec2xug8a+XHeOSNjusxkbK2nS19zD0zzQOKJ+l0HxpasDcGzK2OFxCNIx9rxrU7ME0Et0z/xlsA4q+aH/p+HxTqQh9JAMa3LO1pHMl7P2bQIE0TepQfjexE+0A3N+angBOeXAru6VrPClQKuNjbD3JDWd9GEhZFv3/bfdirNi/5qOHUfEYRWdoAwbJwmzR9LeqvsKzd6cFu5MVWFb8MiGd2qvwzqzOdV2peaPQ==" [[package]] name = "dbus" version = "1.16.2-1" system = "archlinux" url = "https://archive.archlinux.org/packages/d/dbus/dbus-1.16.2-1-x86_64.pkg.tar.zst" sha256 = "740fb8d02f6a5798984f17bf09c4f9f62f42a8339499c283867d9c35cda0d8af" signature = "iHUEABYKAB0WIQSDvIiJNRtd67toQW64rAhgDxCM3wUCZ8O7owAKCRC4rAhgDxCM30JPAP4jKRVukB3Pct+OBKXAq2k6hws2mB9l9ABllAALALRZ8gEA+rTWO19i2HiMFSeMKGExdxG1daKG65Cl7OXE7gkO7Aw=" [[package]] name = "gawk" version = "5.3.1-2" system = "archlinux" url = "https://archive.archlinux.org/packages/g/gawk/gawk-5.3.1-2-x86_64.pkg.tar.zst" sha256 = "4e69602cb8c3f78101a1bfd8e511f1cf7e6cf62dd0a84774d0d7e55b6c088f6d" signature = "iQEzBAABCAAdFiEEW34/txt/EDKaHAOrdx32Yn7faB8FAmfKAbQACgkQdx32Yn7faB/gVwf/al226qRd4pdvIimZfza/EltSTHg6OGCWu3o8dtmVg86x+FLb43gQCHDiCA8KtYAw851mJQqGjjUTi+vu8RQkHkOJepV+n8mNtqmKXNsAwXtdMrlDzFcwhPqFNEaG2LQwoLQ2SuEYS0e+XhvtQsbh+8vMhDNdw+de1O304dC+ripvP/IwjeTcUlDX5Qd8L/giVyyBMtFNeec+sIi/+hyCfIy5FoGZ78n2dRHm0deFlnDEwvtdVhzNx0QvMUQFvyXBwsZUJFKLY7jYcL5I6gAhZ5cNqS2OPT5oYsK93XT6buU7CTv4FIulUjw493ZIYAn79e+y6FqKcrolKN5YeHesPA==" [[package]] name = "gc" version = "8.2.8-2" system = "archlinux" url = "https://archive.archlinux.org/packages/g/gc/gc-8.2.8-2-x86_64.pkg.tar.zst" sha256 = "c7b5e6816e7977a407e3f862b4ac51e7cf70e522c7fe1a72c2eca49431679712" signature = "iNUEABYKAH0WIQQFx3danouXdAf+COadTFqhVCbaCgUCZt6oQl8UgAAAAAAuAChpc3N1ZXItZnByQG5vdGF0aW9ucy5vcGVucGdwLmZpZnRoaG9yc2VtYW4ubmV0MDVDNzc3NUE5RThCOTc3NDA3RkUwOEU2OUQ0QzVBQTE1NDI2REEwQQAKCRCdTFqhVCbaCp63AP4zSG9Ph/ey/7pYMn/RNiK9x1gv3SknQQ5dttHxVgc++QD/aXAHmlJ3i2x5kaqtv+bVKMTa80sF/S7X6DKJfQ+Q9Q4=" [[package]] name = "gcc" version = "14.2.1+r753+g1cd744a6828f-1" system = "archlinux" url = "https://archive.archlinux.org/packages/g/gcc/gcc-14.2.1+r753+g1cd744a6828f-1-x86_64.pkg.tar.zst" sha256 = "2f5d57f8047bd95dc8ca89878e276968e485fec552a1d6222cbe7d4b020e5b8f" signature = "iNUEABYKAH0WIQQFx3danouXdAf+COadTFqhVCbaCgUCZ6dOMl8UgAAAAAAuAChpc3N1ZXItZnByQG5vdGF0aW9ucy5vcGVucGdwLmZpZnRoaG9yc2VtYW4ubmV0MDVDNzc3NUE5RThCOTc3NDA3RkUwOEU2OUQ0QzVBQTE1NDI2REEwQQAKCRCdTFqhVCbaCs1BAQDhgm29sxvOmglFqaPf7w14Smqpbd/q83FwqUZX5fyqPwD+Obh+eLgaLHPq2DwHGH8TPoFEHlbMhU82pk2DkvU6qQE=" [[package]] name = "glib2" version = "2.84.0-1" system = "archlinux" url = "https://archive.archlinux.org/packages/g/glib2/glib2-2.84.0-1-x86_64.pkg.tar.zst" sha256 = "28c8e676f9c63b57e1e1d3a0792037c6f81abb2ec60042d3f5d022bbbed77dff" signature = "iHUEABYKAB0WIQSDvIiJNRtd67toQW64rAhgDxCM3wUCZ8nDOwAKCRC4rAhgDxCM3+2cAP9j7yj4Vmzo/oIftCoDCLrjbEFxvP2LwV1gDQZpagIbvwEAgrZVmKkJYB0x0YMmIDetVgBZ0u5Nwvh7IbyKmRwdCgs=" [[package]] name = "guile" version = "3.0.10-1" system = "archlinux" url = "https://archive.archlinux.org/packages/g/guile/guile-3.0.10-1-x86_64.pkg.tar.zst" sha256 = "bf4d1b474045a88c7ad97b1ce56e8dd5786e5a10de02a8d33dc8f041edc8d01d" signature = "iNUEABYKAH0WIQQFx3danouXdAf+COadTFqhVCbaCgUCZnkshF8UgAAAAAAuAChpc3N1ZXItZnByQG5vdGF0aW9ucy5vcGVucGdwLmZpZnRoaG9yc2VtYW4ubmV0MDVDNzc3NUE5RThCOTc3NDA3RkUwOEU2OUQ0QzVBQTE1NDI2REEwQQAKCRCdTFqhVCbaCruHAQDnjJsHGhq4cae34rHS1z+Hr6yzjVQSxvA6SE9XpredlAD/cstobLSMUsHswxf5df94XkoDPJdJs44uXE/iu9gsgQg=" [[package]] name = "hwdata" version = "0.393-1" system = "archlinux" url = "https://archive.archlinux.org/packages/h/hwdata/hwdata-0.393-1-any.pkg.tar.zst" sha256 = "5cb742462a29c1490965c3dd4a0044fc3b1288c18b2805a603952465db369613" signature = "iQEzBAABCAAdFiEEW34/txt/EDKaHAOrdx32Yn7faB8FAmfHOvMACgkQdx32Yn7faB/MsggAkZBBwIt605n0/Xq/McfRE1BpNqVL7yDHCj4sKwfkgFzOvV3UVcI4w1yPXQ43yqAkzS8WW3zZnRnyQtohfIO/EzGd1tcs/f8oPGtvYGl6GrYpdvCQcz9theCrtEdEwWmkEMiRPKGhWoUEcyW6gNjQxcxhbwBMbwqkMtGV2pjvkPS7qiEIsKpqcbRfRGBRmZT1V826scToAUk2ZuAT5xa7nPswZJy+UHFzF22P0cPyzNQ4PM890FKGnholzLLLWhU7Qy6nFfHn+0cm4POvxTNhsuR3RAy8IviEOOKuP/SDJ8EJZNAWot3A5iotODGJyHWb3lxeEAvnqFpkTPvHmm6cyA==" [[package]] name = "iana-etc" version = "20250213-1" system = "archlinux" url = "https://archive.archlinux.org/packages/i/iana-etc/iana-etc-20250213-1-any.pkg.tar.zst" sha256 = "53683da198e1cdb070324c344254d8d55fdb0fcca29d3b83afef45a1f8e41c9d" signature = "iQEzBAABCAAdFiEE5JnHn1PJalTlcv7hwGCGM3xQdz4FAme87BAACgkQwGCGM3xQdz4rSAgArv24A+xkRQca4ktNQ7Ky8Fpxr8l3+1c11lmz6plOVM0uXNQBe1qv7EQF1zWJNLGJAKSay9ZYy6QBJsw1osHBDRRe0eDs+qGTth0QcbmW6A0e9ibBWWpijuCOnTgQ3vCj/Og/dTPSkF7spwcC7Q8aY9PWGiBfjkXIkO1H31Bm5pumqBq+rLAuUIy1abu8VNS230m2aa0svEdZq6g0Lnq/UjEWGJuaj8oVHQKd8i0/q5qODsH8uJOdUDSze6ek907t7fwNyCG0puOGX85wLa/G7tg/PqkihJO4vxsTZx6zv2t6ukXcvm/JVbLcHOyG5bMiWrNGCXQ9f4fiDCYGmVN/Ew==" [[package]] name = "jansson" version = "2.14-4" system = "archlinux" url = "https://archive.archlinux.org/packages/j/jansson/jansson-2.14-4-x86_64.pkg.tar.zst" sha256 = "a67ab57d4a9b4caa2e718652c392345cdd9c2496d835ab1d0ff1e78ae4429fde" signature = "iNUEABYKAH0WIQQFx3danouXdAf+COadTFqhVCbaCgUCZjJful8UgAAAAAAuAChpc3N1ZXItZnByQG5vdGF0aW9ucy5vcGVucGdwLmZpZnRoaG9yc2VtYW4ubmV0MDVDNzc3NUE5RThCOTc3NDA3RkUwOEU2OUQ0QzVBQTE1NDI2REEwQQAKCRCdTFqhVCbaCpfCAP4sFnTjSEIn5wDbLWGZOivsWT2SWPG6AgofrnUjaK/UMAD9E2u6D7WJbVTYrvDhVUz3WN6k8bVB8ZODyoIF66GWEw0=" [[package]] name = "kmod" version = "34.1-1" system = "archlinux" url = "https://archive.archlinux.org/packages/k/kmod/kmod-34.1-1-x86_64.pkg.tar.zst" sha256 = "7344e845a04e079ae779713563fdf8bd258418445f93e3a1d5445bb21c732f75" signature = "iHUEABYKAB0WIQQEKYl95fO9rFN6MGltQr3RFuAGjwUCZ8lVswAKCRBtQr3RFuAGj2UwAP9rjWJGBlY+FqyYjNPHnu4kAHAjArENfPAu7H4F7V96kgD/UcREMxJePgASH/DJDT2jvdf5s9dzY8b6jsCzVMeoogY=" [[package]] name = "libcap" version = "2.75-1" system = "archlinux" url = "https://archive.archlinux.org/packages/l/libcap/libcap-2.75-1-x86_64.pkg.tar.zst" sha256 = "2824ae462e15e0da14d3e965c60871dda3967d031746bc5a336d5a1042b48ffb" signature = "iHUEABYKAB0WIQRizHP4hOUpV7L92IObeih9mi7GCAUCZ8lRowAKCRCbeih9mi7GCHTXAQDgSkHTOPylIWR5oOouCcpfS3oQ4589yTe10VS18OagHAEAkdq9atUJ1GjN+6Yei2E0r6IGAuU8zWt/e8Iaplicpws=" [[package]] name = "libedit" version = "20250104_3.1-1" system = "archlinux" url = "https://archive.archlinux.org/packages/l/libedit/libedit-20250104_3.1-1-x86_64.pkg.tar.zst" sha256 = "9b4167ade67f899d5f4d1e0d3e8e8f18b5edfdd076f5aeffd100cb3093117987" signature = "iQEzBAABCAAdFiEEW34/txt/EDKaHAOrdx32Yn7faB8FAme8RWMACgkQdx32Yn7faB9bnQf+N2KYErONnv0FLvqScucx7dhD+DNMqRFEEruhqsnAtP9KZzRePYMys6Uhn4TlIysatDnz6qy2UMeXuLOKDAYXMz4M37lfRT6YsBzbNj93FQlVrfelM/ap6U3vGBnHUVv8zqPoI6SgF+qqRuDJtoE3DR6TiiHgYm2oHRR/0NwF9S3hxqVkc+Ebmz7VTTlXW0x/g2uOKRqPyJR17GCuVrRWW/B0eIYrNIVVTE9jcMVKC5Uil+OAYd1bPoTQRgolw/Vp13QnHyUC4u8OwM3yl1b3CWjdRkwz7ImS+K5aF6z9/bUGzPwM1WmPkiz4TNeYHqxnKAQ9GnSLZOJBv1rMl3mI+g==" [[package]] name = "libisl" version = "0.27-1" system = "archlinux" url = "https://archive.archlinux.org/packages/l/libisl/libisl-0.27-1-x86_64.pkg.tar.zst" sha256 = "55a36e8195e6d9ce2efeb4276c60df6b6e7d94812fa36f8423d5ce664a5d34df" signature = "iNUEABYKAH0WIQQFx3danouXdAf+COadTFqhVCbaCgUCZtWJeV8UgAAAAAAuAChpc3N1ZXItZnByQG5vdGF0aW9ucy5vcGVucGdwLmZpZnRoaG9yc2VtYW4ubmV0MDVDNzc3NUE5RThCOTc3NDA3RkUwOEU2OUQ0QzVBQTE1NDI2REEwQQAKCRCdTFqhVCbaCgPbAP9GNpnE0ra4qZOGYyJtfnyG42f8Z9dLpX21F/sY/a2UCgD/dz8x7harwjTofWctVHyyCacJsLhSq2jvSfrvvL4H/w8=" [[package]] name = "libmpc" version = "1.3.1-2" system = "archlinux" url = "https://archive.archlinux.org/packages/l/libmpc/libmpc-1.3.1-2-x86_64.pkg.tar.zst" sha256 = "10554706eb15ed2186fbd55fd5db8fa5919788ac9a75d26c0b9ef5bdfca9d470" signature = "iQEzBAABCAAdFiEEFRnVq6Zb9vwrc8dWek52CV2KUuQFAmaHCZwACgkQek52CV2KUuRjbAf/TmL9cCMXYTGsNmR2om6kT7XjczfZoFR9AM0FSTUNy5AuNZNUUCfm6ie6F4rFwHc3nETOSojScOZauZlcNiLrVriHYYFSZ8EhKiCJCo68a7KTbceBNoBuT6AEIpGMpIMti/cvWhu8VXl5JIRo8LNPBzDih05aCDUJ2nayKPYNHalDayu87sDXzJYXuzC8KD7XmUa7Kirn0ZpA4VZXc8CUjYYvn0wvRwLKQP4WMpszxmblQWjMVbQxh7dwC+gPtqIANVjoGKMRfr6QpT03XXIEaTBKbMsxeYFvwn+y2JN30t6oFI6LJADZ22VwimEzu06u+x9c+3+pr4k7Py43OCOGmg==" [[package]] name = "libnghttp2" version = "1.65.0-1" system = "archlinux" url = "https://archive.archlinux.org/packages/l/libnghttp2/libnghttp2-1.65.0-1-x86_64.pkg.tar.zst" sha256 = "7f6829cdaa41f1f61bf05a648198a640f0484fe550a2697435e552d42222b50c" signature = "iHUEABYKAB0WIQQEKYl95fO9rFN6MGltQr3RFuAGjwUCZ8Vu2AAKCRBtQr3RFuAGj71WAP9YmSkSGdsqgEA7JsF5lAYJzj3y7zT9MkXeHumWpXSCFgD+JZ9mdujOPIlWL18ihlxZCSj38gL1Ya7mVwNjd2KETgo=" [[package]] name = "llvm-libs" version = "19.1.7-1" system = "archlinux" url = "https://archive.archlinux.org/packages/l/llvm-libs/llvm-libs-19.1.7-1-x86_64.pkg.tar.zst" sha256 = "44de8dac4c85c2297d8a8b9b4f8a71d422bd2452b6b0f442859f92c5319daad3" signature = "iQEzBAABCAAdFiEEhs/8qRjPOvRxR1iAUeixSKmZnDQFAmeLq+kACgkQUeixSKmZnDSQcgf/UE3HidSGyn485QxUdNk6ffxyRMIxQixiaMPVcFQlTCNoC2c3oN/Y9bp5qWN2Oydh5J17nVy6el5mpVzaSFrVA05cFP0eoOIy1RrlC2ko54icSmchRyD1bGHfwBNlurkCU5y1AQqbo+5Exfg31Vj5NsXdDst5E51WfP37/NxZ9holoXk17Lb5vcgQ/GTgmzEWL7Gt+CF5X0AkPCOejBtBrzcSWM2T4s6dGatM45PCTSWHzgLbi9RuZwd2y0jPZPPocvsmxoi1q0KhjteCXWJpn/HpksmiiRNIG1RN9uV7Vp9f0rVEoWaf1VbdzNyXrdoRFxdxg1Nt0en9VrwhMuX4Mg==" [[package]] name = "make" version = "4.4.1-2" system = "archlinux" url = "https://archive.archlinux.org/packages/m/make/make-4.4.1-2-x86_64.pkg.tar.zst" sha256 = "7c1bc0d882f7c8d1bcb305eb7efaabc19ed6afa5a9a443575fa0d5ed57985535" signature = "iHUEABYKAB0WIQSZH24/B2XPYpWIhYYTmwnaW/DTOAUCZBT0lQAKCRATmwnaW/DTOKwJAP9/kfT3rO0NhbD8wuI6ajzjyKtrl4SfuU0yu/PKByXQOgD/aYSvsyXylJhCadU2smO4LbP2Vj9fnIvEwPvbXbesVQ0=" [[package]] name = "musl" version = "1.2.5-4" system = "archlinux" url = "https://archive.archlinux.org/packages/m/musl/musl-1.2.5-4-x86_64.pkg.tar.zst" sha256 = "c088a092da5b07399f20a1474f9e34f2fcbb5655195562de76443613b6754b38" signature = "iQJLBAABCAA1FiEEiee5MxxK59f699MFwTIpOVS75K0FAmfLY3IXHHNwdXB5a2luQGFyY2hsaW51eC5vcmcACgkQwTIpOVS75K3pMg/+PfdVRfE20NdshwkXo1y5UOelz1H77VjCFuMJDio5HFc7b+IoKNjSxZL8r1FLjolXaVlcI8QvoYZQ61IX4Nnq62Ygg2uY343IjHZg5hHiNN5gZdP2hwHaBFFWfPDsutW0n4fC3cELv+cIWnNCpefK2AofodURnBg1xMWDKH/LQTJlKdyoaAdX/LbxxQICz4BAkZ9Zxmu1DcEOK5p8wd2PDPBY9LSt0VpSKAAO8bDemCPP898X27rn3Z6ICX0FDPMB19J9jXVtHcux+vE9F43evPVVFbwGyi3ddYXkuC+4yvr6NOxq6MAs2feEZxwPFbT7dEFk9FDZJ2Ny6g41lNVbH7w4MpKfk/QO0kRrRoKibRg8lW26cITPi6b9nwqD76LQjmzzR/muTdJGy/S1V8s/aHnXwz3WEchXTgD62yocKzRX2Uh9LxdzV29b3Em/AN6dO7TNG4fMhVNGs83oxMoXx6XsH+aI6qh/TEYCOqqg9KW01MdigzVZuoHaHe8OT5zD2CQr8aIfpV6mj4YZqosjWC1lWwNdIXkzliRpDnsPpsWgpyemvAIOfOMf63aI8HVryHvvFP/Lt/KkCOgJMWNaXI0YFbWlaBAxiO5tcoV0zyKDmNw5J6BmKqVSEN2Ga8lQ17GB08GXD8nzdBQ7+TQmQhSgE0xjCNpHIerMtRt1xg0=" [[package]] name = "musl-aarch64" version = "1.2.5-4" system = "archlinux" url = "https://archive.archlinux.org/packages/m/musl-aarch64/musl-aarch64-1.2.5-4-x86_64.pkg.tar.zst" sha256 = "3786b8bf6fc7cd1abf6d4fe9ec47697e09b2453a2446a967ecc7f79e1701bb87" signature = "iQJLBAABCAA1FiEEiee5MxxK59f699MFwTIpOVS75K0FAmfLY3IXHHNwdXB5a2luQGFyY2hsaW51eC5vcmcACgkQwTIpOVS75K3ShQ/9GXMUzZrqP8wkcnumTzDJYz7wWoYwFpC0Pl/P/J1AJGOoyL4OKJ9n1fb9fISssQdSVwTSvTKw0D7RFgu1pb3BbuI3r19OrSX6PoTZjAwfQHApHTf7uvtBXmuQU2Oq5qmDZ8QfFmimYWBb9TOry4Ah6OlYGkOh1DhS7mnpA1V6sJBuLYFu9z4vqXhvY++vi1oI1OSmSbqN8p1/Qo3Uf6q0gV6UpaZNYdLlVScjPONZsC51uI/VevzedYMBu8xWqKsjFDq0Vp0nEoux0TDGIfWoI5gp8lSSyKoHklImOXPdmcFYy0dmwGDPr8p2NhfCQmHGGVeFs3Fu/jfmUl0EDq6XG9CTaWXTN/wvXi2iiGMTISrgXr9Kmspe7jzqO68FCZ+rVpH1PvPOvkW+8VADs3Kc9RYgjDIPMeZo3t/hPjqcb0BMYQig7qSkIEGFHwLhMRD7dklHD6iasfkLASWxTxwphd5HIvtz9sezNKwHmf/ZxBKykf3Hw61z+Pk4bqgthNectbISkFLTdEOFtLD8jqTyxtLO63zTE6WCanAqNXsdB/VQTHSZn4vqot58EpY99vCmQfEJTSeHsGmSG+Fyezcf4u1vtXO6AoiopgyoYIQFsnkc0ETzUly5AlyKP7jYNwXlPE/Y0ii2SKHPTWcuDYVa+09DHf2yGwElGQ1VhtiQWj8=" [[package]] name = "rust" version = "1:1.85.0-1" system = "archlinux" url = "https://archive.archlinux.org/packages/r/rust/rust-1:1.85.0-1-x86_64.pkg.tar.zst" sha256 = "3fd906c63706593928e8928feb5d7da5019a37fbec2456b6a16b44ce9ded95ff" signature = "iHUEABYKAB0WIQSDvIiJNRtd67toQW64rAhgDxCM3wUCZ7eBMwAKCRC4rAhgDxCM35OzAQCWv+NKTnrmpemr3KmnGGzGtZY5nGaLQTDyPZnGa/Q27AEA897EU+Yj9nXbwc4bw4pHCoOJBqHtdLTvqFrhzVJsmwA=" [[package]] name = "rust-aarch64-musl" version = "1:1.85.0-1" system = "archlinux" url = "https://archive.archlinux.org/packages/r/rust-aarch64-musl/rust-aarch64-musl-1:1.85.0-1-x86_64.pkg.tar.zst" sha256 = "b403261ff4ad7b7202fbdd905c631db5ccc8543e3787452e0757de03f1d5127a" signature = "iHUEABYKAB0WIQSDvIiJNRtd67toQW64rAhgDxCM3wUCZ7eBOAAKCRC4rAhgDxCM3/H9AQCgoRvHj6UxqKm7ffULFTAlLQt70c+r5BEOWqF6vlZ/BwEA63hGBbvD0usdWDyd5av7qcZLhZ6UlkuG+vA2wZfWcQ4=" [[package]] name = "rust-musl" version = "1:1.85.0-1" system = "archlinux" url = "https://archive.archlinux.org/packages/r/rust-musl/rust-musl-1:1.85.0-1-x86_64.pkg.tar.zst" sha256 = "a156e687690b81f645e9f7a6bce395479f20d3172dcffbd10af25f9b3135546c" signature = "iHUEABYKAB0WIQSDvIiJNRtd67toQW64rAhgDxCM3wUCZ7eBNQAKCRC4rAhgDxCM31MtAP9oquTC7q+3elHIaDnnLETN0NJQZ26cHAkIb+4KNmlSpwEAvscIz4L9n4M2aHRa4vdq7i/oICZFrd0P6d+pRspTfQE=" [[package]] name = "systemd" version = "257.4-1" system = "archlinux" url = "https://archive.archlinux.org/packages/s/systemd/systemd-257.4-1-x86_64.pkg.tar.zst" sha256 = "c3f7b1163ea28532f4fec402247956eed38fc0a10944550862acc3ba1b492597" signature = "iHUEABYKAB0WIQQEKYl95fO9rFN6MGltQr3RFuAGjwUCZ8m2pAAKCRBtQr3RFuAGj5eIAQCR8aJbglLdg3v0q/HWp7tAp9rEGm5RIoflwUE5mMP42wD/bgqRazlncz+52aJAnJtTvmF53Beej3ftokhn4/TfrgE=" [[package]] name = "systemd-libs" version = "257.4-1" system = "archlinux" url = "https://archive.archlinux.org/packages/s/systemd-libs/systemd-libs-257.4-1-x86_64.pkg.tar.zst" sha256 = "010b0e720d6dc0cfe91c2d0af63c02e25f3dba5ed880c73c0630d1f805781638" signature = "iHUEABYKAB0WIQQEKYl95fO9rFN6MGltQr3RFuAGjwUCZ8m2pQAKCRBtQr3RFuAGj0JCAP9KbCy4crY5f1JeK7IBAo7MmaZd1FwRCUBd2/FwvBS9WQEAiyUXYHlzGJgtzHGFy6qW8K+ltX0pQ9nCms5sA3obnQQ=" [[package]] name = "systemd-sysvcompat" version = "257.4-1" system = "archlinux" url = "https://archive.archlinux.org/packages/s/systemd-sysvcompat/systemd-sysvcompat-257.4-1-x86_64.pkg.tar.zst" sha256 = "9d7988323d60336af4de92fc7241c85f051e7931bc55faebae949e3ad8931b43" signature = "iHUEABYKAB0WIQQEKYl95fO9rFN6MGltQr3RFuAGjwUCZ8m2pQAKCRBtQr3RFuAGj7sSAP9usvXslic1L5tijJa2gH5b+9CIEiDSBliX5vXbqHIJWAEA+3h77jLrEswOTERngcJT8Mkb2FiDCn0KtPb9FTHD9wk=" apt-swarm-0.5.1/repro-env.toml000064400000000000000000000002741046102023000143570ustar 00000000000000[container] image = "docker.io/library/archlinux" [packages] system = "archlinux" dependencies = [ "make", "musl", "musl-aarch64", "rust-aarch64-musl", "rust-musl", ] apt-swarm-0.5.1/src/args.rs000064400000000000000000000273661046102023000136510ustar 00000000000000use crate::errors::*; use crate::p2p; use crate::p2p::proto::{PeerAddr, PeerFilter}; #[cfg(feature = "git")] use crate::plumbing; use clap::{ArgAction, CommandFactory, Parser, Subcommand}; use clap_complete::Shell; use std::ffi::OsString; use std::io::stdout; use std::net::SocketAddr; use std::path::PathBuf; use std::pin::Pin; use tokio::fs::File; use tokio::io; use tokio::io::AsyncRead; #[derive(Debug, Clone)] pub enum FileOrStdin { File(PathBuf), Stdin, } impl FileOrStdin { /// If the given list is empty, select stdin as input pub fn default_stdin(list: &mut Vec) { if list.is_empty() { list.push(Self::Stdin); } } pub async fn open(&self) -> Result { match self { Self::File(path) => { debug!("Opening file {path:?}..."); let file = File::open(&path) .await .with_context(|| anyhow!("Failed to open file at path: {path:?}"))?; Ok(OpenFileOrStdin::File(file)) } Self::Stdin => Ok(OpenFileOrStdin::Stdin(io::stdin())), } } } impl From for FileOrStdin { fn from(s: OsString) -> Self { if s.to_str() == Some("-") { Self::Stdin } else { Self::File(s.into()) } } } #[derive(Debug)] pub enum OpenFileOrStdin { File(File), Stdin(io::Stdin), } impl AsyncRead for OpenFileOrStdin { fn poll_read( self: std::pin::Pin<&mut Self>, ctx: &mut std::task::Context<'_>, buf: &mut tokio::io::ReadBuf<'_>, ) -> std::task::Poll> { match self.get_mut() { Self::File(file) => Pin::new(file).poll_read(ctx, buf), Self::Stdin(stdin) => Pin::new(stdin).poll_read(ctx, buf), } } } #[derive(Debug, Parser)] #[command(version)] pub struct Args { /// Increase logging output (can be used multiple times) #[arg(short, long, global = true, action(ArgAction::Count))] pub verbose: u8, /// Reduce logging output (can be used multiple times) #[arg(short, long, global = true, action(ArgAction::Count))] pub quiet: u8, /// Path to config file to use #[arg(short, long, global = true)] pub config: Option, /// Configure a socks5 proxy for outgoing connections #[arg(long, global = true)] pub proxy: Option, /// Configure the path where persistent data should be stored #[arg(long, global = true, env = "APT_SWARM_DATA_PATH")] pub data_path: Option, /// Always enable colored output #[arg(short = 'C', long, global = true)] pub colors: bool, #[command(subcommand)] pub subcommand: SubCommand, } #[derive(Debug, Subcommand)] pub enum SubCommand { Import(Import), Export(Export), Fetch(Fetch), Latest(Latest), Ls(Ls), Keyring(Keyring), Pull(Pull), P2p(P2p), #[command(subcommand)] Plumbing(Plumbing), } /// Import signed InRelease files #[derive(Debug, Parser)] pub struct Import { /// The input files to read (- for stdin) pub paths: Vec, } /// Export all known InRelease files #[derive(Debug, Parser)] pub struct Export { pub release_hashes: Vec, /// Instead of exact matches, scan with the given prefix(es) #[arg(long)] pub scan: bool, } /// Fetch the latest InRelease files and import them #[derive(Debug, Parser)] pub struct Fetch { /// Number of concurrent requests #[arg(short = 'j', long)] pub concurrency: Option, } /// Query the latest release for a given key #[derive(Debug, Parser)] pub struct Latest { /// The signing key to query pub fingerprint: sequoia_openpgp::Fingerprint, /// Print only the key #[arg(short = 'K', long, group = "print")] pub key: bool, /// Print only the date #[arg(short = 'D', long, group = "print")] pub date: bool, /// Print only the body (with the signature stripped) #[arg(short = 'B', long, group = "print")] pub body: bool, /// Print only the header (everything before the first empty line) #[arg(short = 'H', long, group = "print")] pub header: bool, /// Print only the attachment (everything after the first empty line) #[arg(short = 'A', long, group = "print")] pub attachment: bool, /// Permit dates from the future #[arg(short = 'F', long)] pub allow_future_dates: bool, } /// List hashes of all known releases #[derive(Debug, Parser)] pub struct Ls { /// Use a specific prefix to filter by pub prefix: Option, /// Count keys present in database instead of listing them #[arg(short = 's', long)] pub count: bool, } /// List all keys currently configured for monitoring #[derive(Debug, Parser)] pub struct Keyring { /// Output keyring as json #[arg(long)] pub json: bool, /// Show the number of known signatures for a given subkey #[arg(short, long)] pub stats: bool, } /// Connect to a remote node and sync from them #[derive(Debug, Parser)] pub struct Pull { /// The address to connect to pub addr: PeerAddr, /// Only sync data for specific keys, identified by their fingerprint #[arg(long = "key")] pub keys: Vec, /// Run the sync but do not import #[arg(short = 'n', long)] pub dry_run: bool, } /// Run in p2p swarm mode #[derive(Debug, Parser)] pub struct P2p { #[cfg(feature = "irc")] #[command(flatten)] pub irc: P2pIrc, #[command(flatten)] pub dns: P2pDns, /// Do not use any bootstrapping mechanism, initial peers need to be added manually #[arg(long)] pub no_bootstrap: bool, /// Do not actively fetch updates from the configured repositories #[arg(long)] pub no_fetch: bool, /// Do not bind a sync port for p2p traffic #[arg(long)] pub no_bind: bool, /// The addresses to bind a sync port for p2p traffic (if not disabled) #[arg(short = 'B', long, default_values = &["0.0.0.0:16169", "[::]:16169"])] pub bind: Vec, /// Configure addresses to announce if somebody wants to sync from us #[arg(short = 'A', long)] pub announce: Vec, /// Monitor a container registry for updates and terminate if an update is available (eg. ghcr.io/kpcyrd/apt-swarm:edge) #[arg(long, value_name = "IMAGE")] pub check_container_updates: Option, /// The VCS commit to assume for our currently running image #[arg(long, value_name = "COMMIT", env = "UPDATE_CHECK_COMMIT")] pub update_assume_commit: Option, } #[cfg(feature = "irc")] #[derive(Debug, Parser)] pub struct P2pIrc { /// Do not connect to irc for peer discovery #[arg(long)] pub no_irc: bool, /// The irc server and channel to connect to #[arg(long, default_value = "ircs://irc.hackint.org/##apt-swarm-p2p")] pub irc_channel: String, } #[derive(Debug, Parser)] pub struct P2pDns { /// Do not query any configured dnsseeds #[arg(long)] pub no_dns: bool, /// The dns names to query for bootstrapping #[arg(long, default_values = p2p::dns::DNS_SEEDS)] pub dns: Vec, } /// Access to low-level features #[derive(Debug, Subcommand)] pub enum Plumbing { AttachSig(AttachSig), Canonicalize(Canonicalize), Completions(Completions), Config(Config), ContainerUpdateCheck(ContainerUpdateCheck), #[cfg(unix)] DbServer(DbServer), DnsBootstrap(DnsBootstrap), Fetch(PlumbingFetch), Fingerprint(Fingerprint), Fsck(Fsck), #[cfg(feature = "git")] GitObject(GitObject), #[cfg(feature = "git")] GitScrape(GitScrape), Index(Index), Migrate(Migrate), Paths(Paths), PeerdbAdd(PeerdbAdd), PeerdbList(PeerdbList), PeerdbGc(PeerdbGc), SyncPull(SyncPull), SyncYield(SyncYield), } /// Create a clear-signed document from a detached signature #[derive(Debug, Parser)] pub struct AttachSig { pub content: PathBuf, pub signatures: Vec, } /// Transform a signed InRelease file into a canonical representation #[derive(Debug, Parser)] pub struct Canonicalize { /// The input files to read (- for stdin) pub paths: Vec, /// Verify signatures belong to trusted key in keyring #[arg(long)] pub verify: bool, } /// Generate shell completions #[derive(Debug, Parser)] pub struct Completions { pub shell: Shell, } impl Completions { pub fn generate(&self) -> Result<()> { clap_complete::generate(self.shell, &mut Args::command(), "apt-swarm", &mut stdout()); Ok(()) } } /// Print applied configuration #[derive(Debug, Parser)] pub struct Config {} /// Query a container registry for a more recent release of a given image #[derive(Debug, Parser)] pub struct ContainerUpdateCheck { /// The image to monitor for updates (eg. ghcr.io/kpcyrd/apt-swarm:edge) #[arg(long)] pub image: String, /// The commit to assume for our currently running image #[arg(long, env = "UPDATE_CHECK_COMMIT")] pub commit: String, } /// Bind a unix domain socket and allow abstract database access from multiple processes #[derive(Debug, Parser)] pub struct DbServer {} /// Run dns bootstrap query, print results #[derive(Debug, Parser)] pub struct DnsBootstrap { /// Only print ipv4 records #[arg(short = '4', long, group = "proto")] pub ipv4_only: bool, /// Only print ipv6 records #[arg(short = '6', long, group = "proto")] pub ipv6_only: bool, /// The dns name to query #[arg(default_values = p2p::dns::DNS_SEEDS)] pub dns: Vec, } /// Fetch a link and write response to stdout #[derive(Debug, Parser)] pub struct PlumbingFetch { /// The resource to fetch pub url: String, } /// Extract the fingerprint of a pgp key #[derive(Debug, Parser)] pub struct Fingerprint { /// The input files to read (- for stdin) pub paths: Vec, } /// Verify stored objects #[derive(Debug, Parser)] pub struct Fsck { pub prefix: Option, } #[cfg(feature = "git")] /// Convert signed git objects into signature format used by apt-swarm #[derive(Debug, Parser)] pub struct GitObject { pub paths: Vec, #[arg(short, long)] pub kind: Option, } #[cfg(feature = "git")] /// Attempt to export all signed objects from a git repo #[derive(Debug, Parser)] pub struct GitScrape { pub paths: Vec, } /// Scan the database and calculate the requested index #[derive(Debug, Parser)] pub struct Index { /// The signing key to index pub fingerprint: sequoia_openpgp::Fingerprint, /// Only entries with this hash algorithm pub hash_algo: String, /// Calculate an index based on a specific prefix pub prefix: Option, /// Calculate a batch index, they are bigger but allow syncs with fewer round-trips #[arg(short, long)] pub batch: bool, } /// Open a fresh database and re-import the old data #[derive(Debug, Parser)] pub struct Migrate {} /// Print configured paths #[derive(Debug, Parser)] pub struct Paths {} /// Add a peerdb entry #[derive(Debug, Parser)] pub struct PeerdbAdd { pub addrs: Vec, } /// Read and print peerdb file #[derive(Debug, Parser)] pub struct PeerdbList { /// Filter by ip address or network (without port) pub filters: Vec, } /// Remove old peerdb entries #[derive(Debug, Parser)] pub struct PeerdbGc {} /// Fetch all available signatures over stdio (use with sync-yield) #[derive(Debug, Parser)] pub struct SyncPull { pub keys: Vec, /// Run the sync but do not import #[arg(short = 'n', long)] pub dry_run: bool, } /// Provide access to our signatures over stdio (use with sync-pull) #[derive(Debug, Parser)] pub struct SyncYield { /// Enable access to peer-exchange queries #[arg(long)] pub pex: bool, } apt-swarm-0.5.1/src/config.rs000064400000000000000000000137541046102023000141560ustar 00000000000000use crate::args::Args; use crate::errors::*; use crate::signed::Signed; use bstr::BString; use bytes::Bytes; use sequoia_openpgp::armor; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::io::prelude::*; use std::path::{Path, PathBuf}; use tokio::fs; #[derive(Debug, PartialEq, Default)] pub struct Config { pub data: ConfigData, pub config_path: Option, pub data_path: Option, } impl Config { pub async fn load_with_args(args: &Args) -> Result { let (config_path, data) = if let Some(path) = &args.config { if path.to_str() == Some("#") { debug!("Config loading has been explicitly disabled, using default config"); (None, ConfigData::default()) } else { let data = ConfigData::load_config_from(path) .await .with_context(|| anyhow!("Failed to load configuration from {:?}", path))?; (Some(path.to_owned()), data) } } else if let Some((path, buf)) = Self::find_config().await { debug!("Using configuration from {:?}", path); let data = ConfigData::load_config_from_str(&buf)?; (Some(path), data) } else { (None, ConfigData::default()) }; Ok(Config { data, config_path, data_path: args.data_path.clone(), }) } async fn find_config() -> Option<(PathBuf, String)> { for path in [ Self::default_config_path(), Ok("/etc/apt-swarm.conf".into()), ] .into_iter() .flatten() { match fs::read_to_string(&path).await { Ok(buf) => return Some((path, buf)), Err(err) => { debug!("Attempt to read config from {path:?} failed: {err:#}"); } } } None } pub fn apt_swarm_path(&self) -> Result> { let path = if let Some(path) = &self.data_path { Cow::Borrowed(path) } else { let data_dir = dirs::data_dir().context("Failed to detect data directory")?; let path = data_dir.join("apt-swarm"); Cow::Owned(path) }; Ok(path) } pub fn database_path(&self) -> Result { let data_dir = self.apt_swarm_path()?; let path = data_dir.join("storage"); Ok(path) } pub fn database_migrate_path(&self) -> Result { let data_dir = self.apt_swarm_path()?; let path = data_dir.join("storage~"); Ok(path) } pub fn database_delete_path(&self) -> Result { let data_dir = self.apt_swarm_path()?; let path = data_dir.join("storage="); Ok(path) } pub fn db_socket_path(&self) -> Result { let data_dir = self.apt_swarm_path()?; let path = data_dir.join("db.sock"); Ok(path) } fn default_config_path() -> Result { let config_dir = dirs::config_dir().context("Failed to detect config directory")?; let path = config_dir.join("apt-swarm.conf"); Ok(path) } pub fn peerdb_path(&self) -> Result { let data_dir = self.apt_swarm_path()?; let path = data_dir.join("peerdb.json"); Ok(path) } pub fn peerdb_new_path(&self) -> Result { let data_dir = self.apt_swarm_path()?; let path = data_dir.join("peerdb.json-"); Ok(path) } } #[derive(Debug, PartialEq, Default, Serialize, Deserialize)] pub struct ConfigData { #[serde(rename = "repository", default)] pub repositories: Vec, } impl ConfigData { pub fn load_config_from_str(buf: &str) -> Result { let config = toml::from_str(buf)?; Ok(config) } pub async fn load_config_from(path: &Path) -> Result { let buf = fs::read_to_string(&path).await?; Self::load_config_from_str(&buf) } } #[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize)] pub struct Repository { #[serde(default)] pub urls: Vec, pub keyring: String, } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum UrlSource { Url(String), Detached { content: String, sig: String }, } impl UrlSource { pub async fn fetch(&self, client: &reqwest::Client) -> Result { match self { UrlSource::Url(url) => { let body = Self::fetch_data(client, url).await?; let (signed, _remaining) = Signed::from_bytes(&body) .context("Failed to parse http response as release")?; Ok(signed) } UrlSource::Detached { content, sig } => { let content = Self::fetch_data(client, content).await?; if !content.ends_with(b"\n") { bail!("Detached signatures are currently only supported if the signed data ends with a newline"); } let sig = Self::fetch_data(client, sig).await?; let mut reader = armor::Reader::from_bytes( &sig, armor::ReaderMode::Tolerant(Some(armor::Kind::Signature)), ); let mut signature = Vec::new(); reader.read_to_end(&mut signature)?; Ok(Signed { content: BString::new(content.into()), signature, }) } } } async fn fetch_data(client: &reqwest::Client, url: &str) -> Result { info!("Fetching url {:?}...", url); let r = client .get(url) .send() .await .context("Failed to send request")? .error_for_status() .context("Received http error")?; let body = r .bytes() .await .context("Failed to download http response")?; Ok(body) } } apt-swarm-0.5.1/src/db/channel.rs000064400000000000000000000067701046102023000147060ustar 00000000000000use super::{Database, DatabaseClient}; use crate::db; use crate::errors::*; use crate::signed::Signed; use crate::sync; use async_trait::async_trait; use sequoia_openpgp::Fingerprint; use tokio::sync::mpsc; pub enum Query { AddRelease(Fingerprint, Signed, mpsc::Sender), IndexFromScan(sync::TreeQuery, mpsc::Sender<(String, usize)>), Spill(Vec, mpsc::Sender>), GetValue(Vec, mpsc::Sender), // Delete(Vec, mpsc::Sender<()>), Count(Vec, mpsc::Sender), } #[derive(Debug)] pub struct DatabaseServer { db: Database, rx: mpsc::Receiver, } impl DatabaseServer { pub fn new(db: Database) -> (DatabaseServer, DatabaseServerClient) { let (tx, rx) = mpsc::channel(32); let server = DatabaseServer { db, rx }; let client = DatabaseServerClient { tx }; (server, client) } pub async fn run(&mut self) -> Result<()> { while let Some(msg) = self.rx.recv().await { match msg { Query::AddRelease(fp, signed, tx) => { let hash = self.db.add_release(&fp, &signed).await?; tx.send(hash).await.ok(); } Query::IndexFromScan(query, tx) => { let ret = self.db.index_from_scan(&query).await?; tx.send(ret).await.ok(); } Query::Spill(prefix, tx) => { let ret = self.db.spill(&prefix).await?; tx.send(ret).await.ok(); } Query::GetValue(key, tx) => { let ret = self.db.get_value(&key).await?; tx.send(ret).await.ok(); } Query::Count(key, tx) => { let ret = self.db.count(&key).await?; tx.send(ret).await.ok(); } } } Ok(()) } } #[derive(Debug, Clone)] pub struct DatabaseServerClient { tx: mpsc::Sender, } impl DatabaseServerClient { async fn request(&self, query: Query, mut rx: mpsc::Receiver) -> Result { self.tx .send(query) .await .map_err(|_| anyhow!("Database server disconnected"))?; let ret = rx.recv().await.context("Database server disconnected")?; Ok(ret) } } #[async_trait] impl DatabaseClient for DatabaseServerClient { async fn add_release(&mut self, fp: &Fingerprint, signed: &Signed) -> Result { let (tx, rx) = mpsc::channel(1); let query = Query::AddRelease(fp.clone(), signed.clone(), tx); self.request(query, rx).await } async fn index_from_scan(&mut self, query: &sync::TreeQuery) -> Result<(String, usize)> { let (tx, rx) = mpsc::channel(1); let query = Query::IndexFromScan(query.clone(), tx); self.request(query, rx).await } async fn spill(&self, prefix: &[u8]) -> Result> { let (tx, rx) = mpsc::channel(1); let query = Query::Spill(prefix.to_vec(), tx); self.request(query, rx).await } async fn get_value(&self, key: &[u8]) -> Result { let (tx, rx) = mpsc::channel(1); let query = Query::GetValue(key.to_vec(), tx); self.request(query, rx).await } async fn count(&mut self, key: &[u8]) -> Result { let (tx, rx) = mpsc::channel(1); let query = Query::Count(key.to_vec(), tx); self.request(query, rx).await } } apt-swarm-0.5.1/src/db/compression.rs000064400000000000000000000041541046102023000156310ustar 00000000000000use crate::errors::*; use std::io::{Read, Write}; const CHUNK_SIZE: usize = 1024 * 1024 * 4; // 4MB pub async fn compress(bytes: &[u8]) -> Result> { let mut compressed = Vec::new(); let mut writer = lz4_flex::frame::FrameEncoder::new(&mut compressed); for chunk in bytes.chunks(CHUNK_SIZE) { writer.write_all(chunk)?; // yield in between chunks to avoid hanging the process tokio::task::yield_now().await; } writer.finish()?; Ok(compressed) } pub async fn decompress(compressed: &[u8]) -> Result> { let mut data = Vec::new(); let mut reader = lz4_flex::frame::FrameDecoder::new(compressed); // put this array on the heap due to it's size let mut buf = vec![0u8; CHUNK_SIZE]; loop { let n = reader .read(&mut buf[..]) .context("Failed to read from decompression stream")?; if n == 0 { break; } data.extend(&buf[..n]); // yield in between chunks to avoid hanging the process tokio::task::yield_now().await; } Ok(data) } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_round_trip() { let txt = b"hello world, around the world, around the world, around the world :)"; let compressed = compress(txt).await.unwrap(); let buf = decompress(&compressed).await.unwrap(); assert_eq!(&buf, txt); } #[tokio::test] async fn test_compress() { let buf = compress(b"hello world, around the world, around the world, around the world :)") .await .unwrap(); assert_eq!( buf, b"\x04\"M\x18`@\x82#\0\0\0\xff\x08hello world, around the\x12\0\x14`rld :)\0\0\0\0" ); } #[tokio::test] async fn test_decompress() { let compressed = b"\x04\"M\x18`@\x82#\0\0\0\xff\x08hello world, around the\x12\0\x14`rld :)\0\0\0\0"; let buf = decompress(compressed).await.unwrap(); assert_eq!( buf, b"hello world, around the world, around the world, around the world :)" ); } } apt-swarm-0.5.1/src/db/consume.rs000064400000000000000000000052421046102023000147400ustar 00000000000000use crate::db; use crate::db::compression; use crate::db::header::BlockHeader; use crate::errors::*; use async_trait::async_trait; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, SeekFrom}; #[async_trait] pub trait Consume { type Item: Ord + 'static; async fn consume( mut reader: R, header: &BlockHeader, ) -> Result; } /// Read and return data pub struct ReadValue; #[async_trait] impl Consume for ReadValue { type Item = db::Value; async fn consume( mut reader: R, header: &BlockHeader, ) -> Result { let mut compressed = vec![0u8; header.data_length as usize]; reader .read_exact(&mut compressed) .await .context("Failed to read block data")?; let data = compression::decompress(&compressed) .await .context("Failed to decompress block data")?; Ok(data) } } /// Skip over data immediately, possibly beyond EOF pub struct FastSkipValue; #[async_trait] impl Consume for FastSkipValue { type Item = (); async fn consume( mut reader: R, header: &BlockHeader, ) -> Result { reader .seek(SeekFrom::Current(header.data_length as i64)) .await .context("Failed to seek over block data")?; trace!("Seeked forward by {} bytes", header.data_length); Ok(()) } } /// Skip over data, verify enough data is present before seek pub struct CheckedSkipValue; #[async_trait] impl Consume for CheckedSkipValue { type Item = (); async fn consume( mut reader: R, header: &BlockHeader, ) -> Result { // determine if enough data is available let pos = reader .stream_position() .await .context("Failed to determine stream position")?; let end = reader .seek(SeekFrom::End(0)) .await .context("Failed to seek to file end")?; let remaining = end - pos; if remaining < header.data_length { bail!( "Seek failed, missing {} bytes", header.data_length - remaining ); } // we have enough data, perform seek let new = reader .seek(SeekFrom::Start(pos + header.data_length)) .await .context("Failed to seek over block data")?; trace!("Seeked forward by {} bytes", new - pos); Ok(()) } } apt-swarm-0.5.1/src/db/disk.rs000064400000000000000000000355261046102023000142310ustar 00000000000000#[cfg(unix)] use super::unix::DatabaseUnixClient; use super::{ compression, consume, consume::Consume as _, exclusive::Exclusive, header::{BlockHeader, CryptoHash}, DatabaseClient, DatabaseHandle, }; use crate::config::Config; use crate::db; use crate::errors::*; use crate::signed::Signed; use crate::sync; use async_trait::async_trait; use bstr::BStr; use futures::{Stream, StreamExt}; use sequoia_openpgp::Fingerprint; use std::borrow::Cow; use std::io::ErrorKind; use std::path::{Path, PathBuf}; use tokio::fs; use tokio::io::{AsyncBufReadExt, AsyncSeekExt, AsyncWriteExt, BufReader, SeekFrom}; pub const SHARD_ID_SIZE: usize = 2; /// Writers should open the database in exclusive mode /// Readers can operate on a database that's being written to #[derive(Debug, PartialEq, Copy, Clone)] pub enum AccessMode { Exclusive, Relaxed, } fn folder_matches_prefix<'a>(folder: &str, full_prefix: &'a [u8]) -> Option<&'a [u8]> { let (prefix, suffix) = full_prefix .split_at_checked(folder.len()) .unwrap_or((full_prefix, &[])); if BStr::new(folder.as_bytes()).starts_with(prefix) { if prefix != full_prefix { suffix.strip_prefix(b"/") } else { Some(suffix) } } else { None } } fn file_matches_prefix(file: &str, prefix: &[u8]) -> bool { // on windows we need to do extra normalization because `:` is illegal #[cfg(not(unix))] use bstr::ByteSlice; #[cfg(not(unix))] let file = file.replace(':', "_"); #[cfg(not(unix))] let prefix = prefix.replace(b":", b"_"); #[cfg(not(unix))] let prefix = &prefix; // ensure filename qualifies for prefix we're looking for let prefix = prefix .split_at_checked(file.len()) .map(|(prefix, _)| prefix) .unwrap_or(prefix); BStr::new(file.as_bytes()).starts_with(prefix) } fn derive_shard_name<'a>(key: &str, hash_str: &'a str) -> Result> { let idx = hash_str .find(':') .with_context(|| anyhow!("Missing hash id in key: {key:?}"))?; let (shard, _) = hash_str .split_at_checked(idx + 1 + SHARD_ID_SIZE) .with_context(|| anyhow!("Key is too short: {key:?}"))?; // perform extra normalization if necessary if cfg!(unix) { Ok(Cow::Borrowed(shard)) } else { let shard = shard.replace(':', "_"); Ok(Cow::Owned(shard)) } } #[derive(Debug)] pub struct Database { path: PathBuf, exclusive: Option, } #[async_trait] impl DatabaseClient for Database { async fn add_release(&mut self, fp: &Fingerprint, signed: &Signed) -> Result { let normalized = signed.to_clear_signed()?; let hash = CryptoHash::calculate(&normalized); let (key, _new) = self.insert(fp, hash, &normalized).await?; Ok(key) } async fn index_from_scan(&mut self, query: &sync::TreeQuery) -> Result<(String, usize)> { sync::index_from_scan(self, query).await } async fn spill(&self, prefix: &[u8]) -> Result> { let mut out = Vec::new(); let stream = self.scan_values(prefix); tokio::pin!(stream); while let Some(item) = stream.next().await { let (hash, data) = item.context("Failed to read from database (spill)")?; out.push((hash, data)); } Ok(out) } async fn get_value(&self, key: &[u8]) -> Result { let value = self.get(key).await?; let value = value.context("Key not found in database")?; Ok(value) } async fn count(&mut self, prefix: &[u8]) -> Result { let count = self.scan_keys(prefix).count().await; Ok(count as u64) } } impl Database { pub async fn open(config: &Config, mode: AccessMode) -> Result { #[cfg(unix)] if mode != AccessMode::Exclusive { let sock_path = config.db_socket_path()?; if let Ok(client) = DatabaseUnixClient::connect(&sock_path).await { return Ok(DatabaseHandle::Unix(client)); } } Ok(DatabaseHandle::Direct( Self::open_directly(config, mode).await?, )) } pub async fn open_directly(config: &Config, mode: AccessMode) -> Result { let path = config.database_path()?; let db = Self::open_at(path, mode).await?; Ok(db) } pub async fn open_at(path: PathBuf, mode: AccessMode) -> Result { debug!("Opening database at {path:?}"); fs::create_dir_all(&path) .await .with_context(|| anyhow!("Failed to create directory: {path:?}"))?; let exclusive = if mode == AccessMode::Exclusive { let exclusive = Exclusive::acquire(&path).await?; Some(exclusive) } else { None }; Ok(Database { path, exclusive }) } pub async fn get>(&self, key: K) -> Result> { let stream = self.scan_values(key.as_ref()); tokio::pin!(stream); let Some(entry) = stream.next().await else { return Ok(None); }; let entry = entry.context("Failed to read from database (get)")?; Ok(Some(entry.1)) } pub async fn insert( &mut self, fp: &Fingerprint, hash: CryptoHash, value: &[u8], ) -> Result<(String, bool)> { // check if write is necessary let fp_str = format!("{fp:X}"); let hash_str = hash.as_str(); let key = format!("{fp_str}/{hash_str}"); if self.count(key.as_bytes()).await? > 0 { info!("Skipping document, already present: {key:?}"); return Ok((key, false)); } info!("Adding document to database: {key:?}"); // determine file to write to let shard = derive_shard_name(&key, hash_str)?; let folder = self.path.join(fp_str); fs::create_dir_all(&folder) .await .with_context(|| anyhow!("Failed to create folder: {folder:?}"))?; let path = folder.join(&*shard); // open file let mut file = fs::OpenOptions::new() .read(true) .write(true) .append(true) .create(true) .open(&path) .await .with_context(|| anyhow!("Failed to open file: {path:?}"))?; // ensure file is in clean state let Some(exclusive) = &mut self.exclusive else { bail!("Tried to perform insert on readonly database"); }; exclusive .ensure_tail_integrity(&path, &mut file) .await .context("Failed to verify tail integrity")?; // seek to end of file for appending data file.seek(SeekFrom::End(0)) .await .with_context(|| anyhow!("Failed to seek to end of file: {path:?}"))?; // prepare header and data let compressed = compression::compress(value) .await .with_context(|| anyhow!("Failed to compress block data: {path:?}"))?; let header = BlockHeader::new(hash, value.len(), compressed.len()); // write to file header .write(&mut file) .await .context("Failed to write block header")?; file.write_all(&compressed) .await .context("Failed to write block data")?; Ok((key, true)) } async fn read_directory_sorted(path: &Path) -> Result> { let mut dir = match fs::read_dir(path).await { Ok(dir) => dir, Err(err) if err.kind() == ErrorKind::NotFound => return Ok(vec![]), Err(err) => { return Err(err).with_context(|| anyhow!("Failed to read directory: {path:?}")); } }; let mut out = Vec::new(); while let Some(entry) = dir .next_entry() .await .with_context(|| anyhow!("Failed to read next directory entry: {path:?}"))? { let path = entry.path(); let filename = entry .file_name() .into_string() .map_err(|err| anyhow!("Found invalid directory entry name: {err:?}"))?; out.push((path, filename)); } out.sort(); Ok(out) } async fn read_shard( path: &Path, folder_name: &str, partitioned_prefix: &[u8], ) -> Result> { let file = fs::File::open(path) .await .with_context(|| anyhow!("Failed to open database file: {path:?}"))?; let mut out = Vec::new(); let mut reader = BufReader::new(file); loop { // check if more data is available if reader .fill_buf() .await .with_context(|| anyhow!("Failed to check for end of file: {path:?}"))? .is_empty() { // reached EOF break; } let (header, _n) = BlockHeader::parse(&mut reader) .await .with_context(|| anyhow!("Failed to read block header: {path:?}"))?; if header.hash.0.as_bytes().starts_with(partitioned_prefix) { // header is eligible, add to list let data = C::consume(&mut reader, &header) .await .with_context(|| anyhow!("Failed to process block: {path:?}"))?; let key = format!("{}/{}", folder_name, header.hash.0); out.push((key.into_bytes(), data)); } else { // does not match prefix, skip over it consume::FastSkipValue::consume(&mut reader, &header) .await .with_context(|| anyhow!("Failed to process block: {path:?}"))?; } } out.sort(); Ok(out) } pub fn scan_keys<'a>(&'a self, prefix: &'a [u8]) -> impl Stream> + 'a { self.scan_prefix::(prefix) .map(|item| item.map(|(key, _value)| key)) } pub fn scan_values<'a>( &'a self, prefix: &'a [u8], ) -> impl Stream> + 'a { self.scan_prefix::(prefix) } fn scan_prefix<'a, C: consume::Consume>( &'a self, prefix: &'a [u8], ) -> impl Stream> + 'a { async_stream::try_stream! { for (folder_path, folder_name) in Self::read_directory_sorted(&self.path).await? { if !folder_path.is_dir() { warn!("Found unexpected file in storage folder: {folder_path:?}"); continue; } let Some(partitioned_prefix) = folder_matches_prefix(&folder_name, prefix) else { continue; }; for (path, filename) in Self::read_directory_sorted(&folder_path).await? { if !file_matches_prefix(&filename, partitioned_prefix) { continue; } for item in Self::read_shard::(&path, &folder_name, partitioned_prefix).await? { yield item; } } } } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_folder_folder_matches_prefix() { assert_eq!( folder_matches_prefix("ED541312A33F1128F10B1C6C54404762BBB6E853", b""), Some(&b""[..]) ); assert_eq!( folder_matches_prefix("ED541312A33F1128F10B1C6C54404762BBB6E853", b"E"), Some(&b""[..]) ); assert_eq!( folder_matches_prefix("ED541312A33F1128F10B1C6C54404762BBB6E853", b"EF"), None ); assert_eq!( folder_matches_prefix("ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312"), Some(&b""[..]) ); assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E853" ), Some(&b""[..]) ); assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E853/" ), Some(&b""[..]) ); assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E853/sha256:" ), Some(&b"sha256:"[..]) ); assert_eq!(folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E853/sha256:ffe924d86aa74fdfe8b8d4b8cd9623c5df7aef626a7aada3416dc83e44e7939d" ), Some(&b"sha256:ffe924d86aa74fdfe8b8d4b8cd9623c5df7aef626a7aada3416dc83e44e7939d"[..])); } #[test] fn test_folder_folder_matches_prefix_bad_inputs() { assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E853//" ), Some(&b"/"[..]) ); assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E8533" ), None ); assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E85333" ), None ); assert_eq!( folder_matches_prefix( "ED541312A33F1128F10B1C6C54404762BBB6E853", b"ED541312A33F1128F10B1C6C54404762BBB6E8533/" ), None ); } #[test] fn test_file_matches_prefix() { assert!(file_matches_prefix("sha256:ff", b"")); assert!(file_matches_prefix("sha256:ff", b"sha")); assert!(file_matches_prefix("sha256:ff", b"sha256:")); assert!(file_matches_prefix("sha256:ff", b"sha256:f")); assert!(file_matches_prefix("sha256:ff", b"sha256:ffe")); assert!(file_matches_prefix( "sha256:ff", b"sha256:ffe924d86aa74fdfe8b8d4b8cd9623c5df7aef626a7aada34" )); assert!(!file_matches_prefix("sha256:ff", b"sha256:e")); assert!(!file_matches_prefix("sha256:ff", b"sha256:fe")); assert!(!file_matches_prefix( "sha512:ff", b"sha256:ffe924d86aa74fdfe8b8d4b8cd9623c5df7aef626a7aada34" )); assert!(!file_matches_prefix( "sha256:ff", b"sha512:ffe924d86aa74fdfe8b8d4b8cd9623c5df7aef626a7aada34" )); } } apt-swarm-0.5.1/src/db/exclusive.rs000064400000000000000000000264661046102023000153110ustar 00000000000000use crate::db::consume::{self, Consume}; use crate::db::header::BlockHeader; use crate::errors::*; #[cfg(unix)] use advisory_lock::{AdvisoryFileLock, FileLockMode}; use std::collections::BTreeSet; use std::path::{Path, PathBuf}; use tokio::fs; use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncSeek, BufReader}; #[derive(Debug)] pub struct Lock { // we only need to hold this, but don't use it for anything #[allow(dead_code)] file: fs::File, } impl Lock { #[cfg(unix)] pub async fn acquire(path: &Path) -> Result { debug!("Acquiring exclusive lock on directory: {path:?}"); let file = fs::File::open(path) .await .with_context(|| anyhow!("Failed to open directory: {path:?}"))?; let file = file.into_std().await; AdvisoryFileLock::try_lock(&file, FileLockMode::Exclusive) .with_context(|| anyhow!("Failed to acquire exclusive lock for: {path:?}"))?; debug!("Successfully acquired exclusive lock"); let file = file.into(); Ok(Self { file }) } #[cfg(not(unix))] pub async fn acquire(path: &Path) -> Result { let path = path.join("lock"); debug!("Acquiring exclusive lock on file: {path:?}"); let file = fs::OpenOptions::new() .write(true) .create(true) .append(true) // do not allow others to read or modify this file while we have it open .share_mode(0) .open(&path) .await .with_context(|| anyhow!("Failed to acquire exclusive lock for: {path:?}"))?; Ok(Self { file }) } } #[derive(Debug)] pub struct Exclusive { // we only need to hold this, but don't use it for anything #[allow(dead_code)] lock: Lock, verified_shards: BTreeSet, } impl Exclusive { pub async fn acquire(path: &Path) -> Result { let lock = Lock::acquire(path).await?; Ok(Exclusive { lock, verified_shards: BTreeSet::new(), }) } #[cfg(test)] pub fn dummy() -> Result { let file = tempfile::tempfile()?; Ok(Exclusive { lock: Lock { file: fs::File::from_std(file), }, verified_shards: BTreeSet::new(), }) } async fn verify_next_block( path: &Path, mut reader: R, ) -> Result { let (header, n) = BlockHeader::parse(&mut reader) .await .with_context(|| anyhow!("Failed to read block header: {path:?}"))?; // skip over data, verify the expected number of bytes is present consume::CheckedSkipValue::consume(&mut reader, &header) .await .with_context(|| anyhow!("Failed to process block: {path:?}"))?; trace!("Successfully verified block data is present"); Ok(n as u64 + header.data_length) } pub async fn ensure_tail_integrity>( &mut self, path: P, file: &mut fs::File, ) -> Result<()> { let path = path.as_ref(); if !self.verified_shards.contains(path) { debug!("Verifying tail integrity of on-disk file: {path:?}"); let mut last_valid_offset = 0; let mut reader = BufReader::new(&mut *file); loop { // check if more data is available if reader .fill_buf() .await .with_context(|| anyhow!("Failed to check for end of file: {path:?}"))? .is_empty() { // reached EOF break; } // verify next block is fully present on disk match Self::verify_next_block(path, &mut reader).await { Ok(n) => { last_valid_offset += n; } Err(err) => { warn!("File contains partial block, truncating to end of last valid block (offset={last_valid_offset}): {err:#}"); file.set_len(last_valid_offset).await.with_context(|| { anyhow!("Failed to truncate file to last valid offset: {path:?}") })?; break; } } } self.verified_shards.insert(path.to_owned()); debug!("Verified tail integrity of on-disk file: {path:?}"); } Ok(()) } } #[cfg(test)] mod tests { use super::*; use tokio::io::{self, AsyncSeekExt, AsyncWriteExt}; fn init() { let _ = env_logger::builder().is_test(true).try_init(); } fn tempfile() -> Result { Ok(fs::File::from_std(tempfile::tempfile()?)) } async fn file_to_buf(file: &mut fs::File) -> Result> { file.rewind().await?; let mut buf = Vec::new(); io::copy(file, &mut buf) .await .context("Failed to read to buffer")?; Ok(buf) } #[tokio::test] async fn test_lock_directory() { init(); let dir = tempfile::tempdir().unwrap(); let _lock = Lock::acquire(dir.path()).await.unwrap(); let err = Lock::acquire(dir.path()).await.err().unwrap().to_string(); let (err, _) = err.split_once(": ").unwrap(); assert_eq!(err, "Failed to acquire exclusive lock for"); } #[tokio::test] async fn test_release_lock() { init(); let dir = tempfile::tempdir().unwrap(); { let _lock = Lock::acquire(dir.path()).await.unwrap(); let err = Lock::acquire(dir.path()).await.err().unwrap().to_string(); let (err, _) = err.split_once(": ").unwrap(); assert_eq!(err, "Failed to acquire exclusive lock for"); } let _lock = Lock::acquire(dir.path()).await.unwrap(); } fn bytes_block1() -> Vec { let mut bytes = Vec::new(); bytes.extend(39u16.to_be_bytes()); bytes.extend(b"sha256:"); bytes.extend([ 0xe8, 0x47, 0x12, 0x23, 0x87, 0x09, 0x39, 0x8f, 0x6d, 0x34, 0x9d, 0xc2, 0x25, 0x0b, 0x0e, 0xfc, 0xa4, 0xb7, 0x2d, 0x8c, 0x2b, 0xfb, 0x7b, 0x74, 0x33, 0x9d, 0x30, 0xba, 0x94, 0x05, 0x6b, 0x14, ]); bytes.extend(1337u64.to_be_bytes()); bytes.extend(4u64.to_be_bytes()); bytes.extend(b"ohai"); bytes } fn bytes_block2() -> Vec { let mut bytes = Vec::new(); bytes.extend(39u16.to_be_bytes()); bytes.extend(b"sha256:"); bytes.extend([ 0xa8, 0xf0, 0xaf, 0x3c, 0x68, 0xac, 0xb0, 0x82, 0xa4, 0x65, 0xc9, 0x68, 0x0e, 0x79, 0x02, 0x61, 0x55, 0xcb, 0x56, 0x69, 0x2d, 0xa7, 0x36, 0x4d, 0xf7, 0x37, 0xc4, 0xe4, 0x75, 0xb7, 0x3a, 0x3a, ]); bytes.extend(1337u64.to_be_bytes()); bytes.extend(20u64.to_be_bytes()); bytes.extend(b"hello world, it's me"); bytes } #[tokio::test] async fn test_tail_integrity_one_block() { init(); // write data let mut file = tempfile().unwrap(); file.write_all(&bytes_block1()).await.unwrap(); file.rewind().await.unwrap(); // verify let mut exclusive = Exclusive::dummy().unwrap(); exclusive .ensure_tail_integrity("/tmp/apt-swarm/sha256:xx", &mut file) .await .unwrap(); let buf = file_to_buf(&mut file).await.unwrap(); assert_eq!( buf, &[ 0, 39, 115, 104, 97, 50, 53, 54, 58, 232, 71, 18, 35, 135, 9, 57, 143, 109, 52, 157, 194, 37, 11, 14, 252, 164, 183, 45, 140, 43, 251, 123, 116, 51, 157, 48, 186, 148, 5, 107, 20, 0, 0, 0, 0, 0, 0, 5, 57, 0, 0, 0, 0, 0, 0, 0, 4, 111, 104, 97, 105, ] ); } #[tokio::test] async fn test_tail_integrity_two_blocks() { init(); // write data let mut file = tempfile().unwrap(); file.write_all(&bytes_block1()).await.unwrap(); file.write_all(&bytes_block2()).await.unwrap(); file.rewind().await.unwrap(); // verify let mut exclusive = Exclusive::dummy().unwrap(); exclusive .ensure_tail_integrity("/tmp/apt-swarm/sha256:xx", &mut file) .await .unwrap(); let buf = file_to_buf(&mut file).await.unwrap(); assert_eq!( buf, &[ 0, 39, 115, 104, 97, 50, 53, 54, 58, 232, 71, 18, 35, 135, 9, 57, 143, 109, 52, 157, 194, 37, 11, 14, 252, 164, 183, 45, 140, 43, 251, 123, 116, 51, 157, 48, 186, 148, 5, 107, 20, 0, 0, 0, 0, 0, 0, 5, 57, 0, 0, 0, 0, 0, 0, 0, 4, 111, 104, 97, 105, 0, 39, 115, 104, 97, 50, 53, 54, 58, 168, 240, 175, 60, 104, 172, 176, 130, 164, 101, 201, 104, 14, 121, 2, 97, 85, 203, 86, 105, 45, 167, 54, 77, 247, 55, 196, 228, 117, 183, 58, 58, 0, 0, 0, 0, 0, 0, 5, 57, 0, 0, 0, 0, 0, 0, 0, 20, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 44, 32, 105, 116, 39, 115, 32, 109, 101, ] ); } #[tokio::test] async fn test_tail_integrity_empty() { init(); let mut file = tempfile().unwrap(); let mut exclusive = Exclusive::dummy().unwrap(); exclusive .ensure_tail_integrity("/tmp/apt-swarm/sha256:xx", &mut file) .await .unwrap(); assert_eq!( exclusive.verified_shards, ["/tmp/apt-swarm/sha256:xx".into()].into_iter().collect() ); let buf = file_to_buf(&mut file).await.unwrap(); assert_eq!(buf, b""); } #[tokio::test] async fn test_tail_integrity_first_block_truncated() { init(); // write data (test with partial block header) let mut file = tempfile().unwrap(); file.write_all(&bytes_block1()[..43]).await.unwrap(); file.rewind().await.unwrap(); // verify let mut exclusive = Exclusive::dummy().unwrap(); exclusive .ensure_tail_integrity("/tmp/apt-swarm/sha256:xx", &mut file) .await .unwrap(); let buf = file_to_buf(&mut file).await.unwrap(); assert_eq!(buf, b""); } #[tokio::test] async fn test_tail_integrity_second_block_truncated() { init(); // write data (test with partial block data) let mut file = tempfile().unwrap(); file.write_all(&bytes_block1()).await.unwrap(); file.write_all(&bytes_block2()[..58]).await.unwrap(); file.rewind().await.unwrap(); // verify let mut exclusive = Exclusive::dummy().unwrap(); exclusive .ensure_tail_integrity("/tmp/apt-swarm/sha256:xx", &mut file) .await .unwrap(); let buf = file_to_buf(&mut file).await.unwrap(); assert_eq!( buf, &[ 0, 39, 115, 104, 97, 50, 53, 54, 58, 232, 71, 18, 35, 135, 9, 57, 143, 109, 52, 157, 194, 37, 11, 14, 252, 164, 183, 45, 140, 43, 251, 123, 116, 51, 157, 48, 186, 148, 5, 107, 20, 0, 0, 0, 0, 0, 0, 5, 57, 0, 0, 0, 0, 0, 0, 0, 4, 111, 104, 97, 105, ] ); } } apt-swarm-0.5.1/src/db/header.rs000064400000000000000000000171411046102023000145200ustar 00000000000000use crate::errors::*; use sha2::{Digest, Sha256}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; pub type HashLength = u16; pub type UncompressedLength = u64; pub type DataLength = u64; #[derive(Debug, PartialEq)] pub struct CryptoHash(pub String); impl CryptoHash { pub fn as_str(&self) -> &str { &self.0 } #[inline] fn split_marker(bytes: &[u8]) -> Result<(&[u8], &[u8])> { let offset = memchr::memchr(b':', bytes).context("Failed to find hash id marker `:`")?; let (hash_id, hash_data) = bytes.split_at(offset + 1); Ok((hash_id, hash_data)) } pub fn decode(bytes: &[u8]) -> Result { // determine the `sha256:` and binary boundary let (hash_id, hash_data) = Self::split_marker(bytes)?; // allocate memory for our decoded hash let mut hash = hash_id.to_owned(); hash.resize(hash.len() + hash_data.len() * 2, 0u8); // decode binary to hex hex::encode_to_slice(hash_data, &mut hash[hash_id.len()..]) .context("Failed to encode header hash into buffer")?; // ensure everything is utf8 and return let hash = String::from_utf8(hash).context("Decoded crypto hash is invalid utf8")?; Ok(CryptoHash(hash)) } pub fn encode(&self) -> Result> { // determine the `sha256:` and hex boundary let (hash_id, hash_data) = Self::split_marker(self.0.as_bytes())?; // allocate memory for our encoded hash let mut hash = hash_id.to_owned(); hash.resize(hash.len() + hash_data.len().div_ceil(2), 0u8); // encode binary to hex hex::decode_to_slice(hash_data, &mut hash[hash_id.len()..]) .context("Failed to decode header hash into buffer")?; Ok(hash) } pub fn calculate(bytes: &[u8]) -> Self { let mut hasher = Sha256::new(); hasher.update(bytes); let result = hasher.finalize(); CryptoHash(format!("sha256:{result:x}")) } } #[derive(Debug, PartialEq)] pub struct BlockHeader { pub hash: CryptoHash, pub uncompressed_length: u64, pub data_length: u64, } impl BlockHeader { pub fn new(hash: CryptoHash, uncompressed_length: usize, data_length: usize) -> Self { Self { hash, uncompressed_length: uncompressed_length as u64, data_length: data_length as u64, } } async fn read_u16(mut reader: R, n: &mut usize) -> Result { let mut bytes = [0u8; u16::BITS as usize / 8]; *n += reader.read_exact(&mut bytes).await?; let num = u16::from_be_bytes(bytes); Ok(num) } async fn read_u64(mut reader: R, n: &mut usize) -> Result { let mut bytes = [0u8; u64::BITS as usize / 8]; *n += reader.read_exact(&mut bytes).await?; let num = u64::from_be_bytes(bytes); Ok(num) } pub async fn parse(mut reader: R) -> Result<(Self, usize)> { let mut n = 0; // read hash length field let hash_length = Self::read_u16(&mut reader, &mut n) .await .context("Failed to read hash length")?; // read hash bytes let mut hash_bytes = vec![0u8; hash_length as usize]; n += reader .read_exact(&mut hash_bytes) .await .context("Failed to read hash bytes")?; let hash = CryptoHash::decode(&hash_bytes)?; // read uncompressed length field let uncompressed_length = Self::read_u64(&mut reader, &mut n) .await .context("Failed to read uncompressed length")?; // read data length field let data_length = Self::read_u64(&mut reader, &mut n) .await .context("Failed to read data length")?; let header = BlockHeader { hash, uncompressed_length, data_length, }; trace!("Parsed block header: {header:?}"); Ok((header, n)) } pub async fn write(&self, mut writer: W) -> Result { let mut n = 0; // hash/key let encoded = self.hash.encode()?; let hash_length_bytes = HashLength::to_be_bytes(encoded.len() as u16); writer.write_all(&hash_length_bytes).await?; n += hash_length_bytes.len(); writer.write_all(&encoded).await?; n += encoded.len(); // uncompressed length let uncompressed_length_bytes = UncompressedLength::to_be_bytes(self.uncompressed_length); writer.write_all(&uncompressed_length_bytes).await?; n += uncompressed_length_bytes.len(); // compressed length let data_length_bytes = DataLength::to_be_bytes(self.data_length); writer.write_all(&data_length_bytes).await?; n += data_length_bytes.len(); Ok(n) } } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_parse_header() { let mut bytes = Vec::::new(); bytes.extend(39u16.to_be_bytes()); bytes.extend(b"sha256:"); bytes.extend(&[ 0xe8, 0x47, 0x12, 0x23, 0x87, 0x09, 0x39, 0x8f, 0x6d, 0x34, 0x9d, 0xc2, 0x25, 0x0b, 0x0e, 0xfc, 0xa4, 0xb7, 0x2d, 0x8c, 0x2b, 0xfb, 0x7b, 0x74, 0x33, 0x9d, 0x30, 0xba, 0x94, 0x05, 0x6b, 0x14, ]); bytes.extend(1337u64.to_be_bytes()); bytes.extend(4u64.to_be_bytes()); // data is not part of the header // bytes.extend(b"ohai"); let (header, bytes_read) = BlockHeader::parse(&bytes[..]).await.unwrap(); assert_eq!( header, BlockHeader { hash: CryptoHash( "sha256:e84712238709398f6d349dc2250b0efca4b72d8c2bfb7b74339d30ba94056b14" .to_string() ), uncompressed_length: 1337, data_length: 4, } ); assert_eq!(bytes_read, 57); } #[tokio::test] async fn test_write_header() { let header = BlockHeader { hash: CryptoHash( "sha256:e84712238709398f6d349dc2250b0efca4b72d8c2bfb7b74339d30ba94056b14" .to_string(), ), uncompressed_length: 1337, data_length: 4, }; let mut buf = Vec::new(); header.write(&mut buf).await.unwrap(); let mut expected = Vec::::new(); expected.extend(39u16.to_be_bytes()); expected.extend(b"sha256:"); expected.extend(&[ 0xe8, 0x47, 0x12, 0x23, 0x87, 0x09, 0x39, 0x8f, 0x6d, 0x34, 0x9d, 0xc2, 0x25, 0x0b, 0x0e, 0xfc, 0xa4, 0xb7, 0x2d, 0x8c, 0x2b, 0xfb, 0x7b, 0x74, 0x33, 0x9d, 0x30, 0xba, 0x94, 0x05, 0x6b, 0x14, ]); expected.extend(1337u64.to_be_bytes()); expected.extend(4u64.to_be_bytes()); assert_eq!(buf, expected); } #[test] fn test_hash_decode_encode() { let mut bytes = Vec::::new(); bytes.extend(b"sha256:"); bytes.extend(&[ 0xe8, 0x47, 0x12, 0x23, 0x87, 0x09, 0x39, 0x8f, 0x6d, 0x34, 0x9d, 0xc2, 0x25, 0x0b, 0x0e, 0xfc, 0xa4, 0xb7, 0x2d, 0x8c, 0x2b, 0xfb, 0x7b, 0x74, 0x33, 0x9d, 0x30, 0xba, 0x94, 0x05, 0x6b, 0x14, ]); let hash = CryptoHash::decode(&bytes).unwrap(); assert_eq!( hash, CryptoHash( "sha256:e84712238709398f6d349dc2250b0efca4b72d8c2bfb7b74339d30ba94056b14" .to_string() ) ); let encoded = hash.encode().unwrap(); assert_eq!(encoded, bytes); } } apt-swarm-0.5.1/src/db/mod.rs000064400000000000000000000034561046102023000140530ustar 00000000000000pub mod channel; pub mod compression; pub mod consume; pub mod disk; pub mod exclusive; pub mod header; pub mod proto; #[cfg(unix)] pub mod unix; pub use self::channel::{DatabaseServer, DatabaseServerClient}; pub use self::disk::{AccessMode, Database}; pub use self::proto::DatabaseHandle; use crate::errors::*; use crate::signed::Signed; use crate::sync; use async_trait::async_trait; use sequoia_openpgp::Fingerprint; pub type Key = Vec; pub type Value = Vec; #[async_trait] pub trait DatabaseClient { async fn add_release(&mut self, fp: &Fingerprint, signed: &Signed) -> Result; async fn index_from_scan(&mut self, query: &sync::TreeQuery) -> Result<(String, usize)>; async fn batch_index_from_scan( &mut self, query: &mut sync::TreeQuery, ) -> Result<(sync::BatchIndex, usize)> { let mut batch = sync::BatchIndex::new(); let mut total = 0; query.enter(); loop { let (index, count) = self.index_from_scan(query).await?; let prefix = query.prefix.as_deref().unwrap_or(""); trace!( "Calculated index for prefix: index={index:?}, prefix={:?}, count={count:?}", prefix ); // TODO: consider only adding responses with count > 0 batch.add(index, prefix.to_string(), count)?; total += count; if query.increment() { break; } } Ok((batch, total)) } /// Get all documents matching this prefix /// We may refactor this again because it's essentially a buffering scan_prefix async fn spill(&self, prefix: &[u8]) -> Result>; async fn get_value(&self, key: &[u8]) -> Result; async fn count(&mut self, prefix: &[u8]) -> Result; } apt-swarm-0.5.1/src/db/proto.rs000064400000000000000000000046241046102023000144350ustar 00000000000000#[cfg(unix)] use super::unix::DatabaseUnixClient; use super::{Database, DatabaseClient}; use crate::db; use crate::errors::*; use crate::signed::Signed; use crate::sync; use async_trait::async_trait; use bstr::BString; use sequoia_openpgp::Fingerprint; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub enum Query { AddRelease(String, Signed), IndexFromScan(SyncQuery), // Delete(BString), Count(BString), } #[derive(Serialize, Deserialize)] pub struct SyncQuery { pub fp: String, pub hash_algo: String, pub prefix: Option, } #[derive(Debug, Serialize, Deserialize)] pub enum Response { Ok, Inserted(String), Num(u64), Index((String, usize)), Error(ErrorResponse), } #[derive(Debug, Serialize, Deserialize)] pub struct ErrorResponse { pub err: String, } impl ErrorResponse { pub fn new(err: &anyhow::Error) -> Self { Self { err: format!("{:#}", err), } } } pub enum DatabaseHandle { Direct(Database), #[cfg(unix)] Unix(DatabaseUnixClient), } #[async_trait] impl DatabaseClient for DatabaseHandle { async fn add_release(&mut self, fp: &Fingerprint, signed: &Signed) -> Result { match self { Self::Direct(db) => db.add_release(fp, signed).await, #[cfg(unix)] Self::Unix(unix) => unix.add_release(fp, signed).await, } } async fn index_from_scan(&mut self, query: &sync::TreeQuery) -> Result<(String, usize)> { match self { Self::Direct(db) => db.index_from_scan(query).await, #[cfg(unix)] Self::Unix(unix) => unix.index_from_scan(query).await, } } async fn spill(&self, prefix: &[u8]) -> Result> { match self { Self::Direct(db) => db.spill(prefix).await, #[cfg(unix)] Self::Unix(db) => db.spill(prefix).await, } } async fn get_value(&self, key: &[u8]) -> Result { match self { Self::Direct(db) => db.get_value(key).await, #[cfg(unix)] Self::Unix(unix) => unix.get_value(key).await, } } async fn count(&mut self, prefix: &[u8]) -> Result { match self { Self::Direct(db) => db.count(prefix).await, #[cfg(unix)] Self::Unix(unix) => unix.count(prefix).await, } } } apt-swarm-0.5.1/src/db/unix.rs000064400000000000000000000066661046102023000142650ustar 00000000000000use super::proto::{Query, Response, SyncQuery}; use super::DatabaseClient; use crate::db; use crate::errors::*; use crate::signed::Signed; use crate::sync; use async_trait::async_trait; use bstr::BString; use sequoia_openpgp::Fingerprint; use std::path::Path; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufStream}; use tokio::net::UnixStream; pub struct DatabaseUnixClient { socket: BufStream, } impl DatabaseUnixClient { pub async fn connect(path: &Path) -> Result { let socket = UnixStream::connect(path) .await .with_context(|| anyhow!("Failed to connect to socket at {path:?}"))?; debug!("Connected to unix domain socket at {path:?}"); let socket = BufStream::new(socket); Ok(Self { socket }) } pub async fn send_query(&mut self, q: &Query) -> Result<()> { let mut json = serde_json::to_string(q).context("Failed to serialize message as json")?; json.push('\n'); self.socket .write_all(json.as_bytes()) .await .context("Failed to send to database server")?; self.socket.flush().await?; Ok(()) } pub async fn recv_response(&mut self) -> Result { let mut buf = Vec::new(); self.socket.read_until(b'\n', &mut buf).await?; if buf.is_empty() { bail!("Database has disconnected without sending a response"); } else if buf == b"\n" { Ok(Response::Ok) } else { let response = serde_json::from_slice::(&buf)?; match response { Response::Error(error) => { bail!("Error from server: {}", error.err); } _ => Ok(response), } } } } #[async_trait] impl DatabaseClient for DatabaseUnixClient { async fn add_release(&mut self, fp: &Fingerprint, signed: &Signed) -> Result { self.send_query(&Query::AddRelease(fp.to_string(), signed.clone())) .await?; let inserted = self.recv_response().await?; if let Response::Inserted(hash) = inserted { info!("Added release to database: {hash:?}"); Ok(hash) } else { bail!("Unexpected response type from database: {inserted:?}"); } } async fn index_from_scan(&mut self, query: &sync::TreeQuery) -> Result<(String, usize)> { self.send_query(&Query::IndexFromScan(SyncQuery { fp: query.fp.to_string(), hash_algo: query.hash_algo.clone(), prefix: query.prefix.clone(), })) .await?; let index = self.recv_response().await?; if let Response::Index(index) = index { Ok(index) } else { bail!("Unexpected response type from database: {index:?}"); } } async fn spill(&self, _prefix: &[u8]) -> Result> { todo!("DatabaseUnixClient::spill") } async fn get_value(&self, _key: &[u8]) -> Result { todo!("DatabaseUnixClient::get_value") } async fn count(&mut self, prefix: &[u8]) -> Result { self.send_query(&Query::Count(BString::new(prefix.to_vec()))) .await?; let count = self.recv_response().await?; if let Response::Num(count) = count { Ok(count) } else { bail!("Unexpected response type from database: {count:?}"); } } } apt-swarm-0.5.1/src/errors.rs000064400000000000000000000001551046102023000142140ustar 00000000000000pub use anyhow::{anyhow, bail, Context as _, Error, Result}; pub use log::{debug, error, info, trace, warn}; apt-swarm-0.5.1/src/fetch.rs000064400000000000000000000060121046102023000137670ustar 00000000000000use crate::config; use crate::config::Repository; use crate::db::DatabaseClient; use crate::errors::*; use crate::keyring::Keyring; use crate::signed::Signed; use sequoia_openpgp::Fingerprint; use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; use tokio::task::JoinSet; pub const DEFAULT_CONCURRENCY: usize = 4; pub const CONNECT_TIMEOUT: Duration = Duration::from_secs(15); pub const READ_TIMEOUT: Duration = Duration::from_secs(60); async fn fetch_repository_updates( client: &reqwest::Client, keyring: &Option, repository: &config::Repository, ) -> Result, Signed)>> { let mut out = Vec::new(); for source in &repository.urls { let Ok(signed) = source .fetch(client) .await .inspect_err(|err| error!("Error fetching latest release: {err:#}")) else { continue; }; for item in signed.canonicalize(keyring.as_ref())? { out.push(item); } } Ok(out) } pub fn client(proxy: Option) -> Result { let mut client = reqwest::Client::builder() .connect_timeout(CONNECT_TIMEOUT) .read_timeout(READ_TIMEOUT); if let Some(proxy) = proxy { let proxy = format!("socks5h://{proxy:?}"); let proxy = reqwest::Proxy::all(&proxy) .with_context(|| anyhow!("Failed to parse as proxy: {proxy:?}"))?; client = client.proxy(proxy); } let client = client.build().context("Failed to setup http client")?; Ok(client) } pub async fn fetch_updates( db: &mut D, keyring: Arc>, concurrency: Option, repositories: Vec, proxy: Option, ) -> Result<()> { let concurrency = concurrency.unwrap_or(DEFAULT_CONCURRENCY); let mut queue = repositories.into_iter(); let mut pool = JoinSet::new(); let client = client(proxy)?; loop { while pool.len() < concurrency { if let Some(repository) = queue.next() { let client = client.clone(); let keyring = keyring.clone(); pool.spawn(async move { fetch_repository_updates(&client, &keyring, &repository).await }); } else { // no more tasks to schedule break; } } if let Some(join) = pool.join_next().await { match join.context("Failed to join task")? { Ok(list) => { for (fp, variant) in list { let fp = fp.context( "Signature can't be imported because the signature is unverified", )?; db.add_release(&fp, &variant).await?; } } Err(err) => error!("Error fetching latest release: {err:#}"), } } else { // no more tasks in pool break; } } Ok(()) } apt-swarm-0.5.1/src/keyring.rs000064400000000000000000000144641046102023000143600ustar 00000000000000use crate::config::Config; use crate::errors::*; use crate::pgp; use crate::pgp::SigningKey; use memchr::memchr; use sequoia_openpgp::packet::Signature; use sequoia_openpgp::types::SignatureType; use sequoia_openpgp::{Fingerprint, KeyHandle}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::collections::BTreeMap; #[derive(Debug, Clone)] pub struct Subkey { pub parent: Fingerprint, pub fingerprint: Fingerprint, } #[derive(Debug, Default, Clone)] pub struct Keyring { pub keys: BTreeMap, pub identifiers: BTreeMap, } impl Keyring { pub fn load(config: &Config) -> Result { let mut keyring = Keyring::default(); for repository in &config.data.repositories { keyring.add_keyring(repository.keyring.as_bytes())?; } Ok(keyring) } pub fn new(keyring: &[u8]) -> Result { let mut k = Keyring::default(); k.add_keyring(keyring)?; Ok(k) } pub fn add_keyring(&mut self, keyring: &[u8]) -> Result<()> { let keys = pgp::load(keyring)?; for key in keys { self.register_identifiers(&key); let fingerprint = key.fingerprint.clone(); self.keys.insert(fingerprint, key); } Ok(()) } pub fn register_identifiers(&mut self, key: &SigningKey) { for (id, fp) in &key.key_handles { let id = id.to_string(); trace!("Linking identifier for key {:X}: {id:?}", key.fingerprint); self.identifiers.insert( id, Subkey { parent: key.fingerprint.clone(), fingerprint: fp.clone(), }, ); } } pub fn all_fingerprints(&self) -> Vec { self.keys .values() .flat_map(|k| &k.key_handles) .flat_map(|(k, _)| { if let KeyHandle::Fingerprint(fp) = k { Some(fp.to_owned()) } else { None } }) .collect() } pub fn find_signing_key(&self, sig: &Signature) -> Result<(&Fingerprint, &SigningKey)> { for issuer in sig.get_issuers() { debug!("Found issuer in signature packet: {issuer:?}"); if let Some(subkey) = self.identifiers.get(&issuer.to_string()) { debug!("Found fingerprint for given issuer: {:?}", subkey.parent); let key = self.keys.get(&subkey.parent).with_context(|| { anyhow!( "Failed to get signing key by fingerprint: {:?}", subkey.parent ) })?; return Ok((&subkey.fingerprint, key)); } } bail!("Could not find key for given signature") } // TODO: this function normalizes data, this should be taken into account pub fn verify(&self, data: &[u8], sig: &Signature) -> Result { let (signer_fp, signing_key) = self.find_signing_key(sig)?; let body: Cow<[u8]> = match sig.typ() { SignatureType::Binary => Cow::Borrowed(data), SignatureType::Text => { let mut out = Vec::new(); let mut bytes = data; while !bytes.is_empty() { if let Some(idx) = memchr(b'\n', bytes) { let line = &bytes[..idx]; // TODO: this could be a `\r\n` newline, do we need to check for `\r`? bytes = &bytes[idx + 1..]; out.extend(line); if !bytes.is_empty() { out.extend(b"\r\n"); } } else { out.extend(bytes); bytes = &[]; } } Cow::Owned(out) } unsupported => bail!("Unsupported signature type: {unsupported:?}"), }; for key in signing_key.cert.keys() { let key = key.key(); // TODO: are we sure the issuer fingerprint is always pointing to the right key? let key_fp = key.fingerprint(); debug!("Attempting verification with {:X}", key_fp); if key_fp != *signer_fp { debug!("This key was not the issuer, skipping: {:?}", key_fp); continue; } sig.clone() .verify_message(key, body) .context("Failed to verify message")?; debug!("Successfully verified signature"); return Ok(key_fp); } bail!("Signature could not be verified with any of the pgp certificates public keys") } pub fn generate_report(&self) -> Result { Ok(KeyringReport { keys: self.keys.values().map(KeyReport::generate).collect(), }) } } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct KeyringReport { pub keys: Vec, } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct KeyReport { pub primary_fingerprint: String, pub uids: Vec, pub subkeys: Vec, } impl KeyReport { pub fn generate(key: &pgp::SigningKey) -> Self { KeyReport { primary_fingerprint: format!("{:X}", key.fingerprint), uids: key.uids.clone(), subkeys: key.subkeys.iter().map(SubkeyReport::generate).collect(), } } } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct SubkeyReport { pub fingerprint: String, pub is_primary: bool, pub for_authentication: bool, pub for_certification: bool, pub for_signing: bool, pub for_storage_encryption: bool, pub for_transport_encryption: bool, } impl SubkeyReport { pub fn generate(key: &pgp::Subkey) -> Self { SubkeyReport { fingerprint: format!("{:X}", key.fingerprint), is_primary: key.is_primary, for_authentication: key.for_authentication, for_certification: key.for_certification, for_signing: key.for_signing, for_storage_encryption: key.for_storage_encryption, for_transport_encryption: key.for_transport_encryption, } } } apt-swarm-0.5.1/src/latest.rs000064400000000000000000000775361046102023000142150ustar 00000000000000use crate::db::Database; use crate::errors::*; use crate::signed::Signed; use bstr::{BString, ByteSlice}; use chrono::{DateTime, NaiveDateTime, Utc}; use futures::StreamExt; use sequoia_openpgp::Fingerprint; use std::str; pub type Latest = (DateTime, Vec, Vec, BString, usize); pub fn parse_date(date: &str) -> Result> { let datetime = NaiveDateTime::parse_from_str(date, "%a, %d %b %Y %T %Z") .context("Failed to parse Date header")?; Ok(datetime.and_utc()) } pub fn extract_date_and_attachment(mut data: &[u8]) -> Option<(DateTime, &[u8])> { let mut date = None; let mut attachment = "".as_bytes(); while !data.is_empty() { let (line, trailing) = data.split_once_str(b"\n").unwrap_or((data, b"")); if line.is_empty() { attachment = trailing; break; } if let Some(value) = line.strip_prefix(b"Date: ") { if let Ok(value) = str::from_utf8(value) { debug!("Parsing date header: {value:?}"); date = parse_date(value).ok(); } } data = trailing; } Some((date?, attachment)) } fn update_latest( latest: &mut Option, key: Vec, bytes: Vec, max_allowed_datetime: DateTime, ) -> Result<()> { let (signed, _trailing) = Signed::from_bytes(&bytes)?; let content = signed.content; let Some((date, attachment)) = extract_date_and_attachment(&content) else { return Ok(()); }; if date > max_allowed_datetime { let key = String::from_utf8_lossy(&key); warn!("Skipping document with date from the future: {date:?}, {key}"); return Ok(()); } let idx = content.len() - attachment.len(); let new = Some((date, key, bytes, content, idx)); // if the new current entry is more recent, update // if there's no current latest, `new` always wins // if there's a tie in the datetime, it uses the key to break the tie if new > *latest { *latest = new; } Ok(()) } pub async fn find( db: &Database, fp: Fingerprint, max_allowed_datetime: DateTime, ) -> Result> { let prefix = format!("{fp}/"); let stream = db.scan_values(prefix.as_bytes()); let mut latest = None; tokio::pin!(stream); while let Some(item) = stream.next().await { let (key, value) = item.context("Failed to read from database (scan-latest)")?; update_latest(&mut latest, key, value, max_allowed_datetime)?; } Ok(latest) } #[cfg(test)] mod test { use super::*; use crate::db::header::CryptoHash; use chrono::TimeZone; #[test] fn test_parse_date() { assert_eq!( parse_date("Wed, 21 Aug 2024 15:36:07 UTC").unwrap(), Utc.with_ymd_and_hms(2024, 8, 21, 15, 36, 7).unwrap() ); assert_eq!( parse_date("Fri, 14 Feb 2025 11:28:01 UTC").unwrap(), Utc.with_ymd_and_hms(2025, 2, 14, 11, 28, 1).unwrap() ); assert_eq!( parse_date("Sun, 05 Nov 2023 19:19:57 UTC").unwrap(), Utc.with_ymd_and_hms(2023, 11, 5, 19, 19, 57).unwrap() ); } #[test] fn extract_release_date() { let data = b"Origin: Valve Software LLC Label: Steam launcher Codename: stable Date: Wed, 01 Mar 2023 19:01:42 UTC Architectures: i386 amd64 Components: steam Description: Steam packages for Ubuntu and Debian MD5Sum: 2cc0cb39217ac21fb9d9e3078ffe1c95 2846 steam/binary-i386/Packages 685cf20f3ec2ac8b73c4619ca8a26bfa 1292 steam/binary-i386/Packages.gz 1bf3fd71424a1112a232f8617452bc38 135 steam/binary-i386/Release 0cbb5e2098896d0ec9398430eec59081 2222 steam/binary-amd64/Packages baaca0b481c88853e597e5eff662b04a 1101 steam/binary-amd64/Packages.gz 92c8a3be7382bf8dbe080afc094c799a 136 steam/binary-amd64/Release ce8c452267b4804c551a866a0e14936d 1058 steam/source/Sources 7372595c640f014ab5015417b05bf2b7 591 steam/source/Sources.gz 6809037802698e089478642ab605bf38 137 steam/source/Release SHA1: 9e97f7b06aad48a50815c6176e95a749553bdf15 2846 steam/binary-i386/Packages f8c1cbabbb4443e98e225d7e4b632e9349fba43a 1292 steam/binary-i386/Packages.gz 137f598735523f918e676cb500218b70394d7265 135 steam/binary-i386/Release fe9d79b187dd510d849bf04070a93e60cff3c450 2222 steam/binary-amd64/Packages 950c55d9408f711f86e173cde80627e42a28c895 1101 steam/binary-amd64/Packages.gz 6958f751e15104d4a727f38185ec9faf25d04a75 136 steam/binary-amd64/Release 5f7555981af1f82623b93e2e62a97c03d0e5b44c 1058 steam/source/Sources b887a9ff370656af32631317d2184b39d44e9d37 591 steam/source/Sources.gz aa51a6ea3e0664c790e78a62c7d4662725d1c35a 137 steam/source/Release SHA256: 8a33a3338e878e0bd993b28d660f4075ecfff9f2b9e8e056810dd50b2371eb43 2846 steam/binary-i386/Packages 8c3109fee36ffc26ac61941c3f243bfdd4932aa90390b89e6c825d9d706673fc 1292 steam/binary-i386/Packages.gz d21b7028166ccdac26f4c8c1084dad81d0d1e45f82652bcf1b28d0277b795da0 135 steam/binary-i386/Release 6637cebce9fa077b22daac68f35bfa91493802fde021701b38f6f8a6866b547c 2222 steam/binary-amd64/Packages 4199ba44aeb45ebc0697378fe98738f10ff332cab03337529ddcd29ce4d0ac51 1101 steam/binary-amd64/Packages.gz 9e766d8dedb507da4c41cca732b3eff724f53630efa9dbc798ef78dfdfbc5b41 136 steam/binary-amd64/Release 87bc01cbcde97b917be01df34cd05772f638c3d8e93eddeba17eedb2d70a2f95 1058 steam/source/Sources 841ac95be57e35183644e4efed99dfc0d39b6039f049ebcf9815e4e54e3e4d38 591 steam/source/Sources.gz 4cc31b1d8142f8e6145c2331b198f92c825cf6677205d97227f90268ee8c50d0 137 steam/source/Release "; let (date, attachment) = extract_date_and_attachment(data).unwrap(); assert_eq!(date, Utc.with_ymd_and_hms(2023, 3, 1, 19, 1, 42).unwrap()); assert_eq!(attachment, b""); } #[test] fn extract_attachment() { let data = b"Date: Sat, 22 Feb 2025 05:33:44 UTC Commit: 07c76667ce66d38cf08bf1e331256d22d338b2a1 \xc3\x28this is\n\narbitrary\nbinary\xf0\x28\x8c\x28"; let (date, attachment) = extract_date_and_attachment(data).unwrap(); assert_eq!(date, Utc.with_ymd_and_hms(2025, 2, 22, 5, 33, 44).unwrap()); assert_eq!( attachment, b"\xc3\x28this is\n\narbitrary\nbinary\xf0\x28\x8c\x28" ); } const RELEASE_DATA: &[&[u8]] = &[ b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: testing Codename: trixie Date: Fri, 15 Nov 2024 11:28:01 UTC Valid-Until: Wed, 25 Dec 2024 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: 4f1c7cdf829350ecd5f19446f105c224 5155 main/binary-amd64/Packages 5efe887860f463dee1257876419c5ead 2452 main/binary-amd64/Packages.gz 8993e226d487ae15a57b295ee7163410 72 main/binary-amd64/Release 301e1861261a0cac8704012e48bf9ae0 5122 main/binary-arm64/Packages 5a8be3a82df40c1d67a83b6f74031b24 2432 main/binary-arm64/Packages.gz 04848f1e95e99ecd5266016b54f6ba3b 72 main/binary-arm64/Release ebea07f2c2dee778846066370e6e8c89 5151 main/binary-i386/Packages 69db395f0f704f7c2002ccf3dd675874 2448 main/binary-i386/Packages.gz c87b59e471c0b39de0cfca2638377f8f 71 main/binary-i386/Release b3c0d559a60239b9ab703ba905aae6f5 2939 main/source/Sources fb531fdc96ffc0afcc24ba04dd27fca4 1258 main/source/Sources.gz 704ca88fd2254271bed6e9700954c775 73 main/source/Release SHA1: 88549bebf05677460cd5f3737bba3308ddc00230 5155 main/binary-amd64/Packages c93610bbfa153e7128ab46d46115a9d7d306a0e0 2452 main/binary-amd64/Packages.gz 4790dd0652995711f37417277d9f240f43264004 72 main/binary-amd64/Release 9648703f6299f925ccdb2e6db73c0dcaabe5a2a2 5122 main/binary-arm64/Packages c5b3aadfaac20a671fac0f6f3020926afe1466a7 2432 main/binary-arm64/Packages.gz 559a5d2deafc73df93436224cae9eb13ce1476b7 72 main/binary-arm64/Release acaaf2190ee353082b472faf65a25b1b90ae594c 5151 main/binary-i386/Packages 2a749e0d470886f56299662ae4830fc10d69eda2 2448 main/binary-i386/Packages.gz 2c099ef796776b4f026e324a181929a95cb6fd6f 71 main/binary-i386/Release 669806decc4fbb53899c8ad78ac46f290543b5fd 2939 main/source/Sources dd38d54b49f079e5aa2100ef52a480f9a030be98 1258 main/source/Sources.gz 2ec604f75d95854298c93160692fa5d810497e8d 73 main/source/Release SHA256: affbb204a6e0e18f8b4730bb2fd43f2fefd5c7c1c80e04db702909b38e68764d 5155 main/binary-amd64/Packages 823125c3308508e8280f3864acfa32ebde37dcde2b66625900871649d965f043 2452 main/binary-amd64/Packages.gz 1cd4765e05f5d3491b247aab90ae65b779d3b0a5fa93d1076afd87f41a6aef92 72 main/binary-amd64/Release b9a81ec0de4b34c36727ac6403de0c69d078d06de3317ec287a7225e83c203d9 5122 main/binary-arm64/Packages bb03be229acab70c79d3ff1a874c5c4eca6f2e76f7dfece63190aad3ec1504a2 2432 main/binary-arm64/Packages.gz 291d5c3dd3e5a5de74cf8ca0261f9881ca8e0d3ea07bbee096d137eacf861bda 72 main/binary-arm64/Release 41e7710fcee9b0cee79bed7875e79747c383608d772a3bed5b14edb139baba85 5151 main/binary-i386/Packages b9ae9259fda7197e0d97d7eefe6e34482a80502a7f4d0cb9e5963c03b51a3670 2448 main/binary-i386/Packages.gz 03864d020cf80a7bd64d2f3a9122ad40482d2dfd776264534e172d518fe3136d 71 main/binary-i386/Release 8975f6acf34d666bca543d417913adb832b8b900fcc7aabe1c7671d65e5a6024 2939 main/source/Sources e5e0e6695226a4945e873fab8eb694e9ab8af8d94c6dc6373d40968116fda3f8 1258 main/source/Sources.gz fe0a611678e47cab4d8cc639eb7249cdfb506151360eab974388532b469753bd 73 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAABCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmc3MEEACgkQdKlBuiGe yBBYZgf+Oe+kmqQSD10o1O1bNmlFnFv2e81qyAD9Ka96+wDdVzYsoQbd82EE8r9U tx566aC7fON1+sknc+z+vHlG0PWGrSxE1nzeSi1NoBWl5FjPAy/mPIlatgAfowjK G4JhAsJKAyKR7WBRWmjWUrSl+HHBP3aB/jcwvrdN2dV4UBVkWJKYWelRTXWmzXOR VcjmHsFQDkY42wXz8biVCDd+urVLtGLW04m8us/l1ZVSKKATZecTVWYmhD/u+0oH tBIlcVdR6VgRIhB4QcMLalZJ60kmy+oFz/UI+rId3bnAN4j3tELqfcBhlaC8aLDi v34DhYj76SPDEB4BdO8q0byuf0Smlw== =93Mo -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: testing Codename: trixie Date: Fri, 14 Feb 2025 11:28:01 UTC Valid-Until: Wed, 26 Mar 2025 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: 4f1c7cdf829350ecd5f19446f105c224 5155 main/binary-amd64/Packages 5efe887860f463dee1257876419c5ead 2452 main/binary-amd64/Packages.gz 8993e226d487ae15a57b295ee7163410 72 main/binary-amd64/Release 301e1861261a0cac8704012e48bf9ae0 5122 main/binary-arm64/Packages 5a8be3a82df40c1d67a83b6f74031b24 2432 main/binary-arm64/Packages.gz 04848f1e95e99ecd5266016b54f6ba3b 72 main/binary-arm64/Release ebea07f2c2dee778846066370e6e8c89 5151 main/binary-i386/Packages 69db395f0f704f7c2002ccf3dd675874 2448 main/binary-i386/Packages.gz c87b59e471c0b39de0cfca2638377f8f 71 main/binary-i386/Release b3c0d559a60239b9ab703ba905aae6f5 2939 main/source/Sources fb531fdc96ffc0afcc24ba04dd27fca4 1258 main/source/Sources.gz 704ca88fd2254271bed6e9700954c775 73 main/source/Release SHA1: 88549bebf05677460cd5f3737bba3308ddc00230 5155 main/binary-amd64/Packages c93610bbfa153e7128ab46d46115a9d7d306a0e0 2452 main/binary-amd64/Packages.gz 4790dd0652995711f37417277d9f240f43264004 72 main/binary-amd64/Release 9648703f6299f925ccdb2e6db73c0dcaabe5a2a2 5122 main/binary-arm64/Packages c5b3aadfaac20a671fac0f6f3020926afe1466a7 2432 main/binary-arm64/Packages.gz 559a5d2deafc73df93436224cae9eb13ce1476b7 72 main/binary-arm64/Release acaaf2190ee353082b472faf65a25b1b90ae594c 5151 main/binary-i386/Packages 2a749e0d470886f56299662ae4830fc10d69eda2 2448 main/binary-i386/Packages.gz 2c099ef796776b4f026e324a181929a95cb6fd6f 71 main/binary-i386/Release 669806decc4fbb53899c8ad78ac46f290543b5fd 2939 main/source/Sources dd38d54b49f079e5aa2100ef52a480f9a030be98 1258 main/source/Sources.gz 2ec604f75d95854298c93160692fa5d810497e8d 73 main/source/Release SHA256: affbb204a6e0e18f8b4730bb2fd43f2fefd5c7c1c80e04db702909b38e68764d 5155 main/binary-amd64/Packages 823125c3308508e8280f3864acfa32ebde37dcde2b66625900871649d965f043 2452 main/binary-amd64/Packages.gz 1cd4765e05f5d3491b247aab90ae65b779d3b0a5fa93d1076afd87f41a6aef92 72 main/binary-amd64/Release b9a81ec0de4b34c36727ac6403de0c69d078d06de3317ec287a7225e83c203d9 5122 main/binary-arm64/Packages bb03be229acab70c79d3ff1a874c5c4eca6f2e76f7dfece63190aad3ec1504a2 2432 main/binary-arm64/Packages.gz 291d5c3dd3e5a5de74cf8ca0261f9881ca8e0d3ea07bbee096d137eacf861bda 72 main/binary-arm64/Release 41e7710fcee9b0cee79bed7875e79747c383608d772a3bed5b14edb139baba85 5151 main/binary-i386/Packages b9ae9259fda7197e0d97d7eefe6e34482a80502a7f4d0cb9e5963c03b51a3670 2448 main/binary-i386/Packages.gz 03864d020cf80a7bd64d2f3a9122ad40482d2dfd776264534e172d518fe3136d 71 main/binary-i386/Release 8975f6acf34d666bca543d417913adb832b8b900fcc7aabe1c7671d65e5a6024 2939 main/source/Sources e5e0e6695226a4945e873fab8eb694e9ab8af8d94c6dc6373d40968116fda3f8 1258 main/source/Sources.gz fe0a611678e47cab4d8cc639eb7249cdfb506151360eab974388532b469753bd 73 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAEBCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmevKMEACgkQdKlBuiGe yBA7PQgA1CoBKtlyBwbiNxB7OhLEFcuSp3U0ufVXtof2R09TvoUut8E8TRrAl10c q/6YMRA5Wb/uYfrtf0eWlgpXyH442yVFFY+forYrCfrhY54GXQJA6lguL8ZMqUdS SlES1JzvX65L73guCtbRXpSlcuLT7iTbvHlIIU5QTOtYKo59KdmcF01KPtrLLen1 fzdTlGxq7wPxQid3KuN3eZfZ20RUtU79amZxq8spdlZxN6eVU4orliMRR7YiLzIP EDMZ1vmPtHw4Hg24YGPC2OOzn2bUIb8TzQ3grbvc0BuvjokbPvZOG5j2jMEJjb+3 RkvVS4tolFfLOk8EQrCD7CdxxLqvZw== =Ea8d -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: stable Codename: bookworm Date: Fri, 14 Feb 2025 11:28:01 UTC Valid-Until: Wed, 26 Mar 2025 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: ef9461c1420699ca148523e82f1658ae 5165 main/binary-amd64/Packages 8472a30220841fd71471e513eea7feb5 2446 main/binary-amd64/Packages.gz 5a232710573bca3aae4b577c16ece1c1 71 main/binary-amd64/Release f4bc0d019adf816ed328ef8fc6d14da8 5132 main/binary-arm64/Packages 6810832523f5872f3a0e9a6d3271932f 2427 main/binary-arm64/Packages.gz 132565cf1e259a93a021e651e2ab3cd4 71 main/binary-arm64/Release 66294d5c2544ddcc9de4a63307844213 5161 main/binary-i386/Packages 7954605c44cec2c6732b09f4bf5146f5 2445 main/binary-i386/Packages.gz 5768b889feb010e5d4a62ad2003a6da2 70 main/binary-i386/Release 82b6a307db03b9cbfb6a267a57e64fb2 2953 main/source/Sources b7c2043f6c99a9e94d28401946d2d5aa 1258 main/source/Sources.gz 94aa68972888c3c4340efb5dd97b195e 72 main/source/Release SHA1: cfa9e4e3aeb947faabb55eeee303ef6b3a8a7d9e 5165 main/binary-amd64/Packages 7af71b12e4d55a900d027a97a13fd925d17fbc08 2446 main/binary-amd64/Packages.gz 0f979d666f966c427fab567771f55d6f9b963b79 71 main/binary-amd64/Release ec30ea663b574cf2ad6a7051b80733130a95967c 5132 main/binary-arm64/Packages 22d34250fe983afe37b3e09a39e4ed0cf503ffcd 2427 main/binary-arm64/Packages.gz 88b92baad3148570453a1ca4df4ac8f6c8b33c94 71 main/binary-arm64/Release 54f6e88fdab6f14055791f59f72f5707ae31ae2c 5161 main/binary-i386/Packages c9f0e20778899974b6267219246efc5113bef700 2445 main/binary-i386/Packages.gz c2f88e8b760b1fbd8e4fab14f02d7dd022309208 70 main/binary-i386/Release 48576f3f83997e38c1310c0a25affab6c9fabaa0 2953 main/source/Sources 859ac4cb8868b4b55253fd1ac8ceef2c010bc0e0 1258 main/source/Sources.gz e495ccf6037e86ba98915df00c0fce0839703634 72 main/source/Release SHA256: beab22bc6765408c14e65a66648d01b7c080f0f624c84a8c96fb0ec2e8ee32ee 5165 main/binary-amd64/Packages 90300ff39af1c8af397ccfd1a8fecffe26717b338f56b7b275c9207aad07ef10 2446 main/binary-amd64/Packages.gz 679b22e05826dc8eea366e3d9cc42471a9dbd03f95656d3a9541dfafcd82dc00 71 main/binary-amd64/Release 050f154f3d910bc349a9ff06b8d9c2f6ecfe89005fab4d576f817f6b841407b8 5132 main/binary-arm64/Packages b3c372797cdf5aa2310f1d0459d6fd8f2bf17abfc76bb5cb70891995ee745b8d 2427 main/binary-arm64/Packages.gz ffd961c4598ade54f231c2679cd0b7e8c346b66aa94cac0752d10deea94ee1d9 71 main/binary-arm64/Release 68e493ff92bdc6542ff3f86b8e18126c85131a3936313bc4ec868261e77778ed 5161 main/binary-i386/Packages 6691349d45f13e637acf77b52e4c6358e214336860ca012c4a1e6382cdf467e9 2445 main/binary-i386/Packages.gz e9a73c169e4a69b67bfec28ff6fda7a5c2236310cd9efe1d60eae4fb5305c7fa 70 main/binary-i386/Release 9a17f06b2326c7c48accc85a76e063ed0986ebff994869d95c746a7159ae3f2a 2953 main/source/Sources 03850f5c767373134f44c5c38ce4e3978ad8128faa118f024ccb264e3d5bb83c 1258 main/source/Sources.gz d8476d69da595bd80bfaef1aca6d58129be6ab51257f8d1873a5b85ff1398f49 72 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAABCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmevKMEACgkQdKlBuiGe yBBPUwf7BpPi7d6Pzs9LsPKTizSmkoBx3Lm/KBQDuDSpFhfJYk5yuViP4W3DKn0D T/MltNF5GFXdvH4Q65kQoTa+4CGc83iKbcej7jDo5q+cMXfOqg1hYi6opIEj9shG 5mRqHWKkLJ96wnc8Mh+YAvK3vIAX40iwOMOlMfZQADBGK7H6gTx4/R4/pn4CgHdS StzttG8ektIx5lojv0FUUE94NQyF0uKtTqB0RUooTzlV/qLEczv8W9ra6kk2AJuD 6xYp5LOKccdEMO4u27MykwD4MaPricDoErQe7ssD+RSp2fSa9nSnxIjiik4dr9lr VdqlFDMGH3w/JSHSz1UrespC1RjtMw== =TUnR -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: unstable Codename: sid Date: Fri, 14 Feb 2025 11:28:01 UTC Valid-Until: Wed, 26 Mar 2025 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: 2dcd5ffd7f2f64b7c38fa925d7e96a1e 6260 main/binary-amd64/Packages cc6cfcd9826a8c8e8eb51d65c669b130 2915 main/binary-amd64/Packages.gz 20449ced16157eb8f05d42a478c33e3b 73 main/binary-amd64/Release bc775e621485c01622f2397eeb67b8e4 5018 main/binary-arm64/Packages 3182269d9dc1cb2ef4e18e56e7ac59fd 2416 main/binary-arm64/Packages.gz 5ddfcea95c0f3ba08f348fafdc2ebaa9 73 main/binary-arm64/Release 299be9fd66e74f0fd79f5f4623ec4411 6254 main/binary-i386/Packages 43804ab9928c2362033ac99f15719714 2913 main/binary-i386/Packages.gz 6b9b53f0e38c1f9360e2b36e9219bf83 72 main/binary-i386/Release bf88ece9d707203d82a2b14d8c93bdfe 2848 main/source/Sources 19685747ecc5d2c86c548ebc0de6590f 1239 main/source/Sources.gz 3e925b43fce2d4b8af85c7e785c6e401 74 main/source/Release SHA1: b693045f159751607329ef6cf5a47091e6c9eb78 6260 main/binary-amd64/Packages daf58cc1700106f872cfc05ab311976204da2f76 2915 main/binary-amd64/Packages.gz c35fad9ab6e3c4100c30ca38fb6a2abba5b59871 73 main/binary-amd64/Release 58de7862604db3a87830814def98bb88da9eae28 5018 main/binary-arm64/Packages 4c18f89c5561660162f515a0dff512cfef7e0df3 2416 main/binary-arm64/Packages.gz 93f23ad9365f6eab9c51ff37056c6c10e993cb41 73 main/binary-arm64/Release d34782b6e3aa5cd52b974a1f3975ad2992e27050 6254 main/binary-i386/Packages a2712d6d50a38d45144bfb4583057f76aaee346e 2913 main/binary-i386/Packages.gz 357698f11a8138a7da6a483cca6d3b891f5cf52e 72 main/binary-i386/Release ec0d9e1baa8368ea60e458f0d30370a78ceabeb2 2848 main/source/Sources f43cb2d855e570991461daec3dffbdd402660597 1239 main/source/Sources.gz 8a76c8851861683bec52c7179f0af99288640f8d 74 main/source/Release SHA256: 63480240eb3597f4954914f83aeb4c306cec74e6d47921e03aefeed52845d7e5 6260 main/binary-amd64/Packages 7b6bab95507a72a44353f79c04057a586b17348bc6845190b1e9946ad4f2a34d 2915 main/binary-amd64/Packages.gz 6176a6b8747088b9d83774f369efed8fc4b1f22bafe037c47f500b505aa5fd70 73 main/binary-amd64/Release 3df4bea29a43aa15075d59d25a8a892702a45bd6e2dcc379f97ed3409b85155c 5018 main/binary-arm64/Packages 36309b5c3d598a2ac72aff088825d01c194d339041465287ec1eff477e8b274c 2416 main/binary-arm64/Packages.gz e0abbf1c817cb66436db607a507c8b579fb059e3e54369ca979d8cbc0177e307 73 main/binary-arm64/Release 2887da6b3403ce4de428a1ec59aab76c5b15d6074ee7b4b15e40d9dd796b6afe 6254 main/binary-i386/Packages 1868b7f7c167f38eac694ad2fe62af9e0828f5176d4e50cf4ee0c78ffb8d3505 2913 main/binary-i386/Packages.gz 241bd9dee8cb13dd5bbc4b41d496d5e096dfd292db7bb0443df532ea2582cf26 72 main/binary-i386/Release 66b48d52df535c3b3c5841472524aaf3c3589a06195670f2ad309ba80dd1ba94 2848 main/source/Sources b3871901256f870704056586c696edbd27af9535b580836b6f3d3130f124a69f 1239 main/source/Sources.gz eafd75f908427c7b1b03f83a7fcd4884d4aced30433b64211c71a062d40b324f 74 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAABCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmevKMEACgkQdKlBuiGe yBDoqAf+N/nWI6wvXlqihgoMKGeUhkI+YKhu+1X89r8bLxLazgmQ1sAnj/cjPWCz x3XBOEOgfiwo7qUgsW9xYv8pg2JBbFugF/zOmI3kZ7MUCEmZC22ebapr0iRdJpBc xvXInkkBCYxFtFuGR5eDC+6v2idpj8i+S9UPkBh4osK641iEHzdv4w0dJynWVJNd pLM7TgmdEYzOwoCsSNoPySlOYGbNZQt/90b3bkh0YSeBzTBo5NDexNkl3xgcWkaW zD8TJGKfNwI7ExNiR9+Cfw/12QnE2jhuadKzDKHS5WI+qJArfFZR+m1H/seJnZnG b5XduXB/PK6BAcdfR9AFIgRwnvGoWg== =6F6z -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: unstable Codename: sid Date: Fri, 14 Feb 2025 11:28:01 UTC Valid-Until: Wed, 26 Mar 2025 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: 2dcd5ffd7f2f64b7c38fa925d7e96a1e 6260 main/binary-amd64/Packages cc6cfcd9826a8c8e8eb51d65c669b130 2915 main/binary-amd64/Packages.gz 20449ced16157eb8f05d42a478c33e3b 73 main/binary-amd64/Release bc775e621485c01622f2397eeb67b8e4 5018 main/binary-arm64/Packages 3182269d9dc1cb2ef4e18e56e7ac59fd 2416 main/binary-arm64/Packages.gz 5ddfcea95c0f3ba08f348fafdc2ebaa9 73 main/binary-arm64/Release 299be9fd66e74f0fd79f5f4623ec4411 6254 main/binary-i386/Packages 43804ab9928c2362033ac99f15719714 2913 main/binary-i386/Packages.gz 6b9b53f0e38c1f9360e2b36e9219bf83 72 main/binary-i386/Release bf88ece9d707203d82a2b14d8c93bdfe 2848 main/source/Sources 19685747ecc5d2c86c548ebc0de6590f 1239 main/source/Sources.gz 3e925b43fce2d4b8af85c7e785c6e401 74 main/source/Release SHA1: b693045f159751607329ef6cf5a47091e6c9eb78 6260 main/binary-amd64/Packages daf58cc1700106f872cfc05ab311976204da2f76 2915 main/binary-amd64/Packages.gz c35fad9ab6e3c4100c30ca38fb6a2abba5b59871 73 main/binary-amd64/Release 58de7862604db3a87830814def98bb88da9eae28 5018 main/binary-arm64/Packages 4c18f89c5561660162f515a0dff512cfef7e0df3 2416 main/binary-arm64/Packages.gz 93f23ad9365f6eab9c51ff37056c6c10e993cb41 73 main/binary-arm64/Release d34782b6e3aa5cd52b974a1f3975ad2992e27050 6254 main/binary-i386/Packages a2712d6d50a38d45144bfb4583057f76aaee346e 2913 main/binary-i386/Packages.gz 357698f11a8138a7da6a483cca6d3b891f5cf52e 72 main/binary-i386/Release ec0d9e1baa8368ea60e458f0d30370a78ceabeb2 2848 main/source/Sources f43cb2d855e570991461daec3dffbdd402660597 1239 main/source/Sources.gz 8a76c8851861683bec52c7179f0af99288640f8d 74 main/source/Release SHA256: 63480240eb3597f4954914f83aeb4c306cec74e6d47921e03aefeed52845d7e5 6260 main/binary-amd64/Packages 7b6bab95507a72a44353f79c04057a586b17348bc6845190b1e9946ad4f2a34d 2915 main/binary-amd64/Packages.gz 6176a6b8747088b9d83774f369efed8fc4b1f22bafe037c47f500b505aa5fd70 73 main/binary-amd64/Release 3df4bea29a43aa15075d59d25a8a892702a45bd6e2dcc379f97ed3409b85155c 5018 main/binary-arm64/Packages 36309b5c3d598a2ac72aff088825d01c194d339041465287ec1eff477e8b274c 2416 main/binary-arm64/Packages.gz e0abbf1c817cb66436db607a507c8b579fb059e3e54369ca979d8cbc0177e307 73 main/binary-arm64/Release 2887da6b3403ce4de428a1ec59aab76c5b15d6074ee7b4b15e40d9dd796b6afe 6254 main/binary-i386/Packages 1868b7f7c167f38eac694ad2fe62af9e0828f5176d4e50cf4ee0c78ffb8d3505 2913 main/binary-i386/Packages.gz 241bd9dee8cb13dd5bbc4b41d496d5e096dfd292db7bb0443df532ea2582cf26 72 main/binary-i386/Release 66b48d52df535c3b3c5841472524aaf3c3589a06195670f2ad309ba80dd1ba94 2848 main/source/Sources b3871901256f870704056586c696edbd27af9535b580836b6f3d3130f124a69f 1239 main/source/Sources.gz eafd75f908427c7b1b03f83a7fcd4884d4aced30433b64211c71a062d40b324f 74 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAEBCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmevKMEACgkQdKlBuiGe yBApxwf9EAE4fnC6Iyhn0n15WQikVPojEcn2MPjS8r4OtBVHRHMal5js6ZDN15JE GmQZP7vHqC12Yxifmp2mOkoVlwVvGeHPwb0m/h2FSHy5P6CADq/9CPwjVYbVORkQ oWo4AOJu/jNnRe9wYQFCRO1mxzcms17Rv8d0UBN6bSLvwJH+Qpvr32v4JzaOomZN HfII2Te8vZzdptZdssBYupKO0hVCJIRYykrQBy3FbIQN6dzP7GD/oygoBsa1t7Cj JCGaSpnOBrFV5UwPuX+6k5J17cuF9c/d0E5rLzGnLiaYxl9Jk9deu/muvGKME/jk xmfGz8KEqUZylajBN7f6JfhPFpL1ZA== =sS4f -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: testing Codename: trixie Date: Fri, 14 Feb 2025 11:28:01 UTC Valid-Until: Wed, 26 Mar 2025 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: 4f1c7cdf829350ecd5f19446f105c224 5155 main/binary-amd64/Packages 5efe887860f463dee1257876419c5ead 2452 main/binary-amd64/Packages.gz 8993e226d487ae15a57b295ee7163410 72 main/binary-amd64/Release 301e1861261a0cac8704012e48bf9ae0 5122 main/binary-arm64/Packages 5a8be3a82df40c1d67a83b6f74031b24 2432 main/binary-arm64/Packages.gz 04848f1e95e99ecd5266016b54f6ba3b 72 main/binary-arm64/Release ebea07f2c2dee778846066370e6e8c89 5151 main/binary-i386/Packages 69db395f0f704f7c2002ccf3dd675874 2448 main/binary-i386/Packages.gz c87b59e471c0b39de0cfca2638377f8f 71 main/binary-i386/Release b3c0d559a60239b9ab703ba905aae6f5 2939 main/source/Sources fb531fdc96ffc0afcc24ba04dd27fca4 1258 main/source/Sources.gz 704ca88fd2254271bed6e9700954c775 73 main/source/Release SHA1: 88549bebf05677460cd5f3737bba3308ddc00230 5155 main/binary-amd64/Packages c93610bbfa153e7128ab46d46115a9d7d306a0e0 2452 main/binary-amd64/Packages.gz 4790dd0652995711f37417277d9f240f43264004 72 main/binary-amd64/Release 9648703f6299f925ccdb2e6db73c0dcaabe5a2a2 5122 main/binary-arm64/Packages c5b3aadfaac20a671fac0f6f3020926afe1466a7 2432 main/binary-arm64/Packages.gz 559a5d2deafc73df93436224cae9eb13ce1476b7 72 main/binary-arm64/Release acaaf2190ee353082b472faf65a25b1b90ae594c 5151 main/binary-i386/Packages 2a749e0d470886f56299662ae4830fc10d69eda2 2448 main/binary-i386/Packages.gz 2c099ef796776b4f026e324a181929a95cb6fd6f 71 main/binary-i386/Release 669806decc4fbb53899c8ad78ac46f290543b5fd 2939 main/source/Sources dd38d54b49f079e5aa2100ef52a480f9a030be98 1258 main/source/Sources.gz 2ec604f75d95854298c93160692fa5d810497e8d 73 main/source/Release SHA256: affbb204a6e0e18f8b4730bb2fd43f2fefd5c7c1c80e04db702909b38e68764d 5155 main/binary-amd64/Packages 823125c3308508e8280f3864acfa32ebde37dcde2b66625900871649d965f043 2452 main/binary-amd64/Packages.gz 1cd4765e05f5d3491b247aab90ae65b779d3b0a5fa93d1076afd87f41a6aef92 72 main/binary-amd64/Release b9a81ec0de4b34c36727ac6403de0c69d078d06de3317ec287a7225e83c203d9 5122 main/binary-arm64/Packages bb03be229acab70c79d3ff1a874c5c4eca6f2e76f7dfece63190aad3ec1504a2 2432 main/binary-arm64/Packages.gz 291d5c3dd3e5a5de74cf8ca0261f9881ca8e0d3ea07bbee096d137eacf861bda 72 main/binary-arm64/Release 41e7710fcee9b0cee79bed7875e79747c383608d772a3bed5b14edb139baba85 5151 main/binary-i386/Packages b9ae9259fda7197e0d97d7eefe6e34482a80502a7f4d0cb9e5963c03b51a3670 2448 main/binary-i386/Packages.gz 03864d020cf80a7bd64d2f3a9122ad40482d2dfd776264534e172d518fe3136d 71 main/binary-i386/Release 8975f6acf34d666bca543d417913adb832b8b900fcc7aabe1c7671d65e5a6024 2939 main/source/Sources e5e0e6695226a4945e873fab8eb694e9ab8af8d94c6dc6373d40968116fda3f8 1258 main/source/Sources.gz fe0a611678e47cab4d8cc639eb7249cdfb506151360eab974388532b469753bd 73 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAABCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmevKMEACgkQdKlBuiGe yBCu9gf/diaKUJFDU9Ed/av5Y3ClsGFUtRuHFMeTY4mfqVRSWj7eDhCjJqrfIxpJ TsVMMYghdrGG2Dl2M3npbT/HC7/1am+Zs914z4vsmnJKYhyIeb0I9WK89zNIg05q r7rT4MFuHC78HX8+Wvh8Oq8WWFj/eL/YZmVskDO3HISThE21N3DkDzRuu1Fxg4/m 4clPWI4bXo+JD+A/FWvLISzEdlpWlNKq+SuarCKa76EV0Az+RiiLmj0/mEY1p/gI 6VAinjieOVaw/Th5feF+JAhJ7wzKdoscVdv8MZ1yJijRAjBjDu4P2mYw0NCQipXO GVTwJIeTkG0B0NTYBrIpMgC9MyQQhQ== =7brN -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: TorProject Suite: stable Codename: bookworm Date: Fri, 14 Feb 2025 11:28:01 UTC Valid-Until: Wed, 26 Mar 2025 11:28:01 UTC Architectures: amd64 arm64 i386 Components: main MD5Sum: ef9461c1420699ca148523e82f1658ae 5165 main/binary-amd64/Packages 8472a30220841fd71471e513eea7feb5 2446 main/binary-amd64/Packages.gz 5a232710573bca3aae4b577c16ece1c1 71 main/binary-amd64/Release f4bc0d019adf816ed328ef8fc6d14da8 5132 main/binary-arm64/Packages 6810832523f5872f3a0e9a6d3271932f 2427 main/binary-arm64/Packages.gz 132565cf1e259a93a021e651e2ab3cd4 71 main/binary-arm64/Release 66294d5c2544ddcc9de4a63307844213 5161 main/binary-i386/Packages 7954605c44cec2c6732b09f4bf5146f5 2445 main/binary-i386/Packages.gz 5768b889feb010e5d4a62ad2003a6da2 70 main/binary-i386/Release 82b6a307db03b9cbfb6a267a57e64fb2 2953 main/source/Sources b7c2043f6c99a9e94d28401946d2d5aa 1258 main/source/Sources.gz 94aa68972888c3c4340efb5dd97b195e 72 main/source/Release SHA1: cfa9e4e3aeb947faabb55eeee303ef6b3a8a7d9e 5165 main/binary-amd64/Packages 7af71b12e4d55a900d027a97a13fd925d17fbc08 2446 main/binary-amd64/Packages.gz 0f979d666f966c427fab567771f55d6f9b963b79 71 main/binary-amd64/Release ec30ea663b574cf2ad6a7051b80733130a95967c 5132 main/binary-arm64/Packages 22d34250fe983afe37b3e09a39e4ed0cf503ffcd 2427 main/binary-arm64/Packages.gz 88b92baad3148570453a1ca4df4ac8f6c8b33c94 71 main/binary-arm64/Release 54f6e88fdab6f14055791f59f72f5707ae31ae2c 5161 main/binary-i386/Packages c9f0e20778899974b6267219246efc5113bef700 2445 main/binary-i386/Packages.gz c2f88e8b760b1fbd8e4fab14f02d7dd022309208 70 main/binary-i386/Release 48576f3f83997e38c1310c0a25affab6c9fabaa0 2953 main/source/Sources 859ac4cb8868b4b55253fd1ac8ceef2c010bc0e0 1258 main/source/Sources.gz e495ccf6037e86ba98915df00c0fce0839703634 72 main/source/Release SHA256: beab22bc6765408c14e65a66648d01b7c080f0f624c84a8c96fb0ec2e8ee32ee 5165 main/binary-amd64/Packages 90300ff39af1c8af397ccfd1a8fecffe26717b338f56b7b275c9207aad07ef10 2446 main/binary-amd64/Packages.gz 679b22e05826dc8eea366e3d9cc42471a9dbd03f95656d3a9541dfafcd82dc00 71 main/binary-amd64/Release 050f154f3d910bc349a9ff06b8d9c2f6ecfe89005fab4d576f817f6b841407b8 5132 main/binary-arm64/Packages b3c372797cdf5aa2310f1d0459d6fd8f2bf17abfc76bb5cb70891995ee745b8d 2427 main/binary-arm64/Packages.gz ffd961c4598ade54f231c2679cd0b7e8c346b66aa94cac0752d10deea94ee1d9 71 main/binary-arm64/Release 68e493ff92bdc6542ff3f86b8e18126c85131a3936313bc4ec868261e77778ed 5161 main/binary-i386/Packages 6691349d45f13e637acf77b52e4c6358e214336860ca012c4a1e6382cdf467e9 2445 main/binary-i386/Packages.gz e9a73c169e4a69b67bfec28ff6fda7a5c2236310cd9efe1d60eae4fb5305c7fa 70 main/binary-i386/Release 9a17f06b2326c7c48accc85a76e063ed0986ebff994869d95c746a7159ae3f2a 2953 main/source/Sources 03850f5c767373134f44c5c38ce4e3978ad8128faa118f024ccb264e3d5bb83c 1258 main/source/Sources.gz d8476d69da595bd80bfaef1aca6d58129be6ab51257f8d1873a5b85ff1398f49 72 main/source/Release -----BEGIN PGP SIGNATURE----- wsBzBAEBCAAdFiEEImXrTLK/iNkAro0bdKlBuiGeyBAFAmevKMEACgkQdKlBuiGe yBAoDQf/Uii8ah8gAAoVqxe5RvUCUdI7rULIPcxfIt9G6ddJDXzvCkgMbq9VqxoL v+x6qdKjD9tAy+uoeWQygin/aUSD0uPC2d1XXdVvin9A/mTkUxa9C6f84ecxtaQP TnSNFaQuE6hUlmekB4AFKhBev0N25cezgJC86Cwxsjqub5h1R4anALvHYLqr8p1P k1LMCwN6nQVIy8dMz6RbN9o69qDIs7yUPhVG5RFN4us8g5A3YDOMFbLJUY2WAiCm t96GZIs+oOO03g7xqtJc9G67fULuo4TycW70P9yFk5A/+a0m0/ovWuvvjode9iDM hhRmafsYupear5ln4kdTQgJhH7k9zw== =VXJQ -----END PGP SIGNATURE----- ", ]; #[test] fn test_datetime_tie() { let mut latest = None; for bytes in RELEASE_DATA { let key = CryptoHash::calculate(bytes); update_latest( &mut latest, key.0.into_bytes(), bytes.to_vec(), DateTime::::MAX_UTC, ) .unwrap(); } assert_eq!( latest, Some(( Utc.with_ymd_and_hms(2025, 2, 14, 11, 28, 1).unwrap(), "sha256:c4dde6759a31026a6a2b8d3a72dbd8290d0b831568d409ccf51660cdb52bf055".into(), RELEASE_DATA[3].to_vec(), Signed::from_bytes(RELEASE_DATA[3]).unwrap().0.content, 2986, )) ); } #[test] fn test_latest_datetime_capped() { let mut latest = None; for bytes in RELEASE_DATA { let key = CryptoHash::calculate(bytes); update_latest( &mut latest, key.0.into_bytes(), bytes.to_vec(), Utc.with_ymd_and_hms(2025, 1, 1, 1, 1, 1).unwrap(), ) .unwrap(); } assert_eq!( latest, Some(( Utc.with_ymd_and_hms(2024, 11, 15, 11, 28, 1).unwrap(), "sha256:0204f8c76d22ae29164c18e5cdb615e9985b562f7d8d0c9a9e963e2076ab15e1".into(), RELEASE_DATA[0].to_vec(), Signed::from_bytes(RELEASE_DATA[0]).unwrap().0.content, 2988, )) ); } } apt-swarm-0.5.1/src/lib.rs000064400000000000000000000003731046102023000134500ustar 00000000000000pub mod args; pub mod config; pub mod db; pub mod errors; pub mod fetch; pub mod keyring; pub mod latest; pub mod net; pub mod p2p; pub mod pgp; pub mod plumbing; pub mod signed; pub mod sync; pub mod timers; #[cfg(fuzzing)] pub use sequoia_openpgp; apt-swarm-0.5.1/src/main.rs000064400000000000000000000234461046102023000136340ustar 00000000000000use apt_swarm::args::{Args, FileOrStdin, SubCommand}; use apt_swarm::config; use apt_swarm::db::{AccessMode, Database, DatabaseClient}; use apt_swarm::errors::*; use apt_swarm::fetch; use apt_swarm::keyring::Keyring; use apt_swarm::latest; use apt_swarm::net; use apt_swarm::p2p; use apt_swarm::plumbing; use apt_swarm::signed::Signed; use apt_swarm::sync; use chrono::{DateTime, Utc}; use clap::Parser; use colored::Colorize; use env_logger::Env; use futures::StreamExt; use num_format::{Locale, ToFormattedString}; use sequoia_openpgp::KeyHandle; use std::borrow::Cow; use std::sync::Arc; use tokio::io::{self, AsyncBufReadExt, AsyncWriteExt}; #[tokio::main] async fn main() -> Result<()> { #[cfg(target_os = "openbsd")] pledge::pledge("stdio dns inet rpath wpath cpath flock unix", "") .context("Failed to setup pledge sandbox")?; let args = Args::parse(); let log_level = match (args.quiet, args.verbose) { (0, 0) => "warn,apt_swarm=info", (1, 0) => "warn", (_, 0) => "error", (_, 1) => "info,apt_swarm=debug", (_, 2) => "debug", (_, 3) => "debug,apt_swarm=trace", _ => "trace", }; env_logger::init_from_env(Env::default().default_filter_or(log_level)); rustls::crypto::ring::default_provider() .install_default() .map_err(|_| anyhow!("Failed to install rustls ring CryptoProvider"))?; let config = config::Config::load_with_args(&args).await; if args.colors { colored::control::set_override(true); } match args.subcommand { SubCommand::Import(mut import) => { let config = config?; let keyring = Some(Keyring::load(&config)?); let mut db = Database::open(&config, AccessMode::Exclusive).await?; FileOrStdin::default_stdin(&mut import.paths); for path in import.paths { let reader = path.open().await?; let mut reader = io::BufReader::new(reader); while !reader.fill_buf().await?.is_empty() { let signed = Signed::from_reader(&mut reader) .await .context("Failed to parse release file")?; for (fp, variant) in signed.canonicalize(keyring.as_ref())? { let fp = fp.context( "Signature can't be imported because the signature is unverified", )?; db.add_release(&fp, &variant).await?; } } } } SubCommand::Export(export) => { let config = config?; let db = Database::open_directly(&config, AccessMode::Relaxed).await?; let mut stdout = io::stdout(); if export.release_hashes.is_empty() { let stream = db.scan_values(&[]); tokio::pin!(stream); while let Some(item) = stream.next().await { let (_hash, data) = item.context("Failed to read from database")?; stdout.write_all(&data).await?; } } else { for hash in &export.release_hashes { if export.scan { let stream = db.scan_values(hash.as_bytes()); tokio::pin!(stream); while let Some(item) = stream.next().await { let (_hash, data) = item.context("Failed to read from database")?; stdout.write_all(&data).await?; } } else { let data = db .get(hash) .await .context("Failed to read database")? .with_context(|| anyhow!("Failed to find key in database: {hash:?}"))?; stdout.write_all(&data).await?; } } } // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } SubCommand::Fetch(fetch) => { let config = config?; let keyring = Keyring::load(&config)?; let mut db = Database::open_directly(&config, AccessMode::Exclusive).await?; let keyring = Arc::new(Some(keyring)); fetch::fetch_updates( &mut db, keyring, fetch.concurrency, config.data.repositories, args.proxy, ) .await?; } SubCommand::Latest(latest) => { let config = config?; let db = Database::open_directly(&config, AccessMode::Relaxed).await?; let max_allowed_datetime = if latest.allow_future_dates { DateTime::::MAX_UTC } else { Utc::now() }; if let Some((date, mut key, signed, content, idx)) = latest::find(&db, latest.fingerprint, max_allowed_datetime).await? { let mut stdout = io::stdout(); let value: Cow<'_, [u8]> = if latest.key { key.push(b'\n'); Cow::Owned(key) } else if latest.date { let mut date = date.to_rfc3339(); date.push('\n'); Cow::Owned(date.into_bytes()) } else if latest.body { Cow::Borrowed(&content) } else if latest.header { Cow::Borrowed(&content[..idx]) } else if latest.attachment { Cow::Borrowed(&content[idx..]) } else { Cow::Borrowed(&signed) }; stdout.write_all(&value).await?; // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } } SubCommand::Ls(ls) => { let config = config?; // TODO: this should call open(), but needs to be rewritten because // .scan_keys is not available over unix domain socket let db = Database::open_directly(&config, AccessMode::Relaxed).await?; let prefix = if let Some(prefix) = &ls.prefix { prefix.as_bytes() } else { &[] }; let mut stdout = io::stdout(); let mut count = 0; let stream = db.scan_keys(prefix); tokio::pin!(stream); while let Some(item) = stream.next().await { if ls.count { count += 1; continue; } let hash = item.context("Failed to read from database (ls)")?; stdout.write_all(&hash).await?; stdout.write_all(b"\n").await?; } // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; if ls.count { println!("{count}"); } } SubCommand::Keyring(args) => { let config = config?; let keyring = Keyring::load(&config)?; let mut db = Database::open(&config, AccessMode::Relaxed).await?; if args.json { let keyring = keyring.generate_report()?; let keyring = serde_json::to_string_pretty(&keyring) .context("Failed to encode keyring as json")?; println!("{keyring}"); } else { for key in keyring.keys.values() { let hex = key.hex_fingerprint(); for uid in &key.uids { println!("{} {}", hex.green(), uid.yellow()); } for (handle, _fp) in &key.key_handles { if let KeyHandle::Fingerprint(fp) = handle { let subkey = format!("Subkey {fp:X}"); let stats = if args.stats { let prefix = format!("{fp:X}/"); let count = db.count(prefix.as_bytes()).await?; if count > 0 { let count = count.to_formatted_string(&Locale::en); Some(format!(" ({count} known signatures)")) } else { None } } else { None }; let stats = stats.as_deref().unwrap_or(""); println!("{} {}{}", hex.green(), subkey.purple(), stats.cyan()); } } } } } SubCommand::Pull(pull) => { let config = config?; let keyring = Keyring::load(&config)?; let mut db = Database::open(&config, AccessMode::Exclusive).await?; let mut sock = net::connect(&pull.addr, args.proxy).await?; let (rx, mut tx) = sock.split(); let result = sync::sync_pull(&mut db, &keyring, &pull.keys, pull.dry_run, &mut tx, rx).await; tx.shutdown().await.ok(); result?; } SubCommand::P2p(p2p) => { let config = config?; let keyring = Keyring::load(&config)?; // Explicitly open database, do not test for unix domain socket let db = Database::open_directly(&config, AccessMode::Exclusive).await?; p2p::spawn(db, keyring, config, p2p, args.proxy).await?; } SubCommand::Plumbing(plumbing) => { plumbing::run(config, plumbing, args.quiet, args.proxy).await? } } Ok(()) } apt-swarm-0.5.1/src/net.rs000064400000000000000000000044361046102023000134740ustar 00000000000000use crate::errors::*; use crate::p2p::proto::PeerAddr; use std::net::SocketAddr; use std::time::Duration; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use tokio::net::TcpStream; use tokio::time; use tokio_socks::tcp::Socks5Stream; pub const CONNECT_TIMEOUT: Duration = Duration::from_secs(15); pub const HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(20); pub const PROXY_TIMEOUT: Duration = Duration::from_secs(30); pub async fn connect(addr: &PeerAddr, proxy: Option) -> Result { let PeerAddr::Inet(addr) = addr else { bail!("Connecting to onions is not yet implemented") }; // TODO: only do this for PeerAddr::Inet let target = proxy.unwrap_or(*addr); info!("Creating tcp connection to {target:?}"); let sock = TcpStream::connect(target); let mut sock = time::timeout(CONNECT_TIMEOUT, sock) .await .with_context(|| anyhow!("Connecting to {target:?} timed out"))? .with_context(|| anyhow!("Failed to connect to {target:?}"))?; if let Some(proxy) = proxy { debug!("Requesting socks5 connection to {addr:?}"); let connect = Socks5Stream::connect_with_socket(sock, addr); sock = time::timeout(PROXY_TIMEOUT, connect) .await .with_context(|| anyhow!("Connecting to {addr:?} (with socks5 {proxy:?}) timed out"))? .with_context(|| anyhow!("Failed to connect to {addr:?} (with socks5 {proxy:?})"))? .into_inner() } debug!("Connection has been established"); Ok(sock) } pub async fn handshake( mut rx: R, mut tx: W, ) -> Result<()> { debug!("Sending protocol probe to remote peer"); time::timeout(HANDSHAKE_TIMEOUT, tx.write_all(b"//\n")) .await .context("Sending handshake protocol probe timed out")? .context("Failed to send protocol probe")?; let mut buf = [0u8; 3]; time::timeout(HANDSHAKE_TIMEOUT, rx.read_exact(&mut buf)) .await .context("Sending handshake protocol probe timed out")? .context("Failed to receive handshake response")?; if buf == *b":0\n" { debug!("Remote peer has sent expected response"); Ok(()) } else { bail!("Invalid handshake response: {buf:?}") } } apt-swarm-0.5.1/src/p2p/db.rs000064400000000000000000000060461046102023000137730ustar 00000000000000use crate::db::proto::{ErrorResponse, Query, Response}; use crate::db::{DatabaseClient, DatabaseServerClient}; use crate::errors::*; use crate::sync; use std::convert::Infallible; use std::path::PathBuf; use tokio::fs; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::net::{UnixListener, UnixStream}; pub async fn serve_request(db: &mut DatabaseServerClient, buf: &[u8]) -> Result { let query = serde_json::from_slice(buf).context("Failed to deserialize query")?; match query { Query::AddRelease(fp, signed) => { let fp = fp.parse().context("Failed to parse fingerprint")?; let hash = db.add_release(&fp, &signed).await?; Ok(Response::Inserted(hash)) } Query::IndexFromScan(query) => { let fp = query.fp.parse().context("Failed to parse fingerprint")?; let index = db .index_from_scan(&sync::TreeQuery { fp, hash_algo: query.hash_algo, prefix: query.prefix, }) .await?; Ok(Response::Index(index)) } Query::Count(key) => { let count = db.count(&key).await?; Ok(Response::Num(count)) } } } pub async fn serve_db_client(db: &mut DatabaseServerClient, mut stream: UnixStream) -> Result<()> { let (rx, mut tx) = stream.split(); let mut reader = BufReader::new(rx); let mut buf = Vec::new(); loop { buf.clear(); reader .read_until(b'\n', &mut buf) .await .context("Failed to read from database client")?; if !buf.ends_with(b"\n") { // client has disconnected return Ok(()); } match serve_request(db, &buf).await { Ok(Response::Ok) => tx.write_all(b"\n").await?, Ok(response) => { let mut err = serde_json::to_string(&response)?; err.push('\n'); tx.write_all(err.as_bytes()).await?; } Err(err) => { let err = ErrorResponse::new(&err); let mut err = serde_json::to_string(&err)?; err.push('\n'); tx.write_all(err.as_bytes()).await?; } } } } pub async fn spawn_unix_db_server(db: &DatabaseServerClient, path: PathBuf) -> Result { fs::remove_file(&path).await.ok(); let listener = UnixListener::bind(&path) .with_context(|| anyhow!("Failed to bind database socket at: {path:?}"))?; debug!("Bound database socket at {path:?}"); loop { let (stream, _src_addr) = listener.accept().await?; debug!("Accepted database client on unix domain socket"); let mut db = db.clone(); tokio::spawn(async move { if let Err(err) = serve_db_client(&mut db, stream).await { error!("Error while serving database client: {err:#}"); } else { debug!("Database client disconnected"); } }); } } apt-swarm-0.5.1/src/p2p/dns.rs000064400000000000000000000035041046102023000141660ustar 00000000000000use crate::errors::*; use crate::p2p; use crate::p2p::proto::{PeerAddr, SyncRequest}; use std::convert::Infallible; use std::net::SocketAddr; use std::time::Duration; use tokio::sync::mpsc; use tokio::sync::mpsc::error::TrySendError; use tokio::time; pub const DNS_SEEDS: &[&str] = &["dnsseed.apt-swarm.orca.toys"]; const DNS_DEBOUNCE: Duration = Duration::from_millis(100); const DNS_QUERY_COOLDOWN: Duration = Duration::from_secs(60 * 60); // 1h const DNS_QUERY_JITTER: Duration = Duration::from_secs(60 * 3); // 3min pub async fn resolve(dns: &str) -> Result> { info!("Resolving dns name: {dns:?}"); let host = format!("{dns}:16169"); let stream = tokio::net::lookup_host(host.clone()) .await .with_context(|| anyhow!("Failed to resolve: {host:?}"))?; Ok(stream) } pub async fn spawn(dns: Vec, peering_tx: mpsc::Sender) -> Result { // briefly delay this in case we error out for some reason tokio::time::sleep(DNS_DEBOUNCE).await; loop { for name in &dns { match resolve(name).await { Ok(addrs) => { let addrs = addrs.map(PeerAddr::Inet).collect(); for addr in &addrs { debug!("Resolved dns name to address: {addr:?}"); } let addr = SyncRequest { hint: None, addrs }; if let Err(TrySendError::Full(addr)) = peering_tx.try_send(addr) { warn!("Discarding addr because peering backlog is full: {addr:?}"); } } Err(err) => error!("Failed to query dns name {name:?}: {err:#}"), } } time::sleep(DNS_QUERY_COOLDOWN).await; p2p::random_jitter(DNS_QUERY_JITTER).await; } } apt-swarm-0.5.1/src/p2p/fetch.rs000064400000000000000000000067151046102023000145020ustar 00000000000000use crate::config::Repository; use crate::db::DatabaseClient; use crate::errors::*; use crate::fetch; use crate::keyring::Keyring; use crate::p2p; use crate::sync; use std::collections::HashMap; use std::convert::Infallible; use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; use tokio::sync::mpsc; use tokio::time; pub struct GossipStats { last_announced_index: String, last_announced_at: time::Instant, next_idle_announce_after: Duration, } impl GossipStats { pub fn new(idx: String) -> Self { GossipStats { last_announced_index: idx, last_announced_at: time::Instant::now(), next_idle_announce_after: p2p::GOSSIP_IDLE_ANNOUNCE_INTERVAL, } } pub fn needs_announcement(&self, idx: &str) -> bool { if self.last_announced_index != idx { true } else { let elapsed = time::Instant::now().duration_since(self.last_announced_at); elapsed >= self.next_idle_announce_after } } pub fn update_announced_index(&mut self, idx: String) { self.last_announced_index = idx; self.last_announced_at = time::Instant::now(); } } pub async fn spawn_fetch_timer( db: &mut D, keyring: Keyring, repositories: Vec, proxy: Option, announce_addrs: Vec, p2p_tx: Option>, ) -> Result { let mut stats = HashMap::new(); for key in keyring.all_fingerprints() { stats.insert(key, GossipStats::new("TODO".to_string())); } let keyring = Arc::new(Some(keyring)); let mut interval = time::interval(p2p::FETCH_INTERVAL - p2p::FETCH_INTERVAL_JITTER); loop { interval.tick().await; p2p::random_jitter(p2p::FETCH_INTERVAL_JITTER).await; info!("Fetch timer has started"); if let Err(err) = fetch::fetch_updates(db, keyring.clone(), None, repositories.clone(), proxy).await { error!("Fetch timer has crashed: {err:#}"); } else { debug!("Fetch timer has completed"); } for (fp, gossip) in &mut stats { let query = sync::TreeQuery { fp: fp.clone(), hash_algo: "sha256".to_string(), prefix: None, }; match db.index_from_scan(&query).await { Ok((idx, count)) => { debug!("Recalculated index for gossip checks: fp={fp:X} idx={idx:?} count={count:?}"); if count > 0 && gossip.needs_announcement(&idx) { let mut msg = format!("[sync] fp={fp:X} idx={idx} count={count}"); for addr in &announce_addrs { msg += &format!(" addr={addr}"); } if let Some(p2p_tx) = &p2p_tx { trace!("Sending to p2p channel: {:?}", msg); // if the p2p channel crashed do not interrupt monitoring if let Err(err) = p2p_tx.try_send(msg) { warn!("Failed to send to p2p channel: {err:#}"); } } gossip.update_announced_index(idx); } } Err(err) => { error!("Failed to access database: {err:#}"); } } } } } apt-swarm-0.5.1/src/p2p/irc.rs000064400000000000000000000144601046102023000141620ustar 00000000000000use crate::errors::*; use crate::p2p; use crate::p2p::proto::{PeerGossip, SyncRequest}; use futures::prelude::*; use irc::client::prelude::{Client, Command, Config, Response}; use std::convert::Infallible; use std::time::Duration; use tokio::sync::mpsc; use tokio::sync::mpsc::error::TrySendError; use tokio::time; use url::Url; const IRC_DEBOUNCE: Duration = Duration::from_millis(250); pub const IRC_RECONNECT_COOLDOWN: Duration = Duration::from_secs(60); // 1min pub const IRC_RECONNECT_JITTER: Duration = Duration::from_secs(60 * 3); // 3min const IRC_CLIENT_ID: &str = concat!( "p2p bootstrap - v", env!("CARGO_PKG_VERSION"), " https://github.com/kpcyrd/apt-swarm" ); fn random_nickname() -> String { let mut buf = [0u8; 3]; getrandom::fill(&mut buf).expect("Failed to use getrandom"); let name = format!("apt-swarm-{}", hex::encode(buf)); name } fn parse_channel(url: &str) -> Result<(String, String)> { let url = Url::parse(url).with_context(|| anyhow!("Failed to parse url: {url:?}"))?; if url.scheme() != "ircs" { bail!("Only secure ircs:// links are supported: {url:?}"); } let mut host = url .host_str() .with_context(|| anyhow!("Could not found host in irc url: {url:?}"))? .to_string(); if let Some(port) = url.port() { host += &format!(":{port}"); } if !["", "/"].contains(&url.path()) { bail!("Found unexpected path in irc url: {url:?}"); } let fragment = url .fragment() .with_context(|| anyhow!("Could not find channel in irc url: {url:?}"))?; Ok((host, format!("#{fragment}"))) } pub async fn connect_irc( rx: &mut mpsc::Receiver, irc: &(String, String), peering_tx: &mpsc::Sender, ) -> Result { let (server, channel) = irc; info!("Connecting to irc for peer discovery (server={server:?}, channel={channel:?})..."); let nickname = random_nickname(); let config = Config { nickname: Some(nickname), server: Some("irc.hackint.org".to_string()), channels: vec![channel.to_string()], realname: Some(IRC_CLIENT_ID.to_string()), use_tls: Some(true), ..Default::default() }; let mut client = Client::from_config(config).await?; client .identify() .context("Failed to identify with irc server")?; let mut stream = client.stream().context("Failed to setup irc stream")?; loop { tokio::select! { msg = stream.next() => { if let Some(message) = msg.transpose().context("Failed to read from irc stream")? { trace!("Received msg from irc server: {message:?}"); match message.command { Command::PRIVMSG(target, msg) => { debug!("Received irc privmsg: {:?}: {:?}", target, msg); if target != *channel { continue; } if !msg.starts_with("[sync] ") { continue; } match msg.parse::() { Ok(info) => { info!("Discovered peer: {info:?}"); let info = SyncRequest::from(info); if let Err(TrySendError::Full(info)) = peering_tx.try_send(info) { warn!("Discarding peer gossip because peering backlog is full: {info:?}"); } } Err(err) => { warn!("Malformed irc message: {err:#}"); } } } Command::Response(Response::RPL_ISUPPORT, _) => { // client.send_quit("QUIT")?; } _ => (), } } else { bail!("irc client has been shutdown"); } } msg = rx.recv() => { if let Some(msg) = msg { debug!("Sending message to irc: {msg:?}"); client.send_privmsg(channel, &msg) .context("Failed to send to irc")?; // slowing this down slightly, just in case time::sleep(Duration::from_millis(250)).await; } } } } } pub async fn spawn( mut rx: mpsc::Receiver, url: String, peering_tx: mpsc::Sender, ) -> Result { // briefly delay the connection, so we don't spam irc in case something crashes immediately tokio::time::sleep(IRC_DEBOUNCE).await; let irc = parse_channel(&url)?; loop { let Err(err) = connect_irc(&mut rx, &irc, &peering_tx).await; error!("irc connection has crashed: {err:#}"); time::sleep(IRC_RECONNECT_COOLDOWN).await; p2p::random_jitter(IRC_RECONNECT_JITTER).await; } } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_irc_url() { let url = "ircs://irc.hackint.org/##apt-swarm-p2p"; let (server, channel) = parse_channel(url).unwrap(); assert_eq!(server, "irc.hackint.org"); assert_eq!(channel, "##apt-swarm-p2p"); let url = "ircs://irc.hackint.org##apt-swarm-p2p"; let (server, channel) = parse_channel(url).unwrap(); assert_eq!(server, "irc.hackint.org"); assert_eq!(channel, "##apt-swarm-p2p"); let url = "ircs://irc.hackint.org:1337/##apt-swarm-p2p"; let (server, channel) = parse_channel(url).unwrap(); assert_eq!(server, "irc.hackint.org:1337"); assert_eq!(channel, "##apt-swarm-p2p"); } #[test] fn test_parse_irc_invalid() { assert!(parse_channel("irc://irc.hackint.org/##apt-swarm-p2p").is_err()); assert!(parse_channel("https://irc.hackint.org/##apt-swarm-p2p").is_err()); assert!(parse_channel("ircs://irc.hackint.org/").is_err()); assert!(parse_channel("ircs://irc.hackint.org/abc").is_err()); assert!(parse_channel("ircs://irc.hackint.org/abc##apt-swarm-p2p").is_err()); } } apt-swarm-0.5.1/src/p2p/mod.rs000064400000000000000000000120601046102023000141560ustar 00000000000000#[cfg(unix)] pub mod db; pub mod dns; pub mod fetch; #[cfg(feature = "irc")] pub mod irc; pub mod peerdb; pub mod peering; pub mod proto; pub mod sync; pub mod update_check; use crate::args::P2p; use crate::config::Config; use crate::db::{Database, DatabaseServer}; use crate::errors::*; use crate::keyring::Keyring; use crate::p2p::peerdb::PeerDb; use socket2::{Domain, Socket, Type}; use std::convert::Infallible; use std::net::SocketAddr; use std::time::Duration; use tokio::net::TcpSocket; use tokio::sync::mpsc; use tokio::task::JoinSet; use tokio::time; const FETCH_INTERVAL: Duration = Duration::from_secs(60 * 15); // 15min const FETCH_INTERVAL_JITTER: Duration = Duration::from_secs(45); const SYNC_IDLE_TIMEOUT: Duration = Duration::from_secs(60); const UPDATE_CHECK_INTERVAL: Duration = Duration::from_secs(60 * 15); // 15min const UPDATE_CHECK_DEBOUNCE: Duration = Duration::from_secs(5); const UPDATE_SHUTDOWN_DELAY: Duration = Duration::from_secs(60 * 20); // 20min const GOSSIP_IDLE_ANNOUNCE_INTERVAL: Duration = Duration::from_secs(3600 * 24); // 1h, set this to 24h later const P2P_SYNC_PORT_BACKLOG: u32 = 1024; pub async fn random_jitter(jitter: Duration) { let jitter = fastrand::u64(..jitter.as_secs()); time::sleep(Duration::from_secs(jitter)).await; } pub async fn spawn( db: Database, keyring: Keyring, config: Config, p2p: P2p, proxy: Option, ) -> Result { let mut set = JoinSet::new(); let (mut db_server, mut db_client) = DatabaseServer::new(db); set.spawn(async move { db_server.run().await?; bail!("Database server has terminated"); }); #[cfg(unix)] { let db_client = db_client.clone(); let db_socket_path = config.db_socket_path()?; set.spawn(async move { db::spawn_unix_db_server(&db_client, db_socket_path).await }); } let (irc_tx, irc_rx) = mpsc::channel(32); let irc_tx = cfg!(feature = "irc").then(|| irc_tx); let peerdb = PeerDb::read(&config).await?; let (peerdb_tx, peerdb_rx) = peerdb::Client::new(); set.spawn(async move { peerdb::spawn(peerdb, peerdb_rx).await }); if !p2p.no_bind { for addr in p2p.bind { let db_client = db_client.clone(); let socket = match addr { SocketAddr::V4(_) => Socket::new(Domain::IPV4, Type::STREAM, None)?, SocketAddr::V6(_) => { let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?; socket .set_only_v6(true) .context("Failed to set port to ipv6-only")?; socket } }; socket .set_reuse_address(true) .context("Failed to set reuseaddr for port")?; socket .set_nonblocking(true) .context("Failed to set port to non-blocking")?; let socket = TcpSocket::from_std_stream(socket.into()); socket .bind(addr) .with_context(|| anyhow!("Failed to bind to address: {:?}", addr))?; let listener = socket.listen(P2P_SYNC_PORT_BACKLOG)?; debug!("Listening on address: {addr:?}"); let peerdb_tx = peerdb_tx.clone(); set.spawn( async move { sync::spawn_sync_server(&db_client, peerdb_tx, listener).await }, ); } } if !p2p.no_fetch { let mut db_client = db_client.clone(); let keyring = keyring.clone(); let repositories = config.data.repositories; set.spawn(async move { fetch::spawn_fetch_timer( &mut db_client, keyring, repositories, proxy, p2p.announce, irc_tx, ) .await }); } if let Some(image) = p2p.check_container_updates { let commit = match p2p.update_assume_commit { Some(s) if s.is_empty() => { bail!("Update checks are configured but current commit is empty string") } Some(commit) => commit, None => bail!("Update checks are configured but current commit is not provided"), }; set.spawn(update_check::spawn_update_check(image, commit)); } let (peering_tx, peering_rx) = mpsc::channel(1024); set.spawn(async move { peering::spawn(&mut db_client, keyring, peerdb_tx, proxy, peering_rx).await }); #[cfg(feature = "irc")] if !p2p.no_bootstrap && !p2p.irc.no_irc { set.spawn(irc::spawn(irc_rx, p2p.irc.irc_channel, peering_tx.clone())); } if !p2p.no_bootstrap && !p2p.dns.no_dns { set.spawn(dns::spawn(p2p.dns.dns, peering_tx)); } // if irc is not enabled, supress an unused variable warning #[cfg(not(feature = "irc"))] let _ = irc_rx; info!("Successfully started p2p node..."); let result = set .join_next() .await .context("All features have been disabled, nothing to do")?; result.context("Failed to wait for task")? } apt-swarm-0.5.1/src/p2p/peerdb.rs000064400000000000000000000354051046102023000146500ustar 00000000000000use crate::config::Config; use crate::errors::*; use crate::p2p::proto::PeerAddr; use chrono::{DateTime, TimeDelta, Utc}; use colored::{Color, Colorize}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::collections::btree_map::Entry; use std::collections::BTreeMap; use std::convert::Infallible; use std::path::PathBuf; use std::time::Duration; use tokio::fs; use tokio::sync::mpsc; use tokio::sync::mpsc::error::TrySendError; use tokio::time; const EXPIRE_ERROR_THRESHOLD: usize = 30; const EXPIRE_UNLESS_ADVERTISED_SINCE: Duration = Duration::from_secs(3600 * 24 * 14); const PEERDB_EXPIRE_INTERVAL: Duration = Duration::from_secs(60); const PEERDB_SAMPLE_SIZE: usize = 5; #[derive(Debug)] pub enum Req { AddAdvertisedPeers(Vec), Sample { max_success_age: Option, tx: mpsc::Sender>, }, Metric { metric: MetricType, value: MetricValue, addr: PeerAddr, }, Write, } #[derive(Debug, Clone)] pub struct Client { tx: mpsc::Sender, } impl Client { pub fn new() -> (Self, mpsc::Receiver) { let (tx, rx) = mpsc::channel(1024); (Self { tx }, rx) } async fn request(&self, req: Req, mut rx: mpsc::Receiver) -> Result { self.tx .send(req) .await .map_err(|_| anyhow!("PeerDb server disconnected"))?; let ret = rx.recv().await.context("PeerDb server disconnected")?; Ok(ret) } fn lossy_send(&self, req: Req) { if let Err(TrySendError::Full(req)) = self.tx.try_send(req) { warn!("Discarding peerdb request because backlog is full: {req:?}"); } } pub fn add_advertised_peers(&self, addrs: Vec) { self.lossy_send(Req::AddAdvertisedPeers(addrs)); } #[inline] pub fn successful(&self, metric: MetricType, addr: PeerAddr) { self.lossy_send(Req::Metric { metric, value: MetricValue::Successful, addr, }) } #[inline] pub fn error(&self, metric: MetricType, addr: PeerAddr) { self.lossy_send(Req::Metric { metric, value: MetricValue::Error, addr, }) } pub async fn sample(&self, max_success_age: Option) -> Result> { let (tx, rx) = mpsc::channel(1); self.request( Req::Sample { max_success_age, tx, }, rx, ) .await } pub fn write(&self) { self.lossy_send(Req::Write); } } pub fn format_time_opt(time: Option>) -> Cow<'static, str> { if let Some(time) = time { Cow::Owned(format_time(time)) } else { Cow::Borrowed("-") } } pub fn format_time(time: DateTime) -> String { time.format("%FT%T").to_string() } #[derive(Debug, Default, PartialEq, Serialize, Deserialize)] pub struct Metric { pub last_attempt: Option>, pub errors_since: usize, pub last_success: Option>, } impl Metric { pub fn metric(&mut self, value: MetricValue) { match value { MetricValue::Successful => self.successful(), MetricValue::Error => self.error(), } } pub fn successful(&mut self) { self.errors_since = 0; let now = Utc::now(); self.last_success = Some(now); self.last_attempt = Some(now); } pub fn error(&mut self) { self.errors_since += 1; self.last_attempt = Some(Utc::now()); } pub fn format_stats(&self) -> String { format!( "last_attempt={:<19} errors_since={} last_success={}", format_time_opt(self.last_attempt).yellow(), self.errors_since .to_string() .color(if self.errors_since == 0 { Color::Green } else { Color::Red }), format_time_opt(self.last_success).yellow(), ) } } #[derive(Debug)] pub enum MetricType { Connect, Handshake, } #[derive(Debug)] pub enum MetricValue { Successful, Error, } #[derive(Debug, Default, PartialEq, Serialize, Deserialize)] pub struct PeerStats { #[serde(default)] pub connect: Metric, #[serde(default)] pub handshake: Metric, pub last_advertised: Option>, } impl PeerStats { pub fn metric(&mut self, metric: MetricType, value: MetricValue) { match metric { MetricType::Connect => self.connect.metric(value), MetricType::Handshake => self.handshake.metric(value), } } pub fn expired(&self, now: DateTime) -> bool { // only remove peers that have been advertised, but not recently let Some(last_advertised) = self.last_advertised else { return false; }; if last_advertised + EXPIRE_UNLESS_ADVERTISED_SINCE > now { return false; } // expire peers we couldn't connect to in a while if self.connect.errors_since > EXPIRE_ERROR_THRESHOLD { return true; } // expire peers we couldn't handshake with in a while if self.handshake.errors_since > EXPIRE_ERROR_THRESHOLD { return true; } // peer is still good false } } #[derive(Debug, Default, PartialEq, Serialize, Deserialize)] struct Data { pub peers: BTreeMap, } pub struct PeerDb { data: Data, path: PathBuf, new_path: PathBuf, } impl PeerDb { /// Register a peer address in the database /// /// Returns true if we haven't known this address before. pub fn add_peer(&mut self, addr: PeerAddr) -> (&mut PeerStats, bool) { trace!("Adding address to peerdb: {addr:?}"); match self.data.peers.entry(addr) { entry @ Entry::Vacant(_) => (entry.or_default(), true), entry @ Entry::Occupied(_) => (entry.or_default(), false), } } /// Register a list of peers that has been actively advertised to us /// /// The database should always be written afterwards to `last_advertised` /// is persisted properly. pub fn add_advertised_peers(&mut self, addrs: &[PeerAddr]) { let now = Utc::now(); for addr in addrs { let (peer, _new) = self.add_peer(addr.clone()); peer.last_advertised = Some(now); } } pub fn peers(&self) -> &BTreeMap { &self.data.peers } /// Return a sample of random peers to connect to pub fn sample(&self, max_success_age: Option) -> Vec { let now = Utc::now(); let delta = max_success_age .map(|max_success_age| TimeDelta::from_std(max_success_age).unwrap_or(TimeDelta::MAX)); // apply `max_success_age` filtering let mut peers = self .data .peers .iter() .flat_map(|(addr, stats)| { if let Some(delta) = delta { let last_success = stats.handshake.last_success?; if now.signed_duration_since(last_success) > delta { return None; } } Some(addr) }) .collect::>(); fastrand::shuffle(&mut peers); // TODO: make this smarter peers .into_iter() .take(PEERDB_SAMPLE_SIZE) .cloned() .collect() } /// Remove old peers that both: /// /// - we couldn't successfully connect/handshake with in a while /// - haven't been advertised anymore in a while /// /// Peers that are still being advertised, but we couldn't /// connect/handshake with in a while are still being kept around so we don't /// stop toning down our connection attempts to them. /// /// Returns true if any peers have been removed. pub fn expire_old_peers(&mut self, now: DateTime) -> bool { let before = self.data.peers.len(); self.data.peers.retain(|_, peer| !peer.expired(now)); let after = self.data.peers.len(); if after != before { info!("Removed {} expired peers", before.saturating_sub(after)); true } else { false } } /// Load the local peerdb file from disk. /// /// If this fails, return an empty database so we self-heal. pub async fn read(config: &Config) -> Result { let mut db = Self { data: Data::default(), path: config.peerdb_path()?, new_path: config.peerdb_new_path()?, }; let path = &db.path; debug!("Reading peerdb from file: {path:?}"); let Ok(buf) = fs::read(&path).await else { debug!("Failed to read peerdb file, using empty"); return Ok(db); }; let Ok(data) = serde_json::from_slice(&buf) else { debug!("Failed to parse peerdb file, using empty"); return Ok(db); }; db.data = data; Ok(db) } /// Write the peerdb to disk, in a way so we don't accidentally lose data /// on an unexpected crash pub async fn write(&self) -> Result<()> { let buf = serde_json::to_string(&self.data).context("Failed to serialize peerdb")?; let new_path = &self.new_path; debug!("Writing peerdb file to disk: {new_path:?}"); fs::write(&new_path, &buf) .await .with_context(|| anyhow!("Failed to write peerdb file at {new_path:?}"))?; let path = &self.path; debug!("Moving peerdb file to final location: {path:?}"); fs::rename(&new_path, &path) .await .with_context(|| anyhow!("Failed to rename peerdb {new_path:?} to {path:?}"))?; Ok(()) } } pub async fn spawn(mut peerdb: PeerDb, mut rx: mpsc::Receiver) -> Result { let mut interval = time::interval(PEERDB_EXPIRE_INTERVAL); loop { tokio::select! { req = rx.recv() => { let Some(req) = req else { break }; match req { Req::AddAdvertisedPeers(addrs) => { peerdb.add_advertised_peers(&addrs); peerdb.write().await?; } Req::Sample { max_success_age, tx } => { let sample = peerdb.sample(max_success_age); tx.send(sample).await.ok(); } Req::Metric { metric, value, addr } => { let (peer, _new) = peerdb.add_peer(addr); peer.metric(metric, value); } Req::Write => peerdb.write().await?, } } _ = interval.tick() => { if peerdb.expire_old_peers(Utc::now()) { peerdb.write().await?; } } } } bail!("PeerDb channel has been closed"); } #[cfg(test)] mod tests { use super::*; #[test] fn parse_basic_db() { let data = r#" {"peers":{"[2001:db8::]:16169":{}}} "#; let data = serde_json::from_str::(data).unwrap(); assert_eq!( data, Data { peers: [("[2001:db8::]:16169".parse().unwrap(), PeerStats::default())] .into_iter() .collect(), } ); } #[test] fn test_expired_peers() { fn datetime(s: &str) -> DateTime { s.parse::>().unwrap() } let now = datetime("2025-02-17T01:00:00Z"); // empty assert!(!PeerStats { connect: Metric::default(), handshake: Metric::default(), last_advertised: None, } .expired(now)); // connect errors assert!(PeerStats { connect: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 500, last_success: None, }, handshake: Metric::default(), last_advertised: Some(datetime("2025-01-01T13:37:00Z")), } .expired(now)); // handshake errors assert!(PeerStats { connect: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 0, last_success: Some(datetime("2025-02-17T00:45:00Z")), }, handshake: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 500, last_success: Some(datetime("2025-01-14T00:45:00Z")), }, last_advertised: Some(datetime("2025-01-01T13:37:00Z")), } .expired(now)); // connect errors but recently advertised assert!(!PeerStats { connect: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 500, last_success: None, }, handshake: Metric::default(), last_advertised: Some(datetime("2025-02-14T13:37:00Z")), } .expired(now)); // handshake errors but recently advertised assert!(!PeerStats { connect: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 0, last_success: Some(datetime("2025-02-17T00:45:00Z")), }, handshake: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 500, last_success: Some(datetime("2025-01-14T00:45:00Z")), }, last_advertised: Some(datetime("2025-02-14T13:37:00Z")), } .expired(now)); // connect errors but never advertised assert!(!PeerStats { connect: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 500, last_success: None, }, handshake: Metric::default(), last_advertised: None, } .expired(now)); // handshake errors but never advertised assert!(!PeerStats { connect: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 0, last_success: Some(datetime("2025-02-17T00:45:00Z")), }, handshake: Metric { last_attempt: Some(datetime("2025-02-17T00:45:00Z")), errors_since: 500, last_success: Some(datetime("2025-01-14T00:45:00Z")), }, last_advertised: None, } .expired(now)); } } apt-swarm-0.5.1/src/p2p/peering.rs000064400000000000000000000206301046102023000150320ustar 00000000000000use crate::db::DatabaseClient; use crate::errors::*; use crate::keyring::Keyring; use crate::net; use crate::p2p; use crate::p2p::peerdb::{self, MetricType}; use crate::p2p::proto::{PeerAddr, SyncRequest}; use crate::sync; use crate::timers::EasedInterval; use ipnetwork::IpNetwork; use sequoia_openpgp::Fingerprint; use std::collections::VecDeque; use std::convert::Infallible; use std::net::{IpAddr, SocketAddr}; use std::num::NonZeroUsize; use std::sync::LazyLock; use std::time::Duration; use tokio::io::AsyncWriteExt; use tokio::sync::mpsc; use tokio::time; pub static P2P_BLOCK_LIST: LazyLock> = LazyLock::new(|| { vec![ "127.0.0.1/8".parse().unwrap(), "10.0.0.1/8".parse().unwrap(), "172.16.0.0/12".parse().unwrap(), "192.168.0.0/16".parse().unwrap(), "169.254.0.0/16".parse().unwrap(), "224.0.0.0/4".parse().unwrap(), ] }); pub static P2P_ILLEGAL_PORTS: &[u16] = &[ 21, 22, 23, 25, 53, 80, 110, 143, 389, 443, 587, 993, 995, 1194, 3128, 3389, 5900, 6667, 6669, 6697, 8080, ]; /// When an ip is in cooldown, this port is still allowed, until the specific port goes into cooldown too pub const STANDARD_P2P_PORT: u16 = 16169; /// How often to connect to one of our known peers const P2P_SYNC_CONNECT_INTERVAL: Duration = Duration::from_secs(60 * 10); // 10min /// Time until we make our first connection to an already known peer const P2P_SYNC_CONNECT_DELAY: Duration = Duration::from_secs(30); // 30sec const P2P_SYNC_CONNECT_JITTER: Duration = Duration::from_secs(3); pub const COOLDOWN_LRU_SIZE: usize = 16_384; pub const COOLDOWN_PORT_AFTER_SUCCESS: Duration = Duration::from_secs(60 * 5); // 5min pub const COOLDOWN_PORT_AFTER_ERROR: Duration = Duration::from_secs(60 * 60); // 1hour pub const COOLDOWN_HOST_AFTER_ERROR: Duration = Duration::from_secs(60 * 60); // 1hour pub const COOLDOWN_HOST_THRESHOLD: usize = 10; pub async fn pull_from_peer( db: &mut D, keyring: &Keyring, peerdb: &peerdb::Client, fingerprints: &[Fingerprint], addr: &PeerAddr, proxy: Option, ) -> Result<()> { // setup connection let mut sock = match net::connect(addr, proxy).await { Ok(sock) => { peerdb.successful(MetricType::Connect, addr.clone()); sock } Err(err) => { peerdb.error(MetricType::Connect, addr.clone()); return Err(err); } }; let (mut rx, mut tx) = sock.split(); // perform handshake match net::handshake(&mut rx, &mut tx).await { Ok(_) => { peerdb.successful(MetricType::Handshake, addr.clone()); } Err(err) => { peerdb.error(MetricType::Handshake, addr.clone()); tx.shutdown().await.ok(); return Err(err); } } peerdb.write(); // sync from peer let result = sync::sync_pull(db, keyring, fingerprints, false, &mut tx, rx).await; // shutdown connection tx.shutdown().await.ok(); // peer.sync.successful(); result } #[derive(Debug, Default)] pub struct CooldownEntry { tries: VecDeque, } impl CooldownEntry { fn filter(&mut self) { let now = time::Instant::now(); self.tries.retain(|e| now < *e); } pub fn has_capacity(&mut self) -> bool { self.filter(); self.tries.len() < COOLDOWN_HOST_THRESHOLD } pub fn mark_bad(&mut self) { self.filter(); self.tries .push_back(time::Instant::now() + COOLDOWN_HOST_AFTER_ERROR); } } #[derive(Debug)] pub struct Cooldowns { ip_cache: lru::LruCache, port_cache: lru::LruCache, } impl Cooldowns { pub fn new() -> Self { let ip_cache = lru::LruCache::new(NonZeroUsize::new(COOLDOWN_LRU_SIZE).unwrap()); let port_cache = lru::LruCache::new(NonZeroUsize::new(COOLDOWN_LRU_SIZE).unwrap()); Cooldowns { ip_cache, port_cache, } } pub fn can_approach(&mut self, addr: &PeerAddr) -> bool { let now = time::Instant::now(); if let PeerAddr::Inet(addr) = &addr { if addr.port() != STANDARD_P2P_PORT { if let Some(entry) = self.ip_cache.get_mut(&addr.ip()) { if !entry.has_capacity() { return false; } } } } if let Some(entry) = self.port_cache.get(addr) { now >= *entry } else { true } } pub fn mark_ok(&mut self, addr: PeerAddr) { self.port_cache .put(addr, time::Instant::now() + COOLDOWN_PORT_AFTER_SUCCESS); } pub fn mark_bad(&mut self, addr: PeerAddr) { if let PeerAddr::Inet(addr) = &addr { self.ip_cache .get_or_insert_mut(addr.ip(), CooldownEntry::default) .mark_bad(); } self.port_cache .put(addr, time::Instant::now() + COOLDOWN_PORT_AFTER_ERROR); } } impl Default for Cooldowns { fn default() -> Self { Self::new() } } pub async fn spawn( db: &mut D, keyring: Keyring, peerdb: peerdb::Client, proxy: Option, mut rx: mpsc::Receiver, ) -> Result { // keep track of connection attempts to avoid flooding let mut cooldown = Cooldowns::new(); let mut interval = EasedInterval::new(P2P_SYNC_CONNECT_DELAY, P2P_SYNC_CONNECT_INTERVAL); loop { // Wait for request, or automatically connect to known peer let req = tokio::select! { req = rx.recv() => { let Some(req) = req else { break }; // register all addresses as known before attempting to sync peerdb.add_advertised_peers(req.addrs.clone()); req } _ = interval.tick() => { // Automatically pick a known peer let addrs = peerdb.sample(None).await?; debug!("Automatically selected peers for periodic sync: {addrs:?}"); SyncRequest { hint: None, addrs, } } }; // TODO: allow concurrent syncs // sync from addresses for addr in req.addrs { // only connect if we're not already in sync if let Some(hint) = &req.hint { let fp = &hint.fp; let (idx, _num) = db .index_from_scan(&sync::TreeQuery { fp: fp.clone(), hash_algo: "sha256".to_string(), prefix: None, }) .await?; if *hint.idx == idx { debug!( "We're already in sync with peer: addr={addr:?}, fp={fp:?}, idx={idx:?}" ); continue; } } // prepare connection if let PeerAddr::Inet(addr) = &addr { for block in P2P_BLOCK_LIST.iter() { if block.contains(addr.ip()) { debug!( "Address is on a blocklist, skipping: addr={addr:?}, block={block:?}" ); continue; } } if P2P_ILLEGAL_PORTS.contains(&addr.port()) { debug!("Port is on blocklist, skipping: addr={addr:?}"); continue; } } if !cooldown.can_approach(&addr) { debug!("Address is still in cooldown, skipping for now: {addr:?}"); continue; } p2p::random_jitter(P2P_SYNC_CONNECT_JITTER).await; info!("Syncing from remote peer: {addr:?}"); let ret = pull_from_peer(db, &keyring, &peerdb, &[], &addr, proxy).await; debug!("Connection to {addr:?} has been closed"); match ret { Ok(_) => { cooldown.mark_ok(addr); break; } Err(err) => { warn!("Error while syncing from peer {addr:?}: {err:#}"); cooldown.mark_bad(addr); } } peerdb.write(); } } bail!("Peering task has crashed") } apt-swarm-0.5.1/src/p2p/proto.rs000064400000000000000000000576271046102023000145640ustar 00000000000000use crate::errors::*; use ipnetwork::IpNetwork; use serde::{Deserialize, Serialize}; use std::fmt; use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; #[derive(Debug, PartialEq)] pub struct SyncRequest { pub hint: Option, pub addrs: Vec, } #[derive(Debug, PartialEq)] pub struct SyncHint { pub fp: sequoia_openpgp::Fingerprint, pub idx: String, } impl From for SyncRequest { fn from(gossip: PeerGossip) -> Self { Self { hint: Some(SyncHint { fp: gossip.fp, idx: gossip.idx, }), addrs: gossip.addrs, } } } #[derive(Debug, PartialEq)] pub struct PeerGossip { pub fp: sequoia_openpgp::Fingerprint, pub idx: String, pub count: u64, pub addrs: Vec, } impl FromStr for PeerGossip { type Err = Error; fn from_str(s: &str) -> Result { let s = s .strip_prefix("[sync] ") .context("Message is missing the [sync] tag")?; let mut split = s.split(' '); let fp = split .next() .context("Missing mandatory attribute: fingerprint")?; let fp = fp .strip_prefix("fp=") .with_context(|| anyhow!("First attribute is expected to be fingerprint: {fp:?}"))?; let fp = fp .parse() .with_context(|| anyhow!("Failed to parse as fingerprint: {fp:?}"))?; let idx = split.next().context("Missing mandatory attribute: index")?; let idx = idx .strip_prefix("idx=") .with_context(|| anyhow!("First attribute is expected to be index: {idx:?}"))? .to_string(); let count = split.next().context("Missing mandatory attribute: count")?; let count = count .strip_prefix("count=") .with_context(|| anyhow!("First attribute is expected to be count: {count:?}"))?; let count = count .parse() .with_context(|| anyhow!("Failed to parse as count: {count:?}"))?; let mut addrs = Vec::new(); for extra in split { if let Some(addr) = extra.strip_prefix("addr=") { let addr = addr .parse() .with_context(|| anyhow!("Failed to parse as address: {addr:?}"))?; addrs.push(addr); } } Ok(PeerGossip { fp, idx, count, addrs, }) } } #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum PeerAddr { Inet(SocketAddr), Onion((String, u16)), } impl PeerAddr { fn inet_to_u128(addr: IpAddr) -> u128 { match addr { // IPv4 has most significant bit set to 0 IpAddr::V4(ip) => (ip.to_bits() as u128) << 95, // IPv6 has most significant bit set to 1 IpAddr::V6(ip) => (ip.to_bits() >> 1) | (1 << 127), } } pub fn xor_distance(&self, other: &PeerAddr) -> u128 { match (self, other) { (PeerAddr::Inet(value), PeerAddr::Inet(other)) => { let value = Self::inet_to_u128(value.ip()); let other = Self::inet_to_u128(other.ip()); value ^ other } // key distance doesn't make sense here (PeerAddr::Onion(_), PeerAddr::Onion(_)) => 1, _ => u128::MAX, } } } impl fmt::Debug for PeerAddr { fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PeerAddr::Inet(addr) => fmt::Debug::fmt(addr, w), PeerAddr::Onion((host, port)) => { write!(w, "\"{}:{}\"", host.escape_debug(), port)?; Ok(()) } } } } impl fmt::Display for PeerAddr { fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PeerAddr::Inet(addr) => fmt::Display::fmt(addr, w), PeerAddr::Onion((host, port)) => { write!(w, "{host}:{port}")?; Ok(()) } } } } impl FromStr for PeerAddr { type Err = Error; fn from_str(addr: &str) -> Result { if addr.starts_with('[') { // IPv6 address let addr = addr.parse()?; Ok(PeerAddr::Inet(addr)) } else { let Some((host, port)) = addr.rsplit_once(':') else { bail!("Missing port in peer address: {addr:?}"); }; let port = port .parse() .with_context(|| anyhow!("Failed to parse port: {addr:?}"))?; if host.ends_with(".onion") { // .onion address if !host.chars().all(|c| c.is_alphanumeric() || c == '.') { bail!("Onion address contains invalid characters"); } Ok(PeerAddr::Onion((host.to_string(), port))) } else { // IPv4 address let host = host .parse() .with_context(|| anyhow!("Failed to parse ip address: {addr:?}"))?; Ok(PeerAddr::Inet(SocketAddr::new(host, port))) } } } } impl Serialize for PeerAddr { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { match self { PeerAddr::Inet(addr) => { let addr = addr.to_string(); addr.serialize(serializer) } PeerAddr::Onion((host, port)) => format!("{host}:{port}").serialize(serializer), } } } impl<'de> Deserialize<'de> for PeerAddr { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let value: String = Deserialize::deserialize(deserializer)?; value .parse() .map_err(|err| serde::de::Error::custom(format!("{err:#}"))) } } #[derive(Debug, Clone, PartialEq)] pub enum PeerFilter { IpNetwork(IpNetwork), ExactIp { addr: IpAddr, port: Option }, ExactOnion { onion: String, port: Option }, } impl PeerFilter { pub fn matches(&self, addr: &PeerAddr) -> bool { match (self, addr) { (PeerFilter::IpNetwork(net), PeerAddr::Inet(peer)) => net.contains(peer.ip()), (PeerFilter::IpNetwork(_), PeerAddr::Onion(_)) => false, (PeerFilter::ExactIp { addr, port }, PeerAddr::Inet(peer)) => { if let Some(port) = port { if *port != peer.port() { return false; } } peer.ip() == *addr } (PeerFilter::ExactIp { .. }, PeerAddr::Onion(_)) => false, (PeerFilter::ExactOnion { .. }, PeerAddr::Inet(_)) => false, (PeerFilter::ExactOnion { onion, port }, PeerAddr::Onion((peer_host, peer_port))) => { if let Some(port) = port { if *port != *peer_port { return false; } } peer_host == onion } } } } impl FromStr for PeerFilter { type Err = Error; fn from_str(s: &str) -> Result { if s.contains("/") { // this is an ip network without port let network = s.parse::()?; Ok(PeerFilter::IpNetwork(network)) } else if let Ok(addr) = s.parse::() { // this is a full PeerAddr (with port) match addr { PeerAddr::Inet(addr) => Ok(PeerFilter::ExactIp { addr: addr.ip(), port: Some(addr.port()), }), PeerAddr::Onion((host, port)) => Ok(PeerFilter::ExactOnion { onion: host, port: Some(port), }), } } else { // this is a host without port if s.ends_with(".onion") { Ok(PeerFilter::ExactOnion { onion: s.to_string(), port: None, }) } else { let addr = s.parse::()?; Ok(PeerFilter::ExactIp { addr, port: None }) } } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_irc_no_addrs() -> Result<()> { let s = "[sync] fp=ED541312A33F1128F10B1C6C54404762BBB6E853 idx=sha256:1994bea786a499ec72ce94a45e2830ce31746a5ef4fb7a2b73ba0934e4a046ac count=180"; let gi = s.parse::()?; assert_eq!( gi, PeerGossip { fp: "ED541312A33F1128F10B1C6C54404762BBB6E853".parse()?, idx: "sha256:1994bea786a499ec72ce94a45e2830ce31746a5ef4fb7a2b73ba0934e4a046ac" .to_string(), count: 180, addrs: Vec::new(), } ); Ok(()) } #[test] fn test_parse_irc_multiple_addrs() -> Result<()> { let s = "[sync] fp=2265EB4CB2BF88D900AE8D1B74A941BA219EC810 idx=sha256:55a00753512036f55ccc421217e008e4922c66592e6281b09de2fcba4dbd59ce count=12 addr=192.0.2.146:16169 addr=[2001:db8:c010:8f3a::1]:16169"; let gi = s.parse::()?; assert_eq!( gi, PeerGossip { fp: "2265EB4CB2BF88D900AE8D1B74A941BA219EC810".parse()?, idx: "sha256:55a00753512036f55ccc421217e008e4922c66592e6281b09de2fcba4dbd59ce" .to_string(), count: 12, addrs: vec![ "192.0.2.146:16169".parse()?, "[2001:db8:c010:8f3a::1]:16169".parse()?, ], } ); Ok(()) } #[test] fn test_parse_irc_with_onion() -> Result<()> { let s = "[sync] fp=2265EB4CB2BF88D900AE8D1B74A941BA219EC810 idx=sha256:55a00753512036f55ccc421217e008e4922c66592e6281b09de2fcba4dbd59ce count=12 addr=192.0.2.146:16169 addr=3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169"; let gi = s.parse::()?; assert_eq!( gi, PeerGossip { fp: "2265EB4CB2BF88D900AE8D1B74A941BA219EC810".parse()?, idx: "sha256:55a00753512036f55ccc421217e008e4922c66592e6281b09de2fcba4dbd59ce" .to_string(), count: 12, addrs: vec![ PeerAddr::Inet("192.0.2.146:16169".parse()?), PeerAddr::Onion(( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion" .to_string(), 16169 )), ], } ); Ok(()) } #[test] fn test_ipv4_xor_distance() { let base = "192.168.1.2:16169".parse::().unwrap(); assert_eq!( base.xor_distance(&"192.168.1.2:16169".parse::().unwrap()), 0 ); assert_eq!( base.xor_distance(&"192.168.1.2:443".parse::().unwrap()), 0 ); assert_eq!( base.xor_distance(&"192.168.1.1:16169".parse::().unwrap()), 3 << 95 ); assert_eq!( base.xor_distance(&"192.168.1.3:16169".parse::().unwrap()), 1 << 95 ); assert_eq!( base.xor_distance(&"192.168.2.0:16169".parse::().unwrap()), 770 << 95 ); assert_eq!( base.xor_distance(&"1.0.0.1:16169".parse::().unwrap()), 3_249_012_995 << 95 ); assert_eq!( base.xor_distance(&"255.255.255.255:16169".parse::().unwrap()), 1_062_731_517 << 95 ); assert_eq!( base.xor_distance( &"[2001:db8:3333:4444:5555:6666:7777:8888]:16169" .parse::() .unwrap() ), 319_453_597_143_525_594_717_699_116_388_956_488_772, ); } #[test] fn test_ipv6_xor_distance() { let base = "[2001:db8:3333:4444:5555:6666:7777:8888]:16169" .parse::() .unwrap(); assert_eq!( base.xor_distance( &"[2001:db8:3333:4444:5555:6666:7777:8888]:16169" .parse::() .unwrap() ), 0 ); assert_eq!( base.xor_distance( &"[2001:db8:3333:4444:5555:6666:7777:8888]:443" .parse::() .unwrap() ), 0 ); assert_eq!( base.xor_distance(&"[2001:db8::]:16169".parse::().unwrap()), 7_922_856_549_568_655_098_759_595_076 ); assert_eq!( base.xor_distance(&"[fe80::1a2b:3c4d:5e6f]:16169".parse::().unwrap()), 147_879_349_812_077_389_872_108_282_106_859_055_987 ); assert_eq!( base.xor_distance(&"192.168.1.3:16169".parse::().unwrap()), 319_453_597_183_139_675_974_831_285_185_728_463_940 ); } #[test] fn test_peer_addr_serialize() { let addr = serde_json::to_string(&PeerAddr::Inet("[2001:db8::]:16169".parse().unwrap())).unwrap(); assert_eq!(addr, "\"[2001:db8::]:16169\""); let addr = serde_json::to_string(&PeerAddr::Onion(( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion".to_string(), 16169, ))) .unwrap(); assert_eq!( addr, "\"3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169\"" ); } #[test] fn test_peer_addr_deserialize() { let addr = serde_json::from_str::("\"[2001:db8::]:16169\"").unwrap(); assert_eq!(addr, PeerAddr::Inet("[2001:db8::]:16169".parse().unwrap())); let addr = serde_json::from_str::( "\"3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169\"", ) .unwrap(); assert_eq!( addr, PeerAddr::Onion(( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion".to_string(), 16169 )) ); } #[test] fn test_peer_addr_debug_inet() { let addr = PeerAddr::Inet("[2001:db8::]:16169".parse().unwrap()); assert_eq!(format!("{addr:?}"), "[2001:db8::]:16169"); } #[test] fn test_peer_addr_debug_onion() { let addr = PeerAddr::Onion(( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion".to_string(), 16169, )); assert_eq!( format!("{addr:?}"), "\"3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169\"" ); } #[test] fn test_detect_invalid_onion_address() { let addr = "3wisi2b\nfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169"; assert!(addr.parse::().is_err()); } #[test] fn parse_peerfilter() { fn test_matches(filter: PeerFilter) -> Vec<(&'static str, bool)> { [ "192.168.1.2:16169", "1.1.1.1:16169", "1.1.1.1:1337", "[2001:db8::]:16169", "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", "[fe80::1]:16169", "[fe80::1]:1337", ] .into_iter() .map(|addr| (addr, addr.parse::().unwrap())) .map(|(addr, peer)| { let matches = filter.matches(&peer); (addr, matches) }) .collect() } // test let filter = "1.1.1.1".parse::().unwrap(); assert_eq!( filter, PeerFilter::ExactIp { addr: "1.1.1.1".parse().unwrap(), port: None, } ); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", true), ("1.1.1.1:1337", true), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", false), ("[fe80::1]:1337", false) ] ); // test let filter = "::/0".parse::().unwrap(); assert_eq!(filter, PeerFilter::IpNetwork("::/0".parse().unwrap()),); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", false), ("1.1.1.1:1337", false), ("[2001:db8::]:16169", true), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", true), ("[fe80::1]:1337", true) ] ); // test let filter = "0.0.0.0/0".parse::().unwrap(); assert_eq!(filter, PeerFilter::IpNetwork("0.0.0.0/0".parse().unwrap()),); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", true), ("1.1.1.1:16169", true), ("1.1.1.1:1337", true), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", false), ("[fe80::1]:1337", false) ] ); // test let filter = "1.1.1.1/8".parse::().unwrap(); assert_eq!(filter, PeerFilter::IpNetwork("1.1.1.1/8".parse().unwrap()),); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", true), ("1.1.1.1:1337", true), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", false), ("[fe80::1]:1337", false) ] ); // test let filter = "fe80::1".parse::().unwrap(); assert_eq!( filter, PeerFilter::ExactIp { addr: "fe80::1".parse().unwrap(), port: None, } ); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", false), ("1.1.1.1:1337", false), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", true), ("[fe80::1]:1337", true) ] ); // test let filter = "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion" .parse::() .unwrap(); assert_eq!( filter, PeerFilter::ExactOnion { onion: "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion".to_string(), port: None, } ); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", false), ("1.1.1.1:1337", false), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", true ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", true ), ("[fe80::1]:16169", false), ("[fe80::1]:1337", false) ] ); // test let filter = "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169" .parse::() .unwrap(); assert_eq!( filter, PeerFilter::ExactOnion { onion: "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion".to_string(), port: Some(16169), } ); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", false), ("1.1.1.1:1337", false), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", true ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", false), ("[fe80::1]:1337", false) ] ); // test let filter = "1.1.1.1:16169".parse::().unwrap(); assert_eq!( filter, PeerFilter::ExactIp { addr: "1.1.1.1".parse().unwrap(), port: Some(16169), } ); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", true), ("1.1.1.1:1337", false), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", false), ("[fe80::1]:1337", false) ] ); // test let filter = "[fe80::1]:16169".parse::().unwrap(); assert_eq!( filter, PeerFilter::ExactIp { addr: "fe80::1".parse().unwrap(), port: Some(16169), } ); assert_eq!( test_matches(filter), &[ ("192.168.1.2:16169", false), ("1.1.1.1:16169", false), ("1.1.1.1:1337", false), ("[2001:db8::]:16169", false), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:16169", false ), ( "3wisi2bfpxplne5wlwz4l5ucvsbaozbteaqnm62oxzmgwhb2qqxvsuyd.onion:1337", false ), ("[fe80::1]:16169", true), ("[fe80::1]:1337", false) ] ); } } apt-swarm-0.5.1/src/p2p/sync.rs000064400000000000000000000022461046102023000143600ustar 00000000000000use crate::db::DatabaseServerClient; use crate::errors::*; use crate::p2p::{self, peerdb}; use crate::sync; use std::convert::Infallible; use tokio::io::AsyncWriteExt; use tokio::net::{TcpListener, TcpStream}; pub async fn serve_sync_client( db: &mut DatabaseServerClient, peerdb: peerdb::Client, mut stream: TcpStream, ) -> Result<()> { let (rx, mut tx) = stream.split(); let result = sync::sync_yield(db, Some(peerdb), rx, &mut tx, Some(p2p::SYNC_IDLE_TIMEOUT)).await; tx.shutdown().await.ok(); result } pub async fn spawn_sync_server( db: &DatabaseServerClient, peerdb: peerdb::Client, listener: TcpListener, ) -> Result { loop { let (stream, src_addr) = listener.accept().await?; debug!("Accepted connection from client: {:?}", src_addr); let mut db = db.clone(); let peerdb = peerdb.clone(); tokio::spawn(async move { if let Err(err) = serve_sync_client(&mut db, peerdb, stream).await { error!("Error while serving client: {err:#}"); } else { debug!("Client disconnected: {src_addr:?}"); } }); } } apt-swarm-0.5.1/src/p2p/update_check.rs000064400000000000000000000021551046102023000160220ustar 00000000000000use crate::args::ContainerUpdateCheck; use crate::errors::*; use crate::p2p; use crate::plumbing::update; use std::convert::Infallible; use tokio::time; pub async fn spawn_update_check(image: String, commit: String) -> Result { let mut interval = time::interval(p2p::UPDATE_CHECK_INTERVAL); debug!("Delaying first update check"); time::sleep(p2p::UPDATE_CHECK_DEBOUNCE).await; let check = ContainerUpdateCheck { image, commit }; loop { interval.tick().await; match update::check(&check).await { Ok(update::Updates::Available { current, latest }) => { warn!( "We're running an outdated version of {:?}, going to shutdown in some minutes... (current={:?}, latest={:?})", check.image, current, latest ); time::sleep(p2p::UPDATE_SHUTDOWN_DELAY).await; bail!("Sending shutdown signal to request container image update"); } Ok(_) => (), Err(err) => { warn!("Update check failed: {err:#}"); } } } } apt-swarm-0.5.1/src/pgp.rs000064400000000000000000000050041046102023000134640ustar 00000000000000use crate::errors::*; use sequoia_openpgp::cert::prelude::*; use sequoia_openpgp::parse::{PacketParser, Parse}; use sequoia_openpgp::policy::NullPolicy; use sequoia_openpgp::{Cert, Fingerprint, KeyHandle, KeyID}; #[derive(Debug, Clone)] pub struct Subkey { pub fingerprint: sequoia_openpgp::Fingerprint, pub is_primary: bool, pub for_authentication: bool, pub for_certification: bool, pub for_signing: bool, pub for_storage_encryption: bool, pub for_transport_encryption: bool, } #[derive(Debug, Clone)] pub struct SigningKey { pub fingerprint: sequoia_openpgp::Fingerprint, pub cert: Cert, pub uids: Vec, pub key_handles: Vec<(KeyHandle, Fingerprint)>, pub subkeys: Vec, } impl SigningKey { pub fn hex_fingerprint(&self) -> String { format!("{:X}", self.fingerprint) } pub fn register_keyhandles(&mut self, fp: Fingerprint) { let keyid = KeyID::from(&fp); self.key_handles.push((KeyHandle::KeyID(keyid), fp.clone())); self.key_handles .push((KeyHandle::Fingerprint(fp.clone()), fp)); } } pub fn load(keyring: &[u8]) -> Result> { let ppr = PacketParser::from_bytes(&keyring)?; let mut out = Vec::new(); for certo in CertParser::from(ppr) { let cert = certo.context("Error reading pgp key")?; let fingerprint = cert.fingerprint(); let mut signing_key = SigningKey { fingerprint, cert: cert.clone(), uids: Vec::new(), key_handles: Vec::new(), subkeys: Vec::new(), }; let p = &NullPolicy::new(); for key in cert.keys().with_policy(p, None) { // TODO: we should probably also track and display encryption-only keys, for transparency if key.for_signing() { signing_key.register_keyhandles(key.fingerprint()); } signing_key.subkeys.push(Subkey { fingerprint: key.fingerprint(), is_primary: key.primary(), for_authentication: key.for_authentication(), for_certification: key.for_certification(), for_signing: key.for_signing(), for_storage_encryption: key.for_storage_encryption(), for_transport_encryption: key.for_transport_encryption(), }); } for ua in cert.userids() { signing_key.uids.push(ua.userid().to_string()); } out.push(signing_key); } Ok(out) } apt-swarm-0.5.1/src/plumbing/git.rs000064400000000000000000000745051046102023000153120ustar 00000000000000use crate::errors::*; use crate::signed::Signed; use bstr::ByteSlice; use gix_object::{CommitRef, WriteTo}; #[derive(Debug, Clone, Copy, clap::ValueEnum)] pub enum Kind { Commit, Tag, } pub fn convert(kind: Option, buf: &[u8]) -> Result { let signed = match kind { Some(Kind::Commit) => { let mut commit = CommitRef::from_bytes(buf).context("Failed to decode as commit")?; let mut signature = None; for (k, v) in &commit.extra_headers { if k.as_bytes() == b"gpgsig" { signature = Some(v.to_vec()); } } let signature = signature.context("Provided commit is not signed")?; commit .extra_headers .retain(|(k, _v)| k.as_bytes() != b"gpgsig"); let mut msg = b"-----BEGIN PGP SIGNED MESSAGE-----\n\n".to_vec(); commit.write_to(&mut msg)?; msg.extend(&signature); msg.push(b'\n'); let (signed, _) = Signed::from_bytes(&msg)?; signed } Some(Kind::Tag) => { // TODO: if we instead search for the start of the signature we could do this more efficiently let mut msg = b"-----BEGIN PGP SIGNED MESSAGE-----\n\n".to_vec(); msg.extend(buf); let (signed, _) = Signed::from_bytes(&msg)?; signed } None => bail!("git objects with loose header are not supported yet"), }; Ok(signed) } #[cfg(test)] mod tests { use super::*; use crate::plumbing::Keyring; fn init() { let _ = env_logger::builder().is_test(true).try_init(); } const KEYRING: &[u8] = b"-----BEGIN PGP PUBLIC KEY BLOCK----- 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 =NtF6 -----END PGP PUBLIC KEY BLOCK----- "; #[test] fn verify_tag() -> Result<()> { init(); let buf = b"object f870ab6864bedcf9e5af137214aa9bc726b8299c type commit tag 20230105 tagger Levente Polyak 1672932047 +0100 Version 20230105 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4kC1fixGMLp2ji8m/BtUfI2BcsgFAmO26s8ACgkQ/BtUfI2B csifzA//czbzHwvxg+HVJwzUmId4rVt452si+7ucOjG0+dRtcE31zL39FgA3jeqK zL0z+G/lI7LoINM5FKrakBwXBcBx5TYDvt41P900NTwH0EqR7ZKePdL/gya8B0HN 6RC7SrdVnY/nkibDOHSGOyMBcf5x815oxgHffo+87Fgoz3pTpZmifEMnFs4Kr7oc C9GMvsBEs8tPztYaBxgXsJ4Sd7ThqqxOa3u82ioiD1K5Wp/RaAaWW3CRpg0RKgg4 pw8HVdNJk1rd42x5K1stSvmdiC6nyZBumaNP3HXMYdkecKRY+Iv5powcQr4kpp61 lwcfTYcwEg5qeWscUlyrOtx0pYh1WHu4rg3HdOy0bwhEwOOIizLzmVArSH43OQRA DwK9gEvsmZspB1j6xQA/gQqeP7ps4VDJ2hW+NVn4AAMDpLvybSBzHCA6/8fO3Z+m vSfPc7oxQ4MFlligyrhXFZAa4rhBb3kUDY15P5TcrX6zTUbQA9BDQrQbuRrj+uEP yLFl/ptRrn+mW+AB80IOD4stu3tTZqKkyV4BMJLou8z2buWN3VN14CbUTGCTUNMW gEZz7HSkX3WmEJKFBRG45hyDfIx9XqaEbJH0SXcmDzZ1uZ55aD40vBQQcHqZoKLj 7f06imt697ReuFR5bMYjkNMlWmMAYR4ERrEIWBQXnCcY3MpiMx0= =Sg65 -----END PGP SIGNATURE----- "; let keyring = Keyring::new(KEYRING)?; let signed = convert(Some(Kind::Tag), buf)?; assert_eq!( signed, Signed { content: "object f870ab6864bedcf9e5af137214aa9bc726b8299c type commit tag 20230105 tagger Levente Polyak 1672932047 +0100 Version 20230105 " .into(), signature: vec![ 137, 2, 51, 4, 0, 1, 10, 0, 29, 22, 33, 4, 226, 64, 181, 126, 44, 70, 48, 186, 118, 142, 47, 38, 252, 27, 84, 124, 141, 129, 114, 200, 5, 2, 99, 182, 234, 207, 0, 10, 9, 16, 252, 27, 84, 124, 141, 129, 114, 200, 159, 204, 15, 255, 115, 54, 243, 31, 11, 241, 131, 225, 213, 39, 12, 212, 152, 135, 120, 173, 91, 120, 231, 107, 34, 251, 187, 156, 58, 49, 180, 249, 212, 109, 112, 77, 245, 204, 189, 253, 22, 0, 55, 141, 234, 138, 204, 189, 51, 248, 111, 229, 35, 178, 232, 32, 211, 57, 20, 170, 218, 144, 28, 23, 5, 192, 113, 229, 54, 3, 190, 222, 53, 63, 221, 52, 53, 60, 7, 208, 74, 145, 237, 146, 158, 61, 210, 255, 131, 38, 188, 7, 65, 205, 233, 16, 187, 74, 183, 85, 157, 143, 231, 146, 38, 195, 56, 116, 134, 59, 35, 1, 113, 254, 113, 243, 94, 104, 198, 1, 223, 126, 143, 188, 236, 88, 40, 207, 122, 83, 165, 153, 162, 124, 67, 39, 22, 206, 10, 175, 186, 28, 11, 209, 140, 190, 192, 68, 179, 203, 79, 206, 214, 26, 7, 24, 23, 176, 158, 18, 119, 180, 225, 170, 172, 78, 107, 123, 188, 218, 42, 34, 15, 82, 185, 90, 159, 209, 104, 6, 150, 91, 112, 145, 166, 13, 17, 42, 8, 56, 167, 15, 7, 85, 211, 73, 147, 90, 221, 227, 108, 121, 43, 91, 45, 74, 249, 157, 136, 46, 167, 201, 144, 110, 153, 163, 79, 220, 117, 204, 97, 217, 30, 112, 164, 88, 248, 139, 249, 166, 140, 28, 66, 190, 36, 166, 158, 181, 151, 7, 31, 77, 135, 48, 18, 14, 106, 121, 107, 28, 82, 92, 171, 58, 220, 116, 165, 136, 117, 88, 123, 184, 174, 13, 199, 116, 236, 180, 111, 8, 68, 192, 227, 136, 139, 50, 243, 153, 80, 43, 72, 126, 55, 57, 4, 64, 15, 2, 189, 128, 75, 236, 153, 155, 41, 7, 88, 250, 197, 0, 63, 129, 10, 158, 63, 186, 108, 225, 80, 201, 218, 21, 190, 53, 89, 248, 0, 3, 3, 164, 187, 242, 109, 32, 115, 28, 32, 58, 255, 199, 206, 221, 159, 166, 189, 39, 207, 115, 186, 49, 67, 131, 5, 150, 88, 160, 202, 184, 87, 21, 144, 26, 226, 184, 65, 111, 121, 20, 13, 141, 121, 63, 148, 220, 173, 126, 179, 77, 70, 208, 3, 208, 67, 66, 180, 27, 185, 26, 227, 250, 225, 15, 200, 177, 101, 254, 155, 81, 174, 127, 166, 91, 224, 1, 243, 66, 14, 15, 139, 45, 187, 123, 83, 102, 162, 164, 201, 94, 1, 48, 146, 232, 187, 204, 246, 110, 229, 141, 221, 83, 117, 224, 38, 212, 76, 96, 147, 80, 211, 22, 128, 70, 115, 236, 116, 164, 95, 117, 166, 16, 146, 133, 5, 17, 184, 230, 28, 131, 124, 140, 125, 94, 166, 132, 108, 145, 244, 73, 119, 38, 15, 54, 117, 185, 158, 121, 104, 62, 52, 188, 20, 16, 112, 122, 153, 160, 162, 227, 237, 253, 58, 138, 107, 122, 247, 180, 94, 184, 84, 121, 108, 198, 35, 144, 211, 37, 90, 99, 0, 97, 30, 4, 70, 177, 8, 88, 20, 23, 156, 39, 24, 220, 202, 98, 51, 29 ] } ); let canonical = signed.canonicalize(Some(&keyring))?; assert_eq!( canonical, vec![( Some("E240B57E2C4630BA768E2F26FC1B547C8D8172C8".parse()?), Signed { content: "object f870ab6864bedcf9e5af137214aa9bc726b8299c type commit tag 20230105 tagger Levente Polyak 1672932047 +0100 Version 20230105 " .into(), signature: vec![ 194, 193, 115, 4, 0, 1, 10, 0, 29, 22, 33, 4, 226, 64, 181, 126, 44, 70, 48, 186, 118, 142, 47, 38, 252, 27, 84, 124, 141, 129, 114, 200, 5, 2, 99, 182, 234, 207, 0, 10, 9, 16, 252, 27, 84, 124, 141, 129, 114, 200, 159, 204, 15, 255, 115, 54, 243, 31, 11, 241, 131, 225, 213, 39, 12, 212, 152, 135, 120, 173, 91, 120, 231, 107, 34, 251, 187, 156, 58, 49, 180, 249, 212, 109, 112, 77, 245, 204, 189, 253, 22, 0, 55, 141, 234, 138, 204, 189, 51, 248, 111, 229, 35, 178, 232, 32, 211, 57, 20, 170, 218, 144, 28, 23, 5, 192, 113, 229, 54, 3, 190, 222, 53, 63, 221, 52, 53, 60, 7, 208, 74, 145, 237, 146, 158, 61, 210, 255, 131, 38, 188, 7, 65, 205, 233, 16, 187, 74, 183, 85, 157, 143, 231, 146, 38, 195, 56, 116, 134, 59, 35, 1, 113, 254, 113, 243, 94, 104, 198, 1, 223, 126, 143, 188, 236, 88, 40, 207, 122, 83, 165, 153, 162, 124, 67, 39, 22, 206, 10, 175, 186, 28, 11, 209, 140, 190, 192, 68, 179, 203, 79, 206, 214, 26, 7, 24, 23, 176, 158, 18, 119, 180, 225, 170, 172, 78, 107, 123, 188, 218, 42, 34, 15, 82, 185, 90, 159, 209, 104, 6, 150, 91, 112, 145, 166, 13, 17, 42, 8, 56, 167, 15, 7, 85, 211, 73, 147, 90, 221, 227, 108, 121, 43, 91, 45, 74, 249, 157, 136, 46, 167, 201, 144, 110, 153, 163, 79, 220, 117, 204, 97, 217, 30, 112, 164, 88, 248, 139, 249, 166, 140, 28, 66, 190, 36, 166, 158, 181, 151, 7, 31, 77, 135, 48, 18, 14, 106, 121, 107, 28, 82, 92, 171, 58, 220, 116, 165, 136, 117, 88, 123, 184, 174, 13, 199, 116, 236, 180, 111, 8, 68, 192, 227, 136, 139, 50, 243, 153, 80, 43, 72, 126, 55, 57, 4, 64, 15, 2, 189, 128, 75, 236, 153, 155, 41, 7, 88, 250, 197, 0, 63, 129, 10, 158, 63, 186, 108, 225, 80, 201, 218, 21, 190, 53, 89, 248, 0, 3, 3, 164, 187, 242, 109, 32, 115, 28, 32, 58, 255, 199, 206, 221, 159, 166, 189, 39, 207, 115, 186, 49, 67, 131, 5, 150, 88, 160, 202, 184, 87, 21, 144, 26, 226, 184, 65, 111, 121, 20, 13, 141, 121, 63, 148, 220, 173, 126, 179, 77, 70, 208, 3, 208, 67, 66, 180, 27, 185, 26, 227, 250, 225, 15, 200, 177, 101, 254, 155, 81, 174, 127, 166, 91, 224, 1, 243, 66, 14, 15, 139, 45, 187, 123, 83, 102, 162, 164, 201, 94, 1, 48, 146, 232, 187, 204, 246, 110, 229, 141, 221, 83, 117, 224, 38, 212, 76, 96, 147, 80, 211, 22, 128, 70, 115, 236, 116, 164, 95, 117, 166, 16, 146, 133, 5, 17, 184, 230, 28, 131, 124, 140, 125, 94, 166, 132, 108, 145, 244, 73, 119, 38, 15, 54, 117, 185, 158, 121, 104, 62, 52, 188, 20, 16, 112, 122, 153, 160, 162, 227, 237, 253, 58, 138, 107, 122, 247, 180, 94, 184, 84, 121, 108, 198, 35, 144, 211, 37, 90, 99, 0, 97, 30, 4, 70, 177, 8, 88, 20, 23, 156, 39, 24, 220, 202, 98, 51, 29 ] } )] ); Ok(()) } #[test] fn verify_commit() -> Result<()> { init(); let buf = b"tree 1b99d17009234a86e65e830c7a7ae6f7d182b8ef parent d45e77738bda2d17b10f87d05167a12fa5be8d63 author Levente Polyak 1673558348 +0100 committer Levente Polyak 1673912904 +0100 gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4kC1fixGMLp2ji8m/BtUfI2BcsgFAmPF4koACgkQ/BtUfI2B csjt2g//f4DDzb+z8MoMP9UfLCXy3nTstCxdlIiQQtPz7t9WPhxNxjKZai32UQzW 4SBlwzErlugnOe0wkZb2olD7X/+/ffKO/s/b32rqxumjzrzpqSXHrrqo9XoL3Aut dXrgQ0X+hDRGcwbJS6iT05zJuYV9XXxgY+IKrJPQKveiTNYXS9M04b/kxHPvM4Vl gdCAxXKsjSdBxFepepI1vHEZOziEtT/3cB+7Rm2l93AyRuSPG01DZ48xKbIvpsEs Pt2X16cQTe0d0OORBVnnRXjhx9CI1QE5+H4ZUm94CW64GOoOtYQV74mtzJMZjuvN exdaWciOG/5Jq1QrIWvT4uRCl1mc3+rtjj/S9SPelZb24HqakoCCQE6xf1UAu5F8 cN+8AyeENizh5xanueiAVwnRKzc07+VzKbKjR5nA4UWaTs6tNMLII6+LPnLnn2Du ZUCWEg972TevQ5u9AlkJkUI6JqkucBYc0IQZ8r6A7gg4YrLhbElpC5MY3F/EozGY T1jbwndZ/BQFSauImU75eU/JqRTnVi2K+gTXo78U7QaJZuUhhnPxjlbwm4Pgva7X cO5e9ZEVYT8PxgT2CrbBmNFDAu3SH87ONiuJR3OibNsjCikTpUIdgcNK8E4A15JR M3Qw+dOJUEDzhvDkzFYQ87Liz8ITX7cFgpx9OnkBgVjWi6zl+uo= =YZzN -----END PGP SIGNATURE----- commitpkg: abort execution if msg file editor exits none-successfully Previously the script execution did not abort if the msg file editor exited none-successfully leading to undesired commits with a potentially unfinished message. Instead abort the commit if the msg file editor is deliberately terminated with a failure code. Signed-off-by: Levente Polyak "; let keyring = Keyring::new(KEYRING)?; let signed = convert(Some(Kind::Commit), buf)?; assert_eq!( signed, Signed { content: "tree 1b99d17009234a86e65e830c7a7ae6f7d182b8ef parent d45e77738bda2d17b10f87d05167a12fa5be8d63 author Levente Polyak 1673558348 +0100 committer Levente Polyak 1673912904 +0100 commitpkg: abort execution if msg file editor exits none-successfully Previously the script execution did not abort if the msg file editor exited none-successfully leading to undesired commits with a potentially unfinished message. Instead abort the commit if the msg file editor is deliberately terminated with a failure code. Signed-off-by: Levente Polyak " .into(), signature: vec![ 137, 2, 51, 4, 0, 1, 10, 0, 29, 22, 33, 4, 226, 64, 181, 126, 44, 70, 48, 186, 118, 142, 47, 38, 252, 27, 84, 124, 141, 129, 114, 200, 5, 2, 99, 197, 226, 74, 0, 10, 9, 16, 252, 27, 84, 124, 141, 129, 114, 200, 237, 218, 15, 255, 127, 128, 195, 205, 191, 179, 240, 202, 12, 63, 213, 31, 44, 37, 242, 222, 116, 236, 180, 44, 93, 148, 136, 144, 66, 211, 243, 238, 223, 86, 62, 28, 77, 198, 50, 153, 106, 45, 246, 81, 12, 214, 225, 32, 101, 195, 49, 43, 150, 232, 39, 57, 237, 48, 145, 150, 246, 162, 80, 251, 95, 255, 191, 125, 242, 142, 254, 207, 219, 223, 106, 234, 198, 233, 163, 206, 188, 233, 169, 37, 199, 174, 186, 168, 245, 122, 11, 220, 11, 173, 117, 122, 224, 67, 69, 254, 132, 52, 70, 115, 6, 201, 75, 168, 147, 211, 156, 201, 185, 133, 125, 93, 124, 96, 99, 226, 10, 172, 147, 208, 42, 247, 162, 76, 214, 23, 75, 211, 52, 225, 191, 228, 196, 115, 239, 51, 133, 101, 129, 208, 128, 197, 114, 172, 141, 39, 65, 196, 87, 169, 122, 146, 53, 188, 113, 25, 59, 56, 132, 181, 63, 247, 112, 31, 187, 70, 109, 165, 247, 112, 50, 70, 228, 143, 27, 77, 67, 103, 143, 49, 41, 178, 47, 166, 193, 44, 62, 221, 151, 215, 167, 16, 77, 237, 29, 208, 227, 145, 5, 89, 231, 69, 120, 225, 199, 208, 136, 213, 1, 57, 248, 126, 25, 82, 111, 120, 9, 110, 184, 24, 234, 14, 181, 132, 21, 239, 137, 173, 204, 147, 25, 142, 235, 205, 123, 23, 90, 89, 200, 142, 27, 254, 73, 171, 84, 43, 33, 107, 211, 226, 228, 66, 151, 89, 156, 223, 234, 237, 142, 63, 210, 245, 35, 222, 149, 150, 246, 224, 122, 154, 146, 128, 130, 64, 78, 177, 127, 85, 0, 187, 145, 124, 112, 223, 188, 3, 39, 132, 54, 44, 225, 231, 22, 167, 185, 232, 128, 87, 9, 209, 43, 55, 52, 239, 229, 115, 41, 178, 163, 71, 153, 192, 225, 69, 154, 78, 206, 173, 52, 194, 200, 35, 175, 139, 62, 114, 231, 159, 96, 238, 101, 64, 150, 18, 15, 123, 217, 55, 175, 67, 155, 189, 2, 89, 9, 145, 66, 58, 38, 169, 46, 112, 22, 28, 208, 132, 25, 242, 190, 128, 238, 8, 56, 98, 178, 225, 108, 73, 105, 11, 147, 24, 220, 95, 196, 163, 49, 152, 79, 88, 219, 194, 119, 89, 252, 20, 5, 73, 171, 136, 153, 78, 249, 121, 79, 201, 169, 20, 231, 86, 45, 138, 250, 4, 215, 163, 191, 20, 237, 6, 137, 102, 229, 33, 134, 115, 241, 142, 86, 240, 155, 131, 224, 189, 174, 215, 112, 238, 94, 245, 145, 21, 97, 63, 15, 198, 4, 246, 10, 182, 193, 152, 209, 67, 2, 237, 210, 31, 206, 206, 54, 43, 137, 71, 115, 162, 108, 219, 35, 10, 41, 19, 165, 66, 29, 129, 195, 74, 240, 78, 0, 215, 146, 81, 51, 116, 48, 249, 211, 137, 80, 64, 243, 134, 240, 228, 204, 86, 16, 243, 178, 226, 207, 194, 19, 95, 183, 5, 130, 156, 125, 58, 121, 1, 129, 88, 214, 139, 172, 229, 250, 234 ] } ); let canonical = signed.canonicalize(Some(&keyring))?; assert_eq!( canonical, vec![( Some("E240B57E2C4630BA768E2F26FC1B547C8D8172C8".parse()?), Signed { content: "tree 1b99d17009234a86e65e830c7a7ae6f7d182b8ef parent d45e77738bda2d17b10f87d05167a12fa5be8d63 author Levente Polyak 1673558348 +0100 committer Levente Polyak 1673912904 +0100 commitpkg: abort execution if msg file editor exits none-successfully Previously the script execution did not abort if the msg file editor exited none-successfully leading to undesired commits with a potentially unfinished message. Instead abort the commit if the msg file editor is deliberately terminated with a failure code. Signed-off-by: Levente Polyak " .into(), signature: vec![ 194, 193, 115, 4, 0, 1, 10, 0, 29, 22, 33, 4, 226, 64, 181, 126, 44, 70, 48, 186, 118, 142, 47, 38, 252, 27, 84, 124, 141, 129, 114, 200, 5, 2, 99, 197, 226, 74, 0, 10, 9, 16, 252, 27, 84, 124, 141, 129, 114, 200, 237, 218, 15, 255, 127, 128, 195, 205, 191, 179, 240, 202, 12, 63, 213, 31, 44, 37, 242, 222, 116, 236, 180, 44, 93, 148, 136, 144, 66, 211, 243, 238, 223, 86, 62, 28, 77, 198, 50, 153, 106, 45, 246, 81, 12, 214, 225, 32, 101, 195, 49, 43, 150, 232, 39, 57, 237, 48, 145, 150, 246, 162, 80, 251, 95, 255, 191, 125, 242, 142, 254, 207, 219, 223, 106, 234, 198, 233, 163, 206, 188, 233, 169, 37, 199, 174, 186, 168, 245, 122, 11, 220, 11, 173, 117, 122, 224, 67, 69, 254, 132, 52, 70, 115, 6, 201, 75, 168, 147, 211, 156, 201, 185, 133, 125, 93, 124, 96, 99, 226, 10, 172, 147, 208, 42, 247, 162, 76, 214, 23, 75, 211, 52, 225, 191, 228, 196, 115, 239, 51, 133, 101, 129, 208, 128, 197, 114, 172, 141, 39, 65, 196, 87, 169, 122, 146, 53, 188, 113, 25, 59, 56, 132, 181, 63, 247, 112, 31, 187, 70, 109, 165, 247, 112, 50, 70, 228, 143, 27, 77, 67, 103, 143, 49, 41, 178, 47, 166, 193, 44, 62, 221, 151, 215, 167, 16, 77, 237, 29, 208, 227, 145, 5, 89, 231, 69, 120, 225, 199, 208, 136, 213, 1, 57, 248, 126, 25, 82, 111, 120, 9, 110, 184, 24, 234, 14, 181, 132, 21, 239, 137, 173, 204, 147, 25, 142, 235, 205, 123, 23, 90, 89, 200, 142, 27, 254, 73, 171, 84, 43, 33, 107, 211, 226, 228, 66, 151, 89, 156, 223, 234, 237, 142, 63, 210, 245, 35, 222, 149, 150, 246, 224, 122, 154, 146, 128, 130, 64, 78, 177, 127, 85, 0, 187, 145, 124, 112, 223, 188, 3, 39, 132, 54, 44, 225, 231, 22, 167, 185, 232, 128, 87, 9, 209, 43, 55, 52, 239, 229, 115, 41, 178, 163, 71, 153, 192, 225, 69, 154, 78, 206, 173, 52, 194, 200, 35, 175, 139, 62, 114, 231, 159, 96, 238, 101, 64, 150, 18, 15, 123, 217, 55, 175, 67, 155, 189, 2, 89, 9, 145, 66, 58, 38, 169, 46, 112, 22, 28, 208, 132, 25, 242, 190, 128, 238, 8, 56, 98, 178, 225, 108, 73, 105, 11, 147, 24, 220, 95, 196, 163, 49, 152, 79, 88, 219, 194, 119, 89, 252, 20, 5, 73, 171, 136, 153, 78, 249, 121, 79, 201, 169, 20, 231, 86, 45, 138, 250, 4, 215, 163, 191, 20, 237, 6, 137, 102, 229, 33, 134, 115, 241, 142, 86, 240, 155, 131, 224, 189, 174, 215, 112, 238, 94, 245, 145, 21, 97, 63, 15, 198, 4, 246, 10, 182, 193, 152, 209, 67, 2, 237, 210, 31, 206, 206, 54, 43, 137, 71, 115, 162, 108, 219, 35, 10, 41, 19, 165, 66, 29, 129, 195, 74, 240, 78, 0, 215, 146, 81, 51, 116, 48, 249, 211, 137, 80, 64, 243, 134, 240, 228, 204, 86, 16, 243, 178, 226, 207, 194, 19, 95, 183, 5, 130, 156, 125, 58, 121, 1, 129, 88, 214, 139, 172, 229, 250, 234 ] } )] ); Ok(()) } #[test] fn detect_modified_tag() -> Result<()> { init(); let buf = b"this is tampered -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4kC1fixGMLp2ji8m/BtUfI2BcsgFAmO26s8ACgkQ/BtUfI2B csifzA//czbzHwvxg+HVJwzUmId4rVt452si+7ucOjG0+dRtcE31zL39FgA3jeqK zL0z+G/lI7LoINM5FKrakBwXBcBx5TYDvt41P900NTwH0EqR7ZKePdL/gya8B0HN 6RC7SrdVnY/nkibDOHSGOyMBcf5x815oxgHffo+87Fgoz3pTpZmifEMnFs4Kr7oc C9GMvsBEs8tPztYaBxgXsJ4Sd7ThqqxOa3u82ioiD1K5Wp/RaAaWW3CRpg0RKgg4 pw8HVdNJk1rd42x5K1stSvmdiC6nyZBumaNP3HXMYdkecKRY+Iv5powcQr4kpp61 lwcfTYcwEg5qeWscUlyrOtx0pYh1WHu4rg3HdOy0bwhEwOOIizLzmVArSH43OQRA DwK9gEvsmZspB1j6xQA/gQqeP7ps4VDJ2hW+NVn4AAMDpLvybSBzHCA6/8fO3Z+m vSfPc7oxQ4MFlligyrhXFZAa4rhBb3kUDY15P5TcrX6zTUbQA9BDQrQbuRrj+uEP yLFl/ptRrn+mW+AB80IOD4stu3tTZqKkyV4BMJLou8z2buWN3VN14CbUTGCTUNMW gEZz7HSkX3WmEJKFBRG45hyDfIx9XqaEbJH0SXcmDzZ1uZ55aD40vBQQcHqZoKLj 7f06imt697ReuFR5bMYjkNMlWmMAYR4ERrEIWBQXnCcY3MpiMx0= =Sg65 -----END PGP SIGNATURE----- "; let keyring = Keyring::new(KEYRING)?; let signed = convert(Some(Kind::Tag), buf)?; let canonical = signed.canonicalize(None)?; assert_eq!(canonical.len(), 1); let signed = convert(Some(Kind::Tag), buf)?; let canonical = signed.canonicalize(Some(&keyring))?; assert_eq!(canonical.len(), 0); Ok(()) } #[test] fn detect_modified_commit() -> Result<()> { init(); let buf = b"tree ffffffffffffffffffffffffffffffffffffffff parent eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee author Levente Polyak 1673558348 +0100 committer Levente Polyak 1673912904 +0100 gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4kC1fixGMLp2ji8m/BtUfI2BcsgFAmPF4koACgkQ/BtUfI2B csjt2g//f4DDzb+z8MoMP9UfLCXy3nTstCxdlIiQQtPz7t9WPhxNxjKZai32UQzW 4SBlwzErlugnOe0wkZb2olD7X/+/ffKO/s/b32rqxumjzrzpqSXHrrqo9XoL3Aut dXrgQ0X+hDRGcwbJS6iT05zJuYV9XXxgY+IKrJPQKveiTNYXS9M04b/kxHPvM4Vl gdCAxXKsjSdBxFepepI1vHEZOziEtT/3cB+7Rm2l93AyRuSPG01DZ48xKbIvpsEs Pt2X16cQTe0d0OORBVnnRXjhx9CI1QE5+H4ZUm94CW64GOoOtYQV74mtzJMZjuvN exdaWciOG/5Jq1QrIWvT4uRCl1mc3+rtjj/S9SPelZb24HqakoCCQE6xf1UAu5F8 cN+8AyeENizh5xanueiAVwnRKzc07+VzKbKjR5nA4UWaTs6tNMLII6+LPnLnn2Du ZUCWEg972TevQ5u9AlkJkUI6JqkucBYc0IQZ8r6A7gg4YrLhbElpC5MY3F/EozGY T1jbwndZ/BQFSauImU75eU/JqRTnVi2K+gTXo78U7QaJZuUhhnPxjlbwm4Pgva7X cO5e9ZEVYT8PxgT2CrbBmNFDAu3SH87ONiuJR3OibNsjCikTpUIdgcNK8E4A15JR M3Qw+dOJUEDzhvDkzFYQ87Liz8ITX7cFgpx9OnkBgVjWi6zl+uo= =YZzN -----END PGP SIGNATURE----- this is tampered "; let keyring = Keyring::new(KEYRING)?; let signed = convert(Some(Kind::Commit), buf)?; let canonical = signed.canonicalize(None)?; assert_eq!(canonical.len(), 1); let signed = convert(Some(Kind::Commit), buf)?; let canonical = signed.canonicalize(Some(&keyring))?; assert_eq!(canonical.len(), 0); Ok(()) } } apt-swarm-0.5.1/src/plumbing/mod.rs000064400000000000000000000440551046102023000153030ustar 00000000000000#[cfg(feature = "git")] pub mod git; pub mod update; use crate::args::{FileOrStdin, Plumbing}; use crate::config::Config; #[cfg(unix)] use crate::db::channel::DatabaseServer; use crate::db::header::CryptoHash; use crate::db::{AccessMode, Database, DatabaseClient}; use crate::errors::*; use crate::fetch; use crate::keyring::Keyring; use crate::p2p; use crate::p2p::peerdb::{self, PeerDb}; use crate::pgp; use crate::signed::Signed; use crate::sync; use bstr::{BStr, BString}; use chrono::Utc; use colored::Colorize; use futures::StreamExt; use std::borrow::Cow; use std::net::SocketAddr; use std::sync::LazyLock; use tokio::fs; use tokio::io::{self, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt}; use tokio::task::JoinSet; static FSCK_OK: LazyLock = LazyLock::new(|| " OK\n".bold().green().to_string()); static FSCK_ERR: LazyLock = LazyLock::new(|| " ERR\n".bold().red().to_string()); async fn fsck_doc(hash: &[u8], data: &[u8], keyring: Option<&Keyring>) -> Result<()> { let signed = Signed::from_reader(&mut &data[..]) .await .context("Failed to parse release file")?; let canonicalized = signed.canonicalize(keyring)?; let mut canonicalized = canonicalized.into_iter(); match canonicalized.next() { Some((Some(fp), variant)) => { let keyspace = format!("{fp:X}/"); let Some(hash) = hash.strip_prefix(keyspace.as_bytes()) else { bail!( "Signature is stored in incorrect fingerprint keyspace, expected: {keyspace}" ); }; let normalized = variant.to_clear_signed()?; if normalized != data { bail!("Data is not correctly canonicalized, byte mismatch"); } let verified = CryptoHash::calculate(&normalized); if verified.as_str().as_bytes() != hash { bail!("Incorrect sha256, calculated: {:?}", verified.as_str()); } } Some((None, _variant)) => { bail!("Signature can't be validated because the key is not in keyring"); } None => { bail!("Could not find any signature packet"); } } if let Some(_trailing) = canonicalized.next() { bail!("Document is not fully canonicalized, has multiple signatures"); } Ok(()) } pub async fn run( config: Result, args: Plumbing, quiet: u8, proxy: Option, ) -> Result<()> { match args { Plumbing::Canonicalize(mut canonicalize) => { FileOrStdin::default_stdin(&mut canonicalize.paths); let keyring = if canonicalize.verify { let config = config?; Some(Keyring::load(&config)?) } else { None }; let mut stdout = io::stdout(); for path in canonicalize.paths { let reader = path.open().await?; let mut reader = io::BufReader::new(reader); while !reader.fill_buf().await?.is_empty() { let signed = Signed::from_reader(&mut reader) .await .context("Failed to parse release file")?; for (_fp, variant) in signed.canonicalize(keyring.as_ref())? { let text = variant.to_clear_signed()?; stdout.write_all(&text).await?; } } } // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } Plumbing::Fetch(fetch) => { let client = fetch::client(proxy)?; debug!("Fetching url: {:?}", fetch.url); let response = client.get(fetch.url).send().await?; debug!("Received response: {response:?}"); let mut stream = response.error_for_status()?.bytes_stream(); let mut stdout = io::stdout(); while let Some(item) = stream.next().await { stdout.write_all(&item?).await?; } // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } Plumbing::Fingerprint(_fingerprint) => { let mut buf = Vec::new(); let mut stdin = io::stdin(); stdin.read_to_end(&mut buf).await?; pgp::load(&buf)?; } Plumbing::Paths(_paths) => { let config = config?; let config_path = if let Some(path) = &config.config_path { Cow::Owned(format!("{:?}", path)) } else { Cow::Borrowed("-") }; println!("config path: {}", config_path); println!("database path: {:?}", config.database_path()?); } Plumbing::Config(_config) => { let config = config?; let config = serde_json::to_string_pretty(&config.data)?; println!("{config}"); } Plumbing::Index(query) => { let config = config?; let mut db = Database::open(&config, AccessMode::Relaxed).await?; let mut q = sync::TreeQuery { fp: query.fingerprint, hash_algo: query.hash_algo, prefix: query.prefix, }; if query.batch { let (index, _) = db.batch_index_from_scan(&mut q).await?; let mut stdout = io::stdout(); index.write_to(&mut stdout).await?; // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } else { let (index, counter) = db.index_from_scan(&q).await?; println!("{index} {counter}"); } } Plumbing::SyncYield(sync_yield) => { let config = config?; let mut db = Database::open(&config, AccessMode::Relaxed).await?; let mut set = JoinSet::new(); let peerdb = if sync_yield.pex { let peerdb = PeerDb::read(&config).await?; let (peerdb_tx, peerdb_rx) = peerdb::Client::new(); set.spawn(async move { peerdb::spawn(peerdb, peerdb_rx) .await .context("Peerdb thread has crashed")?; Ok(()) }); Some(peerdb_tx) } else { None }; set.spawn(async move { sync::sync_yield(&mut db, peerdb, io::stdin(), &mut io::stdout(), None) .await .context("Error during sync yield") }); match set.join_next().await { Some(Ok(res)) => res?, Some(Err(err)) => bail!("Thread has crashed: {err:?}"), None => (), } } Plumbing::SyncPull(sync_pull) => { let config = config?; let keyring = Keyring::load(&config)?; let mut db = Database::open(&config, AccessMode::Exclusive).await?; sync::sync_pull( &mut db, &keyring, &sync_pull.keys, sync_pull.dry_run, io::stdout(), io::stdin(), ) .await?; } Plumbing::ContainerUpdateCheck(update) => match update::check(&update).await? { update::Updates::AlreadyLatest { commit } => { info!( "We're running the latest version of {:?} (commit={:?})", update.image, commit ); } update::Updates::Available { current, latest } => { info!( "We're running an outdated version of {:?} (current={:?}, latest={:?})", update.image, current, latest ); } }, #[cfg(feature = "git")] Plumbing::GitObject(git) => { for path in &git.paths { let mut buf = Vec::new(); let mut reader = path.open().await?; reader.read_to_end(&mut buf).await?; let signed = git::convert(git.kind, &buf)?; let normalized = signed.to_clear_signed()?; let mut stdout = io::stdout(); stdout.write_all(&normalized).await?; // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } } #[cfg(feature = "git")] Plumbing::GitScrape(git) => { use gix::object::Kind; let mut stdout = io::stdout(); for path in git.paths { info!("Opening git repository: {:?}", path); let repo = gix::open(&path) .with_context(|| anyhow!("Failed to open git repo: {:?}", path))?; for obj in repo.objects.iter()? { let obj = obj.context("Failed to read git object list")?; trace!("Accessing git object: {}", obj); let obj = repo .find_object(obj) .context("Failed to access git object")?; let Ok(signed) = (match obj.kind { Kind::Commit => { trace!("Found git commit: {:?}", obj); git::convert(Some(git::Kind::Commit), &obj.data) } Kind::Tag => { trace!("Found git tag: {:?}", obj); git::convert(Some(git::Kind::Tag), &obj.data) } _ => continue, }) else { continue; }; debug!("Found signed git object: {:?}", obj.id); let normalized = signed.to_clear_signed()?; stdout.write_all(&normalized).await?; } } // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } Plumbing::AttachSig(attach) => { let content = fs::read(&attach.content).await.with_context(|| { anyhow!("Failed to read content from file: {:?}", attach.content) })?; let content = BString::new(content); for sig_path in &attach.signatures { let signature = fs::read(&sig_path).await.with_context(|| { anyhow!("Failed to read signature from file: {:?}", sig_path) })?; let signed = Signed { content: content.clone(), signature, }; let mut stdout = io::stdout(); let text = signed.to_clear_signed()?; stdout.write_all(&text).await?; // https://github.com/tokio-rs/tokio/issues/7174 stdout.flush().await?; } } Plumbing::DnsBootstrap(bootstrap) => { for dns in bootstrap.dns { for addr in p2p::dns::resolve(&dns).await? { if bootstrap.ipv4_only && !addr.is_ipv4() { continue; } if bootstrap.ipv6_only && !addr.is_ipv6() { continue; } println!("{addr}"); } } } #[cfg(unix)] Plumbing::DbServer(_server) => { let config = config?; let db = Database::open_directly(&config, AccessMode::Exclusive).await?; let (mut db_server, db_client) = DatabaseServer::new(db); let db_socket_path = config.db_socket_path()?; tokio::select! { _ = db_server.run() => bail!("Database server has terminated"), ret = p2p::db::spawn_unix_db_server(&db_client, db_socket_path) => ret, }?; } Plumbing::PeerdbAdd(add) => { let config = config?; let mut db = p2p::peerdb::PeerDb::read(&config).await?; for peer in add.addrs { let (_entry, new) = db.add_peer(peer.clone()); if new { info!("Added new peer to peerdb: {peer:?}"); } else { debug!("Peer already in peerdb: {peer:?}"); } } db.write().await?; } Plumbing::PeerdbList(list) => { let config = config?; let db = p2p::peerdb::PeerDb::read(&config).await?; for (addr, stats) in db.peers() { if !list.filters.is_empty() && !list.filters.iter().any(|filter| filter.matches(addr)) { trace!("PeerAddr does not match filter: {addr:?}"); continue; } if quiet == 0 { println!("{}", addr.to_string().bold()); println!( " {} {}", "connect: ".green(), stats.connect.format_stats() ); println!( " {} {}", "handshake: ".green(), stats.handshake.format_stats() ); println!( " {} {}", "advertised:".green(), p2p::peerdb::format_time_opt(stats.last_advertised).yellow() ); } else { println!("{addr}"); } } } Plumbing::PeerdbGc(_gc) => { let config = config?; let mut db = p2p::peerdb::PeerDb::read(&config).await?; if db.expire_old_peers(Utc::now()) { db.write().await?; } } Plumbing::Migrate(_migrate) => { let config = config?; let keyring = Keyring::load(&config)?; let new_path = config.database_path()?; let migrate_path = config.database_migrate_path()?; let delete_path = config.database_delete_path()?; for path in [&migrate_path, &delete_path] { if fs::metadata(&path).await.is_ok() { warn!("Previous migration has failed, removing {path:?}..."); fs::remove_dir_all(&path).await.with_context(|| { anyhow!("Failed to delete failed migration at {path:?}") })?; } } info!("Moving database from {new_path:?} to {migrate_path:?}..."); fs::rename(&new_path, &migrate_path) .await .with_context(|| { anyhow!("Failed to rename directory from {new_path:?} to {migrate_path:?}") })?; { let mut new_db = Database::open_at(new_path, AccessMode::Exclusive).await?; let migrate_db = Database::open_at(migrate_path.clone(), AccessMode::Exclusive).await?; let stream = migrate_db.scan_values(&[]); tokio::pin!(stream); while let Some(item) = stream.next().await { let (_key, value) = item?; let (signed, _remaining) = Signed::from_bytes(&value).context("Failed to parse release file")?; for (fp, variant) in signed.canonicalize(Some(&keyring))? { let fp = fp.context( "Signature can't be imported because the signature is unverified", )?; new_db.add_release(&fp, &variant).await?; } } } info!("Moving database from {migrate_path:?} to {delete_path:?} for deletion..."); fs::rename(&migrate_path, &delete_path) .await .with_context(|| { anyhow!("Failed to rename directory from {migrate_path:?} to {delete_path:?}") })?; info!("Migration completed, removing migration folder..."); fs::remove_dir_all(&delete_path).await?; } Plumbing::Fsck(fsck) => { let config = config?; let keyring = Some(Keyring::load(&config)?); let db = Database::open_directly(&config, AccessMode::Relaxed).await?; let prefix = if let Some(prefix) = &fsck.prefix { prefix.as_bytes() } else { &[] }; let mut errors = vec![]; let mut stdout = io::stdout(); let stream = db.scan_values(prefix); tokio::pin!(stream); while let Some(item) = stream.next().await { let (hash, data) = item.context("Failed to read from database (fsck)")?; if quiet == 0 { stdout.write_all(&hash).await?; stdout.write_all(b"... ").await?; stdout.flush().await?; } match fsck_doc(&hash, &data, keyring.as_ref()).await { Ok(_) => { if quiet == 0 { stdout.write_all(FSCK_OK.as_bytes()).await?; stdout.flush().await?; } } Err(err) => { if quiet == 0 { stdout.write_all(FSCK_ERR.as_bytes()).await?; stdout.flush().await?; } error!("{}: {:#}", BStr::new(&hash), err); errors.push((hash, err)); } } } if !errors.is_empty() { for (hash, err) in &errors { println!("{}: {:#}", BStr::new(&hash), err); } bail!("Fsck failed ({} errors occured)", errors.len()); } } Plumbing::Completions(completions) => completions.generate()?, } Ok(()) } apt-swarm-0.5.1/src/plumbing/update.rs000064400000000000000000000047341046102023000160060ustar 00000000000000use crate::args::ContainerUpdateCheck; use crate::errors::*; use serde::{Deserialize, Serialize}; use tokio::process::Command; #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct CraneOutput { pub config: ContainerConfig, } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct ContainerConfig { #[serde(rename = "Env")] pub env: Vec, } pub enum Updates { Available { current: String, latest: String }, AlreadyLatest { commit: String }, } pub async fn check(update: &ContainerUpdateCheck) -> Result { debug!("Checking updates for container image: {:?}", update.image); if update.commit.is_empty() { bail!( "The currently running commit is not configured: {:?}", update.commit ); } let output = Command::new("crane") .arg("config") .arg("--") .arg(&update.image) .output() .await .context("Failed to execute crane")?; if !output.stderr.is_empty() { let error = String::from_utf8_lossy(&output.stderr); warn!("Crane stderr was non-emtpy: {:?}", error); } if !output.status.success() { bail!("Crane exited with error: {:?}", output.status); } let output = serde_json::from_slice::(&output.stdout) .context("Failed to deserialize crane output")?; for env in &output.config.env { trace!("Found environment variable in container image: {:?}", env); if let Some(commit) = env.strip_prefix("UPDATE_CHECK_COMMIT=") { debug!("Found commit in container image: {commit:?}"); if commit == update.commit { debug!( "Update check detected we're running the latest version of {:?} (commit={:?}", update.image, commit ); return Ok(Updates::AlreadyLatest { commit: commit.to_string(), }); } else { debug!("Update check detected we're running an outdated version of {:?} (current={:?}, latest={:?})", update.image, update.commit, commit ); return Ok(Updates::Available { current: update.commit.to_string(), latest: commit.to_string(), }); } } } bail!( "Failed to detect commit id in specified container image: {:?}", update.image ); } apt-swarm-0.5.1/src/signed.rs000064400000000000000000010343431046102023000141600ustar 00000000000000use crate::errors::*; use crate::keyring::Keyring; use bstr::BString; use memchr::memchr; use sequoia_openpgp::armor; use sequoia_openpgp::parse::{PacketParser, PacketParserResult, Parse}; use sequoia_openpgp::serialize::Serialize as _; use sequoia_openpgp::Fingerprint; use sequoia_openpgp::Packet; use serde::{Deserialize, Serialize}; use std::io::prelude::*; use tokio::io::{AsyncBufRead, AsyncBufReadExt}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Signed { pub content: bstr::BString, pub signature: Vec, } impl Signed { pub fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8])> { let mut bytes = bytes .strip_prefix(b"-----BEGIN PGP SIGNED MESSAGE-----\n") .context("InRelease is expected to start with `-----BEGIN PGP SIGNED MESSAGE-----`")?; loop { let pos = 1 + memchr(b'\n', bytes) .context("Failed to find end of cleartext signed message headers")?; let line = &bytes[..pos]; bytes = &bytes[pos..]; // if the line was empty it's the end of headers if line == b"\n" { break; } } let mut content = Vec::new(); while !bytes.starts_with(b"-----BEGIN PGP SIGNATURE-----\n") { let pos = 1 + memchr(b'\n', bytes).context("Failed to find end of signed message")?; let line = &bytes[..pos]; let line = line.strip_prefix(b"- ").unwrap_or(line); content.extend(line); bytes = &bytes[pos..]; } let signature_start = bytes; let remaining = { let mut bytes = bytes; loop { if let Some(bytes) = bytes.strip_prefix(b"-----END PGP SIGNATURE-----\n") { break bytes; } else if bytes == b"-----END PGP SIGNATURE-----" { break b""; } else { let pos = 1 + memchr(b'\n', bytes).context("Failed to find end of signed message")?; bytes = &bytes[pos..]; } } }; let signature = &signature_start[..signature_start.len() - remaining.len()]; let mut reader = armor::Reader::from_bytes( signature, armor::ReaderMode::Tolerant(Some(armor::Kind::Signature)), ); let mut signature = Vec::new(); reader.read_to_end(&mut signature)?; Ok(( Signed { content: BString::from(content), signature, }, remaining, )) } pub async fn from_reader(reader: &mut R) -> Result { let mut line = Vec::new(); while line != b"-----BEGIN PGP SIGNED MESSAGE-----\n" { line.clear(); let read = reader.read_until(b'\n', &mut line).await?; if read == 0 { bail!("Unexpected end of document: Failed to find `BEGIN PGP SIGNED MESSAGE`"); } } while line != b"\n" { line.clear(); let read = reader.read_until(b'\n', &mut line).await?; if read == 0 { bail!("Unexpected end of document: Failed to find end of clear-signed headers"); } } let mut content = Vec::new(); loop { line.clear(); let read = reader.read_until(b'\n', &mut line).await?; if read == 0 { bail!("Unexpected end of document: Failed to find end of signed message"); } if line == b"-----BEGIN PGP SIGNATURE-----\n" { break; } let line = line.strip_prefix(b"- ").unwrap_or(&line); content.extend(line); } let mut signature = line.to_vec(); while line != b"-----END PGP SIGNATURE-----\n" { line.clear(); let read = reader.read_until(b'\n', &mut line).await?; if read == 0 { // if we reached EOF, also accept `END PGP SIGNATURE` with no final newline if line != b"-----END PGP SIGNATURE-----" { bail!("Unexpected end of document: Failed to find end of signature"); } } signature.extend(&line); } let mut reader = armor::Reader::from_bytes( &signature, armor::ReaderMode::Tolerant(Some(armor::Kind::Signature)), ); let mut signature = Vec::new(); reader .read_to_end(&mut signature) .context("Failed to decode signature")?; Ok(Signed { content: BString::from(content), signature, }) } pub fn to_clear_signed(&self) -> Result> { let mut out = Vec::new(); out.extend(b"-----BEGIN PGP SIGNED MESSAGE-----\n\n"); let mut bytes = self.content.as_slice(); while let Some(mut pos) = memchr(b'\n', bytes) { pos += 1; let line = &bytes[..pos]; if line.starts_with(b"-") { out.extend(b"- "); } out.extend(line); bytes = &bytes[pos..]; } if !bytes.is_empty() { bail!("Message didn't end with \\n and that's currently not supported"); } let mut writer = armor::Writer::new(&mut out, armor::Kind::Signature)?; writer.write_all(&self.signature)?; writer.finalize()?; Ok(out) } pub fn canonicalize( &self, keyring: Option<&Keyring>, ) -> Result, Signed)>> { let mut out = Vec::new(); let mut ppr = PacketParser::from_bytes(&self.signature)?; while let PacketParserResult::Some(pp) = ppr { let (packet, next_ppr) = pp.recurse()?; ppr = next_ppr; debug!("Found packet in signature block: {packet:?}"); if let Packet::Signature(sig) = &packet { let fingerprint = if let Some(keyring) = keyring { match keyring.verify(&self.content, sig) { Ok(fingerprint) => Some(fingerprint), Err(err) => { debug!( "Signature could not be verified, dismissing signature packet: {err:#}" ); continue; } } } else { None }; let mut signature = Vec::new(); packet .serialize(&mut signature) .context("Failed to serialize OpenPGP packet")?; out.push(( fingerprint, Signed { content: self.content.clone(), signature, }, )); } else { debug!("Unknown openpgp packet in signature block, dismissing: {packet:?}"); } } if out.is_empty() { warn!("Failed to find any trusted signatures in input data"); } Ok(out) } } #[cfg(test)] mod tests { use super::*; use bstr::BStr; const IN_RELEASE: &[u8] = b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Thu, 2 Feb 2023 21:39:16 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: 8550d0ce5fda03a2f3eb8c735a571bd5 4778 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release 2951333500c011d2b22c01de46d43223 128744 main/binary-amd64/Packages 444ef6562bb0ffef2b40af15d2a1e10d 20921 main/binary-amd64/Packages.gz 69ac9fed864b2f51c2a5fec9f8584724 17345 main/binary-amd64/Packages.bz2 SHA1: 56bddab49c82340b09c4e83e469e4042061bffa4 4778 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release c8be9dfb45580a4ff22f5afb0bff311458ae9dd7 128744 main/binary-amd64/Packages 0c82b553b566704273b4be3e3e08326f9ce7f936 20921 main/binary-amd64/Packages.gz 56e0d8810a31b18c6ae46001e08948fbffb20ebb 17345 main/binary-amd64/Packages.bz2 SHA256: 138a02cd93856c8e8ee0bfd3c558e9306607a7f0fb84609f70c566dcfe65c918 4778 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release 1e1b1c2e00f0beda7787e81a4b9f838a6ff9cb9866d8f0060adfe066805e1963 128744 main/binary-amd64/Packages 50e12a9696e82d0126328341b6e44b6fdad4459e8a53d94beb5d619d1b80c262 20921 main/binary-amd64/Packages.gz 3498ef94ef0967a7384014c6930aea9e3604595435e3f3baf579d3388f89ad26 17345 main/binary-amd64/Packages.bz2 -----BEGIN PGP SIGNATURE----- iQIcBAEBCAAGBQJj3C2FAAoJENmAoXRX9vsGtugP/Rzx0JWWASJJU8Ki7NC3B725 VuwHoW7tup+LEn0RdaIfVrPPAC0fRmbg4hju7nnQofeq9NEwrCsytHDqnQCvEvp4 zz3pK7PDUW18AdYZvnI5CX4iGx7PX2hPbBUnGCRs0OY8netMVqBJbRW43hsjvkaW ZOIl330mxXAGEC2ajRWlzef6stYILGVxuLOUunraIk+jDAU+lGZMaZHO9pqBuJ9p MFwGCb/TR5v9f/ORtX/nl5RII59ryFoVmOdLc18d/p72zIREwCY4P4mLxDZzQMRe EZf1RFhm/F6wl+rJx5ZVa30AmY5L9O1C7Uc/chO6hceNoJEbe9FxMumrX66yFTIv zGTl43pZCqLFyrKzucKeW8+mljrDkoplN8K+Y33JAGTNqrQHbp+ApD4Ls40Wg7hq KVqadABJ7W0Xiq3dF33LJYQ0raEkrEz5hEU1QCN6k+pB2FTEmDIB8AhP5wfn3C6a 3hbHljSr6DX45kIRNrLGqYv08GpglQqcNC0TNUcZpzouyW/PNsu32i66f9Uiscrk hHJwJ3vE26AQEhNc27ghV1gkYX1ap3TkFCgg6SomZWvOkqwqdbFxtJgUWATckVqV eE0Z2U8qNQ1V9YBouHdcVLcAEtprRSuTe5RQDohQuzoXrl6SsGgvVLATAmb/D1nu Aee63sxMlmRBCwC+QKeH =zXvj -----END PGP SIGNATURE----- "; #[test] fn test_parse_signed() -> Result<()> { let (signed, remaining) = Signed::from_bytes(IN_RELEASE)?; assert_eq!(remaining, b""); assert_eq!( signed, Signed { content: BString::from(b"Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Thu, 2 Feb 2023 21:39:16 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: 8550d0ce5fda03a2f3eb8c735a571bd5 4778 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release 2951333500c011d2b22c01de46d43223 128744 main/binary-amd64/Packages 444ef6562bb0ffef2b40af15d2a1e10d 20921 main/binary-amd64/Packages.gz 69ac9fed864b2f51c2a5fec9f8584724 17345 main/binary-amd64/Packages.bz2 SHA1: 56bddab49c82340b09c4e83e469e4042061bffa4 4778 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release c8be9dfb45580a4ff22f5afb0bff311458ae9dd7 128744 main/binary-amd64/Packages 0c82b553b566704273b4be3e3e08326f9ce7f936 20921 main/binary-amd64/Packages.gz 56e0d8810a31b18c6ae46001e08948fbffb20ebb 17345 main/binary-amd64/Packages.bz2 SHA256: 138a02cd93856c8e8ee0bfd3c558e9306607a7f0fb84609f70c566dcfe65c918 4778 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release 1e1b1c2e00f0beda7787e81a4b9f838a6ff9cb9866d8f0060adfe066805e1963 128744 main/binary-amd64/Packages 50e12a9696e82d0126328341b6e44b6fdad4459e8a53d94beb5d619d1b80c262 20921 main/binary-amd64/Packages.gz 3498ef94ef0967a7384014c6930aea9e3604595435e3f3baf579d3388f89ad26 17345 main/binary-amd64/Packages.bz2 ".to_vec()), signature: vec![137, 2, 28, 4, 1, 1, 8, 0, 6, 5, 2, 99, 220, 45, 133, 0, 10, 9, 16, 217, 128, 161, 116, 87, 246, 251, 6, 182, 232, 15, 253, 28, 241, 208, 149, 150, 1, 34, 73, 83, 194, 162, 236, 208, 183, 7, 189, 185, 86, 236, 7, 161, 110, 237, 186, 159, 139, 18, 125, 17, 117, 162, 31, 86, 179, 207, 0, 45, 31, 70, 102, 224, 226, 24, 238, 238, 121, 208, 161, 247, 170, 244, 209, 48, 172, 43, 50, 180, 112, 234, 157, 0, 175, 18, 250, 120, 207, 61, 233, 43, 179, 195, 81, 109, 124, 1, 214, 25, 190, 114, 57, 9, 126, 34, 27, 30, 207, 95, 104, 79, 108, 21, 39, 24, 36, 108, 208, 230, 60, 157, 235, 76, 86, 160, 73, 109, 21, 184, 222, 27, 35, 190, 70, 150, 100, 226, 37, 223, 125, 38, 197, 112, 6, 16, 45, 154, 141, 21, 165, 205, 231, 250, 178, 214, 8, 44, 101, 113, 184, 179, 148, 186, 122, 218, 34, 79, 163, 12, 5, 62, 148, 102, 76, 105, 145, 206, 246, 154, 129, 184, 159, 105, 48, 92, 6, 9, 191, 211, 71, 155, 253, 127, 243, 145, 181, 127, 231, 151, 148, 72, 35, 159, 107, 200, 90, 21, 152, 231, 75, 115, 95, 29, 254, 158, 246, 204, 132, 68, 192, 38, 56, 63, 137, 139, 196, 54, 115, 64, 196, 94, 17, 151, 245, 68, 88, 102, 252, 94, 176, 151, 234, 201, 199, 150, 85, 107, 125, 0, 153, 142, 75, 244, 237, 66, 237, 71, 63, 114, 19, 186, 133, 199, 141, 160, 145, 27, 123, 209, 113, 50, 233, 171, 95, 174, 178, 21, 50, 47, 204, 100, 229, 227, 122, 89, 10, 162, 197, 202, 178, 179, 185, 194, 158, 91, 207, 166, 150, 58, 195, 146, 138, 101, 55, 194, 190, 99, 125, 201, 0, 100, 205, 170, 180, 7, 110, 159, 128, 164, 62, 11, 179, 141, 22, 131, 184, 106, 41, 90, 154, 116, 0, 73, 237, 109, 23, 138, 173, 221, 23, 125, 203, 37, 132, 52, 173, 161, 36, 172, 76, 249, 132, 69, 53, 64, 35, 122, 147, 234, 65, 216, 84, 196, 152, 50, 1, 240, 8, 79, 231, 7, 231, 220, 46, 154, 222, 22, 199, 150, 52, 171, 232, 53, 248, 230, 66, 17, 54, 178, 198, 169, 139, 244, 240, 106, 96, 149, 10, 156, 52, 45, 19, 53, 71, 25, 167, 58, 46, 201, 111, 207, 54, 203, 183, 218, 46, 186, 127, 213, 34, 177, 202, 228, 132, 114, 112, 39, 123, 196, 219, 160, 16, 18, 19, 92, 219, 184, 33, 87, 88, 36, 97, 125, 90, 167, 116, 228, 20, 40, 32, 233, 42, 38, 101, 107, 206, 146, 172, 42, 117, 177, 113, 180, 152, 20, 88, 4, 220, 145, 90, 149, 120, 77, 25, 217, 79, 42, 53, 13, 85, 245, 128, 104, 184, 119, 92, 84, 183, 0, 18, 218, 107, 69, 43, 147, 123, 148, 80, 14, 136, 80, 187, 58, 23, 174, 94, 146, 176, 104, 47, 84, 176, 19, 2, 102, 255, 15, 89, 238, 1, 231, 186, 222, 204, 76, 150, 100, 65, 11, 0, 190, 64, 167, 135], } ); Ok(()) } #[test] fn test_canonicalize_already_canonical() -> Result<()> { let (canonical, remaining) = Signed::from_bytes(IN_RELEASE)?; let canonical = canonical.to_clear_signed()?; assert_eq!(remaining, b""); assert_eq!(BStr::new(&canonical), BStr::new(IN_RELEASE)); Ok(()) } #[test] fn test_canonicalize_strip_version() -> Result<()> { let (canonical, remaining) = Signed::from_bytes(b"-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Thu, 2 Feb 2023 21:39:16 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: 8550d0ce5fda03a2f3eb8c735a571bd5 4778 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release 2951333500c011d2b22c01de46d43223 128744 main/binary-amd64/Packages 444ef6562bb0ffef2b40af15d2a1e10d 20921 main/binary-amd64/Packages.gz 69ac9fed864b2f51c2a5fec9f8584724 17345 main/binary-amd64/Packages.bz2 SHA1: 56bddab49c82340b09c4e83e469e4042061bffa4 4778 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release c8be9dfb45580a4ff22f5afb0bff311458ae9dd7 128744 main/binary-amd64/Packages 0c82b553b566704273b4be3e3e08326f9ce7f936 20921 main/binary-amd64/Packages.gz 56e0d8810a31b18c6ae46001e08948fbffb20ebb 17345 main/binary-amd64/Packages.bz2 SHA256: 138a02cd93856c8e8ee0bfd3c558e9306607a7f0fb84609f70c566dcfe65c918 4778 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release 1e1b1c2e00f0beda7787e81a4b9f838a6ff9cb9866d8f0060adfe066805e1963 128744 main/binary-amd64/Packages 50e12a9696e82d0126328341b6e44b6fdad4459e8a53d94beb5d619d1b80c262 20921 main/binary-amd64/Packages.gz 3498ef94ef0967a7384014c6930aea9e3604595435e3f3baf579d3388f89ad26 17345 main/binary-amd64/Packages.bz2 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJj3C2FAAoJENmAoXRX9vsGtugP/Rzx0JWWASJJU8Ki7NC3B725 VuwHoW7tup+LEn0RdaIfVrPPAC0fRmbg4hju7nnQofeq9NEwrCsytHDqnQCvEvp4 zz3pK7PDUW18AdYZvnI5CX4iGx7PX2hPbBUnGCRs0OY8netMVqBJbRW43hsjvkaW ZOIl330mxXAGEC2ajRWlzef6stYILGVxuLOUunraIk+jDAU+lGZMaZHO9pqBuJ9p MFwGCb/TR5v9f/ORtX/nl5RII59ryFoVmOdLc18d/p72zIREwCY4P4mLxDZzQMRe EZf1RFhm/F6wl+rJx5ZVa30AmY5L9O1C7Uc/chO6hceNoJEbe9FxMumrX66yFTIv zGTl43pZCqLFyrKzucKeW8+mljrDkoplN8K+Y33JAGTNqrQHbp+ApD4Ls40Wg7hq KVqadABJ7W0Xiq3dF33LJYQ0raEkrEz5hEU1QCN6k+pB2FTEmDIB8AhP5wfn3C6a 3hbHljSr6DX45kIRNrLGqYv08GpglQqcNC0TNUcZpzouyW/PNsu32i66f9Uiscrk hHJwJ3vE26AQEhNc27ghV1gkYX1ap3TkFCgg6SomZWvOkqwqdbFxtJgUWATckVqV eE0Z2U8qNQ1V9YBouHdcVLcAEtprRSuTe5RQDohQuzoXrl6SsGgvVLATAmb/D1nu Aee63sxMlmRBCwC+QKeH =zXvj -----END PGP SIGNATURE----- ")?; let canonical = canonical.to_clear_signed()?; assert_eq!(remaining, b""); assert_eq!(canonical, IN_RELEASE); Ok(()) } #[test] fn test_check_signature() -> Result<()> { let (signed, remaining) = Signed::from_bytes(IN_RELEASE)?; assert_eq!(remaining, b""); let keyring = Keyring::new(include_bytes!("../contrib/signal-desktop-keyring.gpg"))?; let canonical = signed.canonicalize(Some(&keyring))?; assert_eq!(canonical, &[("DBA36B5181D0C816F630E889D980A17457F6FB06".parse().ok(), Signed { content: BString::from(b"Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Thu, 2 Feb 2023 21:39:16 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: 8550d0ce5fda03a2f3eb8c735a571bd5 4778 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release 2951333500c011d2b22c01de46d43223 128744 main/binary-amd64/Packages 444ef6562bb0ffef2b40af15d2a1e10d 20921 main/binary-amd64/Packages.gz 69ac9fed864b2f51c2a5fec9f8584724 17345 main/binary-amd64/Packages.bz2 SHA1: 56bddab49c82340b09c4e83e469e4042061bffa4 4778 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release c8be9dfb45580a4ff22f5afb0bff311458ae9dd7 128744 main/binary-amd64/Packages 0c82b553b566704273b4be3e3e08326f9ce7f936 20921 main/binary-amd64/Packages.gz 56e0d8810a31b18c6ae46001e08948fbffb20ebb 17345 main/binary-amd64/Packages.bz2 SHA256: 138a02cd93856c8e8ee0bfd3c558e9306607a7f0fb84609f70c566dcfe65c918 4778 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release 1e1b1c2e00f0beda7787e81a4b9f838a6ff9cb9866d8f0060adfe066805e1963 128744 main/binary-amd64/Packages 50e12a9696e82d0126328341b6e44b6fdad4459e8a53d94beb5d619d1b80c262 20921 main/binary-amd64/Packages.gz 3498ef94ef0967a7384014c6930aea9e3604595435e3f3baf579d3388f89ad26 17345 main/binary-amd64/Packages.bz2 ".to_vec()), signature: vec![194, 193, 92, 4, 1, 1, 8, 0, 6, 5, 2, 99, 220, 45, 133, 0, 10, 9, 16, 217, 128, 161, 116, 87, 246, 251, 6, 182, 232, 15, 253, 28, 241, 208, 149, 150, 1, 34, 73, 83, 194, 162, 236, 208, 183, 7, 189, 185, 86, 236, 7, 161, 110, 237, 186, 159, 139, 18, 125, 17, 117, 162, 31, 86, 179, 207, 0, 45, 31, 70, 102, 224, 226, 24, 238, 238, 121, 208, 161, 247, 170, 244, 209, 48, 172, 43, 50, 180, 112, 234, 157, 0, 175, 18, 250, 120, 207, 61, 233, 43, 179, 195, 81, 109, 124, 1, 214, 25, 190, 114, 57, 9, 126, 34, 27, 30, 207, 95, 104, 79, 108, 21, 39, 24, 36, 108, 208, 230, 60, 157, 235, 76, 86, 160, 73, 109, 21, 184, 222, 27, 35, 190, 70, 150, 100, 226, 37, 223, 125, 38, 197, 112, 6, 16, 45, 154, 141, 21, 165, 205, 231, 250, 178, 214, 8, 44, 101, 113, 184, 179, 148, 186, 122, 218, 34, 79, 163, 12, 5, 62, 148, 102, 76, 105, 145, 206, 246, 154, 129, 184, 159, 105, 48, 92, 6, 9, 191, 211, 71, 155, 253, 127, 243, 145, 181, 127, 231, 151, 148, 72, 35, 159, 107, 200, 90, 21, 152, 231, 75, 115, 95, 29, 254, 158, 246, 204, 132, 68, 192, 38, 56, 63, 137, 139, 196, 54, 115, 64, 196, 94, 17, 151, 245, 68, 88, 102, 252, 94, 176, 151, 234, 201, 199, 150, 85, 107, 125, 0, 153, 142, 75, 244, 237, 66, 237, 71, 63, 114, 19, 186, 133, 199, 141, 160, 145, 27, 123, 209, 113, 50, 233, 171, 95, 174, 178, 21, 50, 47, 204, 100, 229, 227, 122, 89, 10, 162, 197, 202, 178, 179, 185, 194, 158, 91, 207, 166, 150, 58, 195, 146, 138, 101, 55, 194, 190, 99, 125, 201, 0, 100, 205, 170, 180, 7, 110, 159, 128, 164, 62, 11, 179, 141, 22, 131, 184, 106, 41, 90, 154, 116, 0, 73, 237, 109, 23, 138, 173, 221, 23, 125, 203, 37, 132, 52, 173, 161, 36, 172, 76, 249, 132, 69, 53, 64, 35, 122, 147, 234, 65, 216, 84, 196, 152, 50, 1, 240, 8, 79, 231, 7, 231, 220, 46, 154, 222, 22, 199, 150, 52, 171, 232, 53, 248, 230, 66, 17, 54, 178, 198, 169, 139, 244, 240, 106, 96, 149, 10, 156, 52, 45, 19, 53, 71, 25, 167, 58, 46, 201, 111, 207, 54, 203, 183, 218, 46, 186, 127, 213, 34, 177, 202, 228, 132, 114, 112, 39, 123, 196, 219, 160, 16, 18, 19, 92, 219, 184, 33, 87, 88, 36, 97, 125, 90, 167, 116, 228, 20, 40, 32, 233, 42, 38, 101, 107, 206, 146, 172, 42, 117, 177, 113, 180, 152, 20, 88, 4, 220, 145, 90, 149, 120, 77, 25, 217, 79, 42, 53, 13, 85, 245, 128, 104, 184, 119, 92, 84, 183, 0, 18, 218, 107, 69, 43, 147, 123, 148, 80, 14, 136, 80, 187, 58, 23, 174, 94, 146, 176, 104, 47, 84, 176, 19, 2, 102, 255, 15, 89, 238, 1, 231, 186, 222, 204, 76, 150, 100, 65, 11, 0, 190, 64, 167, 135], })]); Ok(()) } #[test] fn test_check_multiple_signatures() -> Result<()> { let (signed, remaining) = Signed::from_bytes(b"-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Origin: Debian Label: Debian Suite: stable Version: 11.6 Codename: bullseye Changelogs: https://metadata.ftp-master.debian.org/changelogs/@CHANGEPATH@_changelog Date: Sat, 17 Dec 2022 10:14:37 UTC Acquire-By-Hash: yes No-Support-for-Architecture-all: Packages Architectures: all amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x Components: main contrib non-free Description: Debian 11.6 Released 17 December 2022 MD5Sum: 7fdf4db15250af5368cc52a91e8edbce 738242 contrib/Contents-all cbd7bc4d3eb517ac2b22f929dfc07b47 57319 contrib/Contents-all.gz 6e4ef0f159fa08f5ba74067e0a94b5e6 787321 contrib/Contents-amd64 98583d055424774c060fdf4b02291da5 54668 contrib/Contents-amd64.gz 61e10f1703d718d584f381a943bfe4d7 370915 contrib/Contents-arm64 86a145a0d8d7346449f2cf62098a5553 29596 contrib/Contents-arm64.gz b6d2673f17fbdb3a5ce92404a62c2d7e 359292 contrib/Contents-armel d02d94be587d56a1246b407669d2a24c 28039 contrib/Contents-armel.gz d272ba9da0f302b6c09a36899e738115 367655 contrib/Contents-armhf 317aa67ea34d625837d245f6fb00bdc4 29236 contrib/Contents-armhf.gz ccb13401b0f48dded08ed089f8074765 407328 contrib/Contents-i386 e496015d7e6e8d5a91cec31fc4bde74c 33556 contrib/Contents-i386.gz 44384de1db64f592fc69693b355a0ec7 359402 contrib/Contents-mips64el a2abf38d14c1c7e3aafcb21881b0fe7d 27962 contrib/Contents-mips64el.gz 457feed233db5ce7db62cc69e7a8a5c6 360549 contrib/Contents-mipsel 90ec76d0dca539a4c4aa33404de4c633 27942 contrib/Contents-mipsel.gz 02985cbbdd1e790b29a9911ba00b5650 370025 contrib/Contents-ppc64el b34b90df14207eafe94313e6d466b28e 29381 contrib/Contents-ppc64el.gz e2089c91540f7adb693675935dacf9e5 357860 contrib/Contents-s390x bb90fb42e72d39da53b3e1e2c2f46bc3 27518 contrib/Contents-s390x.gz ba62d5cf69ffc155d75fa9e16228b039 6722669 contrib/Contents-source fec97c652e41904e73f17cc5f7b0b2ff 469817 contrib/Contents-source.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-all 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-all.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-amd64 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-amd64.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-arm64 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-arm64.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-armel 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-armel.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-armhf 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-armhf.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-i386 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-i386.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-mips64el 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-mips64el.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-mipsel 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-mipsel.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-ppc64el 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-ppc64el.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-s390x 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-s390x.gz 73d0ad5df01464248f578fb7d7ba10b0 103239 contrib/binary-all/Packages 6848b84ab94b0624ad15f5afea5f49bd 27385 contrib/binary-all/Packages.gz a9e21972669e0355e9a875ea31f25c63 23916 contrib/binary-all/Packages.xz 3c9131b20395850cbf9735dfbc0cd6a7 117 contrib/binary-all/Release b6541899bd7907d9dc5afe604d26a719 231878 contrib/binary-amd64/Packages 7cb1a35df9e7ef744685d28932cc1ef2 60884 contrib/binary-amd64/Packages.gz 4ee4184e78f4b0d06e981706a6118dc7 50588 contrib/binary-amd64/Packages.xz 7edd7af81aa30d5a929cad55b259de23 119 contrib/binary-amd64/Release 4b9c68a7d2d23357dc171d29a03565c6 180884 contrib/binary-arm64/Packages c2d2253fb81e2a397e4a42d4d475bd24 48958 contrib/binary-arm64/Packages.gz f57a0a52945226cc76c241ce57c182be 40964 contrib/binary-arm64/Packages.xz 34b661285be33d5dd033de35b00b0b52 119 contrib/binary-arm64/Release 1636c115e53ef208266fcc6b024f7b34 163042 contrib/binary-armel/Packages ed80c2afd00562cee8543a3835ed0907 44389 contrib/binary-armel/Packages.gz ef8175333695e1554eeb8766d74c4795 37452 contrib/binary-armel/Packages.xz f5908602701eedda3f627be810655de2 119 contrib/binary-armel/Release 900f4a8949a535dfd1af4326b43e6fa4 175566 contrib/binary-armhf/Packages 11db111d1dd40616866a8b6d4e59ca8d 47805 contrib/binary-armhf/Packages.gz 512198b43afc25d9da1e078b44f5b4a8 40220 contrib/binary-armhf/Packages.xz 7271fc19a10e612fcdc17bfc361a4805 119 contrib/binary-armhf/Release feb05a736bdfbd41bfdd4d87fd34f72a 203514 contrib/binary-i386/Packages 89a79f0c9d4bb2df7d3dc3d165f02242 54100 contrib/binary-i386/Packages.gz 130d6b77d3b32c1ec94097e694d66718 45340 contrib/binary-i386/Packages.xz 8dc8ab0c142d7166f1a8cb8ef5c8dcaa 118 contrib/binary-i386/Release 825bc5698936bc26f5bb28c20287aeb1 163507 contrib/binary-mips64el/Packages 190dd8f6a3e97c3ebe8ab216e79ed867 44652 contrib/binary-mips64el/Packages.gz 9302a32bad830648c066bfb13a35b6b9 37496 contrib/binary-mips64el/Packages.xz 268c4243d0a655c886c9533779085b8e 122 contrib/binary-mips64el/Release 4e717be16d235fb7e6e118c898ac80af 164647 contrib/binary-mipsel/Packages f73fd75fc0a6371ae7e6b709a4d8d939 44883 contrib/binary-mipsel/Packages.gz 9c8d77e03dcdc178465c28095f4e8d64 37816 contrib/binary-mipsel/Packages.xz 5e4a6cc21b9343c50ab7eeb20be00166 120 contrib/binary-mipsel/Release 1343f3307bbeea9f0b04dd64e8d23d62 180387 contrib/binary-ppc64el/Packages 831c14a6428bbe7b05d290e9aa225785 48843 contrib/binary-ppc64el/Packages.gz 8daa347dc96d3f69e7510c0d3f51916e 40808 contrib/binary-ppc64el/Packages.xz 44eda0cdaff945cc2cb4f8bdfad50371 121 contrib/binary-ppc64el/Release 1a2b7365b25b44a4304271198bda5094 162250 contrib/binary-s390x/Packages 103b59f69a5c230eab05d06289ad7c9b 44334 contrib/binary-s390x/Packages.gz e4109e4637f7b1c233130da040451fd9 37244 contrib/binary-s390x/Packages.xz aa08c18b750a7efa1a4c3f23650132a4 119 contrib/binary-s390x/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-all/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-all/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-all/Packages.xz 3c9131b20395850cbf9735dfbc0cd6a7 117 contrib/debian-installer/binary-all/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-amd64/Packages.xz 7edd7af81aa30d5a929cad55b259de23 119 contrib/debian-installer/binary-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-arm64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-arm64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-arm64/Packages.xz 34b661285be33d5dd033de35b00b0b52 119 contrib/debian-installer/binary-arm64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-armel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-armel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-armel/Packages.xz f5908602701eedda3f627be810655de2 119 contrib/debian-installer/binary-armel/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-armhf/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-armhf/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-armhf/Packages.xz 7271fc19a10e612fcdc17bfc361a4805 119 contrib/debian-installer/binary-armhf/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-i386/Packages.xz 8dc8ab0c142d7166f1a8cb8ef5c8dcaa 118 contrib/debian-installer/binary-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mips64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mips64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mips64el/Packages.xz 268c4243d0a655c886c9533779085b8e 122 contrib/debian-installer/binary-mips64el/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mipsel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mipsel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mipsel/Packages.xz 5e4a6cc21b9343c50ab7eeb20be00166 120 contrib/debian-installer/binary-mipsel/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-ppc64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-ppc64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-ppc64el/Packages.xz 44eda0cdaff945cc2cb4f8bdfad50371 121 contrib/debian-installer/binary-ppc64el/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-s390x/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-s390x/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-s390x/Packages.xz aa08c18b750a7efa1a4c3f23650132a4 119 contrib/debian-installer/binary-s390x/Release fc412a0e8fed50416ae55ca3a34c2654 119152 contrib/dep11/Components-amd64.yml 7473c932902284e9c636636a5ff0587b 15579 contrib/dep11/Components-amd64.yml.gz 751b272121122fce4882d17a9d099c44 13564 contrib/dep11/Components-amd64.yml.xz 49911a9d2f76ed13124c7cff0081266b 113437 contrib/dep11/Components-arm64.yml ee72e145d0e71d94c0d418d36dabfd8c 14251 contrib/dep11/Components-arm64.yml.gz 65f48dc9acec772076e60ce35239703f 12480 contrib/dep11/Components-arm64.yml.xz b1f970bbcdd889ccff5c2646bc2835ba 113437 contrib/dep11/Components-armel.yml d2a414b1147562c0ecfa1aab53fc0260 14029 contrib/dep11/Components-armel.yml.gz b450a677c3a5d4a52d2a0df274c222cf 12524 contrib/dep11/Components-armel.yml.xz 75c6b8bd42fc863caa66c454306c7d39 113437 contrib/dep11/Components-armhf.yml ac52f103d1c493d0f8d8e5662d758f78 14127 contrib/dep11/Components-armhf.yml.gz 80f4310b2d68bf09c7fbba34a0eec794 12480 contrib/dep11/Components-armhf.yml.xz a46b6878a89f45fab86aca68bffe081d 118972 contrib/dep11/Components-i386.yml 751ea67ac68d2e755726b4e9d62ab15e 15566 contrib/dep11/Components-i386.yml.gz 82c956565311c8a7d90bff6e0a226fbe 13560 contrib/dep11/Components-i386.yml.xz 6f822ef8f2c13dc4212ade261b4a8752 113437 contrib/dep11/Components-mips64el.yml a072aab0fb45dab4a6e25295f23e9b5f 14056 contrib/dep11/Components-mips64el.yml.gz e5c2dd7fd785fa1ab66099d7763bd670 12500 contrib/dep11/Components-mips64el.yml.xz 432a29a22c4a782f6edad376f386937f 113437 contrib/dep11/Components-ppc64el.yml b5202b5037949e593060f92290d6f949 14219 contrib/dep11/Components-ppc64el.yml.gz dd92a500c7807091665dbc207c9bef68 12496 contrib/dep11/Components-ppc64el.yml.xz 53c6b87820861b0ed316a88f7542cd76 113437 contrib/dep11/Components-s390x.yml 5a4872d3187bc79418b468890be4b5fe 14050 contrib/dep11/Components-s390x.yml.gz eefb3301e486aedbbbb1d735e2522a00 12488 contrib/dep11/Components-s390x.yml.xz 5d8e37f26e7e15f367751089fa13c876 271360 contrib/dep11/icons-128x128.tar 500b14a4cafa23b9106b402737f863a7 195507 contrib/dep11/icons-128x128.tar.gz d9651fb188be2221d2f583aeba83d8fc 83968 contrib/dep11/icons-48x48.tar 6b5ea4675ad78554aaa53b344f1bd146 47168 contrib/dep11/icons-48x48.tar.gz 7115d3a3d41fc9bca9cfcc3c608bebf2 138752 contrib/dep11/icons-64x64.tar c839e679f1d60d294d39884d0911e514 93294 contrib/dep11/icons-64x64.tar.gz 01e75740c90a7df7e474a1c6152b2aa6 192685 contrib/i18n/Translation-en a2e9608c3e388d26e031583f200e2f92 46929 contrib/i18n/Translation-en.bz2 7b851a6fc52e455ec6e64d1bbd002e60 120 contrib/source/Release d615756c28aa372e2bc408abe1d9ec5b 178776 contrib/source/Sources c19b950adb0b02bb84fec45d11d257d8 51355 contrib/source/Sources.gz 0e1710e68ffbd6a7b3542844610a69fc 43208 contrib/source/Sources.xz 052421edd3e77801652c5e82cea27172 477769406 main/Contents-all c6642306466300d5b980a46ab2da3448 31069218 main/Contents-all.gz 4f76cfae77ca68a2534e4776c1ba603a 129058022 main/Contents-amd64 d00bf88e20a9167d72c15f914e2f6ae6 10270460 main/Contents-amd64.gz 4c143d623f5b8d26d47c079554c17287 122426895 main/Contents-arm64 44ba782a6a21b58a1ff85d2c04785f8d 9831920 main/Contents-arm64.gz 801e7ed91bc44eb81525999ec2a8291e 104683113 main/Contents-armel a5a18ca6cde98c20f5b89666cc6ada02 8703570 main/Contents-armel.gz 307b7ca5872bf53d92aced5dc4fa75ba 113716591 main/Contents-armhf ec3f7e25caefcde0999e74f88fe29c25 9305906 main/Contents-armhf.gz 39e08183dd281004ce0853d8138db6b9 129088857 main/Contents-i386 4339b5c20026a75c512e5c97c56ac03c 10208982 main/Contents-i386.gz 1468642d6dbe21a9b910d360f52d1a71 111097071 main/Contents-mips64el f5727ac1ba4208d6994869b64251d40f 9042221 main/Contents-mips64el.gz 30ac6e6b838d5fc79a6139fc5b4e7337 112593872 main/Contents-mipsel 13fcab9f9e956d966bf9975da41bec6c 9178325 main/Contents-mipsel.gz 985636740f62394375012f87593d5c21 116027632 main/Contents-ppc64el 97f1aaf6603044158ce139c2570992d0 9355024 main/Contents-ppc64el.gz 332ff60dc3b48ca16f5bf3baa139b530 103638209 main/Contents-s390x 1dfb6d3460020eb28ef7ab36bd7d0c08 8711885 main/Contents-s390x.gz 30e2a744a0a8fc6c48325fa30d7d0e70 690410830 main/Contents-source 453c66c682ee49babee0fac4ec460ac7 73501881 main/Contents-source.gz 1f4bf598c355a2bbb0c8ddf889d9636e 157382 main/Contents-udeb-all 708ed31f29f9daf4c980b7abdd66c356 13516 main/Contents-udeb-all.gz 069860439eabdda442aa81afb59f8644 477050 main/Contents-udeb-amd64 6e95b271bba66b8135cdd9ee13cad982 36011 main/Contents-udeb-amd64.gz 8884d6660508188095f2991c73ede3a2 508817 main/Contents-udeb-arm64 a972a7d9191733ca34c65bbec0c4da30 38139 main/Contents-udeb-arm64.gz 72cc361d1b9ae73eeb7e3798a52564b2 323083 main/Contents-udeb-armel 2521b5dc40ca4ce0c2cf495642512931 25477 main/Contents-udeb-armel.gz b74da65320e8e14ccd398d9b3a0af741 579793 main/Contents-udeb-armhf a6b01ebd28d333afe285226a6d3902b5 43153 main/Contents-udeb-armhf.gz 02f78f33d39614e8f2c1ae4a5971637a 751383 main/Contents-udeb-i386 f77c976f4226372caba729cd86720f36 53984 main/Contents-udeb-i386.gz fc8c6638ad4e7036abcfb74c9ca40e67 760534 main/Contents-udeb-mips64el b29f9bef4f9b6237adac6822c3f644ee 52873 main/Contents-udeb-mips64el.gz 8851f799ab3bac7dbe3ade6ca88058d3 760210 main/Contents-udeb-mipsel f5b4e16d70afd5fe145bbcff78ed60c7 52810 main/Contents-udeb-mipsel.gz b0c21603250d55447094b00f1438aef7 401639 main/Contents-udeb-ppc64el 9cc88f8f084a1bf1b0f4a3f7d4d2baa1 29533 main/Contents-udeb-ppc64el.gz 942cbd0dfe1ec1bbc24f50b6a22102e0 258318 main/Contents-udeb-s390x bdeed95042d0b946c8d8f72cb49fd28d 20894 main/Contents-udeb-s390x.gz 779c0c7072ee9cd9b776167e3b0d8694 20423830 main/binary-all/Packages 78a6edfff04a3b7505c0b8b1cc468c68 5208282 main/binary-all/Packages.gz 296b8e6e27112ca9610cde0fbc84f34f 3918264 main/binary-all/Packages.xz d8d2edd733e3235987c8c0c9565344d8 114 main/binary-all/Release ee0b34bb7ba7a8e1a7964ebd20187def 45534962 main/binary-amd64/Packages c14373e666988e64b30c26f3b6c3fbf2 11096605 main/binary-amd64/Packages.gz f30e2d1e8f395c903155dda0c4ba0970 8182920 main/binary-amd64/Packages.xz dbeadc926a4f14b4a73390c82832052b 116 main/binary-amd64/Release e02c425b41e1c7f2e910960cb80b8fc6 44816551 main/binary-arm64/Packages 854700a00d0c4c7b9f8b7946d97b85fc 10941625 main/binary-arm64/Packages.gz 3fd4c3700b238504448734039842d4fd 8071508 main/binary-arm64/Packages.xz f02cb9aab85fccb7a19d168b5acb2390 116 main/binary-arm64/Release a0174a68bcedce8fba19bde6cd1208b3 43343990 main/binary-armel/Packages 56c75313e445b1b136fd240122a4a207 10677432 main/binary-armel/Packages.gz 797f4ee8e47a372aae0a83ea352fe2fa 7871888 main/binary-armel/Packages.xz 358a6eb5337f79950b79beaae6d06bd4 116 main/binary-armel/Release d4028809623d98cbf20cb043be845906 43846413 main/binary-armhf/Packages 8326ddf7c01158570ca901a8827c0449 10775534 main/binary-armhf/Packages.gz 5845702f6c696189347091fd5cb51276 7944712 main/binary-armhf/Packages.xz 8811dc441114bb1b2f90dfce9ff6acfc 116 main/binary-armhf/Release 99f2432683f72cb4833cc0392f8a1313 45094980 main/binary-i386/Packages 1c5363ed68d7894cf94ab51ec66bf926 11013153 main/binary-i386/Packages.gz 534024b184373545b78e74aa164ba211 8121972 main/binary-i386/Packages.xz 50b3c16ad95352c06904ec1341afe2d2 115 main/binary-i386/Release 87f3a748abd585d485b04e11a8f75fa8 43733274 main/binary-mips64el/Packages e7ee93fdf444409e1d751e3160a599e3 10720185 main/binary-mips64el/Packages.gz c2f655d6e0fb46a1eb029045054e5b52 7907404 main/binary-mips64el/Packages.xz c0cc63128ced0d323a714281b3f78ba2 119 main/binary-mips64el/Release d5fc8d1553a24222dda3e6fc804b2aeb 43667386 main/binary-mipsel/Packages 88a8a5f188c1a0e18255daab88d8c83f 10726366 main/binary-mipsel/Packages.gz c9568fef286c9fe7d80cdcf9dece78bc 7906936 main/binary-mipsel/Packages.xz 0ac20990fd13d5eaf32c0041fd37c568 117 main/binary-mipsel/Release 735e4dcaafa4c558fd21e8a7075f4997 44671240 main/binary-ppc64el/Packages 5f14e959fec4dfca2d5b3f8b7bd090af 10884852 main/binary-ppc64el/Packages.gz 1b587b581cb630066fa51c8ea85ea327 8031816 main/binary-ppc64el/Packages.xz 641a1901dc2496b912f4f49e9f7d4db8 118 main/binary-ppc64el/Release d93e11281b31f88d89a0d1eb73cc13ca 43340190 main/binary-s390x/Packages 1ca35cf8189cbb3fe643b9be4ca39e48 10686656 main/binary-s390x/Packages.gz 9f00d6b29f1659c08eea54ca8e0e652e 7877060 main/binary-s390x/Packages.xz 40a1a7ba21820ed919518a0e4f6cbbbd 116 main/binary-s390x/Release 8523f5593a344ec29029e3e20b8e10fa 61160 main/debian-installer/binary-all/Packages 8322a8e0b943187cc1ad41f5e91e0c8c 16449 main/debian-installer/binary-all/Packages.gz 73f68ee665b0ba4fe8b1d5bd0986e6a1 14676 main/debian-installer/binary-all/Packages.xz d8d2edd733e3235987c8c0c9565344d8 114 main/debian-installer/binary-all/Release e5156b114c9a46b50dc7b14217399795 274352 main/debian-installer/binary-amd64/Packages fa8d2c9b9be51d30622654b67ecac5c5 67349 main/debian-installer/binary-amd64/Packages.gz 79cadb77602e77b501f0d9354d6a940b 56064 main/debian-installer/binary-amd64/Packages.xz dbeadc926a4f14b4a73390c82832052b 116 main/debian-installer/binary-amd64/Release bf5150ba5d1823e80ce45b268a79a392 257349 main/debian-installer/binary-arm64/Packages 74c5e0915ec84c2c336d97652ffa0a7a 64271 main/debian-installer/binary-arm64/Packages.gz cca08998fcdd03ca3284112927344e20 53980 main/debian-installer/binary-arm64/Packages.xz f02cb9aab85fccb7a19d168b5acb2390 116 main/debian-installer/binary-arm64/Release 79673899cedce0be43ebc1d416fb58bd 248363 main/debian-installer/binary-armel/Packages 80bf080680db4b7b02ed444454b8981f 63792 main/debian-installer/binary-armel/Packages.gz 7cfb8b710c1228c6359c7b48041cc8c0 53168 main/debian-installer/binary-armel/Packages.xz 358a6eb5337f79950b79beaae6d06bd4 116 main/debian-installer/binary-armel/Release 1f43e9a44586e87494ec1a7269ec7f2c 251788 main/debian-installer/binary-armhf/Packages 262d12c86cfee6e0c82383272d15c377 64864 main/debian-installer/binary-armhf/Packages.gz b4db61d6a2322a13cf8d6b0f49e9ffbe 53852 main/debian-installer/binary-armhf/Packages.xz 8811dc441114bb1b2f90dfce9ff6acfc 116 main/debian-installer/binary-armhf/Release cd8f8bf8d19b9ba5a1efc7a75930121a 349445 main/debian-installer/binary-i386/Packages 41400360bb68ffe289e94a68da63e79f 77230 main/debian-installer/binary-i386/Packages.gz 2a77d691876cab7b5f0803b7611ca267 64124 main/debian-installer/binary-i386/Packages.xz 50b3c16ad95352c06904ec1341afe2d2 115 main/debian-installer/binary-i386/Release c22d0ce635eb0fae86afba6242116a19 364716 main/debian-installer/binary-mips64el/Packages 1aef85058cd12a9638321fedd2ffff31 79498 main/debian-installer/binary-mips64el/Packages.gz 9d5da1ee87189d9671b42c4bc122c48a 66396 main/debian-installer/binary-mips64el/Packages.xz c0cc63128ced0d323a714281b3f78ba2 119 main/debian-installer/binary-mips64el/Release 18bc2f5de2b576eee963afeb65375aab 364202 main/debian-installer/binary-mipsel/Packages a1b8c712b5272debb29e8c07de9caf0b 79784 main/debian-installer/binary-mipsel/Packages.gz cce1945593d8c4b82fd33b6e5f761521 66500 main/debian-installer/binary-mipsel/Packages.xz 0ac20990fd13d5eaf32c0041fd37c568 117 main/debian-installer/binary-mipsel/Release d7b8901246bae032e5ddbc9e45cc872c 256933 main/debian-installer/binary-ppc64el/Packages 70a122a874633fde8db5504f98ee7439 64920 main/debian-installer/binary-ppc64el/Packages.gz f2e4f1994de7021fbfc39fa44056b2b1 53960 main/debian-installer/binary-ppc64el/Packages.xz 641a1901dc2496b912f4f49e9f7d4db8 118 main/debian-installer/binary-ppc64el/Release 1b44e25a26eefd464c288608423d6e42 226275 main/debian-installer/binary-s390x/Packages 095ad8009e027e93ec3bbe8678eef9f6 60464 main/debian-installer/binary-s390x/Packages.gz e513ca8104e23a972e147e86ef1bf5ab 50116 main/debian-installer/binary-s390x/Packages.xz 40a1a7ba21820ed919518a0e4f6cbbbd 116 main/debian-installer/binary-s390x/Release 97a6eda13094854f8838218d5869a796 18520413 main/dep11/Components-amd64.yml 9cd807c0b66a8489b5385bf4f343b288 6213469 main/dep11/Components-amd64.yml.gz c16ba02c289510dce9857dfa6cde4550 4048504 main/dep11/Components-amd64.yml.xz 3e8ecb0bbaecb88d0b16dfaa037dba73 18436837 main/dep11/Components-arm64.yml 09ef5a87673c946f916b0d8ef0c2471d 6191092 main/dep11/Components-arm64.yml.gz fef127cee05f3efb96261e78b4fe4568 4033216 main/dep11/Components-arm64.yml.xz 67becc674b536e310fe22492d55c8652 17658848 main/dep11/Components-armel.yml 34cd8a6a1206f804e6d5c54dcdd3ef63 5952269 main/dep11/Components-armel.yml.gz d7cc0222cae53bcfa1de29218fe5cb94 3879744 main/dep11/Components-armel.yml.xz 09010fea4c1cf082bd54aecc24182e45 18205252 main/dep11/Components-armhf.yml f5b7fd1a9cb147fa6b90e60a4d2139c1 6110587 main/dep11/Components-armhf.yml.gz f1f223ca9e69ad1901345ceb404a5666 3983180 main/dep11/Components-armhf.yml.xz ee8f83c597007ab84b58feec05d647fa 18485654 main/dep11/Components-i386.yml 5a6b35ea7b54d88842ab30bbbd469623 6201776 main/dep11/Components-i386.yml.gz 239cc12774e7c2925d1d783faaf01b5d 4041608 main/dep11/Components-i386.yml.xz dd59f50383f269a8e1ec09c49d8a786c 17819116 main/dep11/Components-mips64el.yml e3f03ed2f2c22dac3207e5f3fb98f862 5977494 main/dep11/Components-mips64el.yml.gz 437c9fa1e058fc9a3486fb8b224740f6 3896708 main/dep11/Components-mips64el.yml.xz 09d0cb63fdf4a4904155dc0d56ccc04b 17947079 main/dep11/Components-ppc64el.yml 3d396ef7d8293620c5160a75fda04d39 6023058 main/dep11/Components-ppc64el.yml.gz 23ebc600f44eb4973c351a4a324ba219 3925796 main/dep11/Components-ppc64el.yml.xz 64acc85d1d2ce3e3dc551ae85e80ca57 17735785 main/dep11/Components-s390x.yml b7f851e780c93532c1707895dfa22474 5976062 main/dep11/Components-s390x.yml.gz 117c2f52a672bca008f2c206ad8527a6 3894008 main/dep11/Components-s390x.yml.xz 3f40799bee1a72a060f7dff19efa7b05 13048320 main/dep11/icons-128x128.tar 6ac207d4fb6b76c25dc59edb50c3bf6b 11409337 main/dep11/icons-128x128.tar.gz 66ce5f075d189138824e736123711450 4878336 main/dep11/icons-48x48.tar 260bbc45bfa6b33e31399b4adb3b1f6d 3477622 main/dep11/icons-48x48.tar.gz 47dea6d08e37b4a5154a072f3ad92cf0 9378816 main/dep11/icons-64x64.tar 417f46677b9086f9dd0a425f0f39ee31 7315395 main/dep11/icons-64x64.tar.gz 180389879ed6715b463d05b637e191dc 6191 main/i18n/Translation-ca 8f8b7ffa4659d4f03b65ed28e69821f9 2673 main/i18n/Translation-ca.bz2 b4ef33a20d80c576c7b352e96a86e063 1205166 main/i18n/Translation-cs d70ae6198f35f876b3070d928d5cdba2 323247 main/i18n/Translation-cs.bz2 3fa5a10989da6ec5b19b5b6ba161b0bf 20240560 main/i18n/Translation-da e83f678061ca99aaedd2f20cb75bba77 4411163 main/i18n/Translation-da.bz2 9f5077418506388082a72c7023c56f8f 7801238 main/i18n/Translation-de a57e3821e975f45d21bf2388a190b770 1717951 main/i18n/Translation-de.bz2 a344219bf0eec9139d5270017ecfceee 1347 main/i18n/Translation-de_DE 0fe0725f74bb5249f15f30ce965142d5 830 main/i18n/Translation-de_DE.bz2 87bf9810c05aba15fb4aca6791feb73d 6257 main/i18n/Translation-el 002ddfc4187acd8414873fe9f0a6442a 1835 main/i18n/Translation-el.bz2 36467cceb9cb2cea759d49c8759be7f9 30246698 main/i18n/Translation-en b4a727f22675ec9db1426d7dbc7a34f0 6240167 main/i18n/Translation-en.bz2 0fdd8948881357f49ead0845c7e621c1 2261 main/i18n/Translation-eo 43bd21f8b5d52b955e509e5893eef37e 1196 main/i18n/Translation-eo.bz2 2ad9740f4bf39f163c04bd0b7266c1aa 1325929 main/i18n/Translation-es b4d4140461b4d6195e3337dcf541554f 317946 main/i18n/Translation-es.bz2 2f7f0aac6c4ae5bd9c1499fd612ef996 10093 main/i18n/Translation-eu 3178567e5f21fe43e4cf1f1a38ed6adc 3914 main/i18n/Translation-eu.bz2 d1e71d50a88504d6b48c27960250acae 269212 main/i18n/Translation-fi 9ca11408c191cfc5270f39467ed80f9b 75849 main/i18n/Translation-fi.bz2 945a63eed28af4c45fd5185b334b33b3 11857302 main/i18n/Translation-fr 06100e8db22b6d72d2c466bc85ea117b 2433064 main/i18n/Translation-fr.bz2 f543980d7c6e8335eb0bb5d00b787418 1427 main/i18n/Translation-gl 09c22bb0dfa3874802c4e7e4389f2b58 824 main/i18n/Translation-gl.bz2 363537eb238e19bd527554a2d1de2533 21069 main/i18n/Translation-hr 3fbd3535dcc2e805f0283d54bd38f5f3 4695 main/i18n/Translation-hr.bz2 5393df220c56a4a92b91b2cac6843067 65236 main/i18n/Translation-hu 61236a1bada04fd4ab090269498c5393 22243 main/i18n/Translation-hu.bz2 d8d93a0510fedeb68fbbdae0342520c0 3983 main/i18n/Translation-id 7542ee230bbc1f2f9f873c265b3b467f 1780 main/i18n/Translation-id.bz2 87ba73fdeb9bac4348a4be42b2386f32 24489940 main/i18n/Translation-it 9c9cd08156baf73f9f088bb97ac00662 4844227 main/i18n/Translation-it.bz2 0f39595a0a049759d0d50ead781f73fd 4511401 main/i18n/Translation-ja 74ff41ba40e19c9ceb4c607b122b7811 803966 main/i18n/Translation-ja.bz2 85c4f9ec1e8e2d6faab177ef030ad2aa 11879 main/i18n/Translation-km 46d57c586859cecf5c1a4470f666000d 2371 main/i18n/Translation-km.bz2 def6a2d200b3c67b6a1c497524d0a631 2606190 main/i18n/Translation-ko 3210a7e112a3f29ecf785ba05a78559a 584643 main/i18n/Translation-ko.bz2 d41d8cd98f00b204e9800998ecf8427e 0 main/i18n/Translation-ml 4059d198768f9f8dc9372dc1c54bc3c3 14 main/i18n/Translation-ml.bz2 904af013a9ba73cd72f71a1ca451be5a 1193 main/i18n/Translation-nb bf917a722cf4d90cf2f56acb8edb1b31 738 main/i18n/Translation-nb.bz2 cb57eb70e5645204174caec8edcc4a2b 174332 main/i18n/Translation-nl ad8c86dde21a892ff20203dc71eb981c 47973 main/i18n/Translation-nl.bz2 bc88d84933fd8ae64ea0a7ba32a1e814 2051811 main/i18n/Translation-pl 3095483ca3926b759de515651199283a 491993 main/i18n/Translation-pl.bz2 d1736cf50b7994e7c6ce66962b7f4b03 1074959 main/i18n/Translation-pt 7f9e024af1c410635fc69db5bf5d090a 272186 main/i18n/Translation-pt.bz2 c3453467a749e3888da35949b643835d 3306707 main/i18n/Translation-pt_BR 89726f5a5abac29bd3a6069e27019c9a 802734 main/i18n/Translation-pt_BR.bz2 b50c9c49ea0a9da73b0a76db38a36ea4 1717 main/i18n/Translation-ro 22696f68e30228ffbd84b26dbc821f81 982 main/i18n/Translation-ro.bz2 52035b6ff376a4d7c38eea8bbd406751 3058931 main/i18n/Translation-ru d6c7de740e63ee4ce0e2044a0d449804 494782 main/i18n/Translation-ru.bz2 2b383f6dbb23852965418241eda484de 5984088 main/i18n/Translation-sk 04f2970e8de7fc5a090b84ab700cbb23 1304539 main/i18n/Translation-sk.bz2 cf58326418b53f94289ad593878bfda2 323953 main/i18n/Translation-sr 096b962e3404fbc28ebfb174e7587136 58385 main/i18n/Translation-sr.bz2 366024c5bc4dabb550f8481c2d662611 85612 main/i18n/Translation-sv 22b0c4eaa8e59ee11318ce2e68953f4b 27320 main/i18n/Translation-sv.bz2 ced97abb44ee155f744680871aa5a6e2 14670 main/i18n/Translation-tr 233a8366a334283e9b802cae336ed09b 5362 main/i18n/Translation-tr.bz2 c8840c6e4bbe54b098d5b589e5d9e08b 3740343 main/i18n/Translation-uk 7ed20cfd2585b8f77be6e2bab7561133 576766 main/i18n/Translation-uk.bz2 2adb559c8ab8415644e43781db4f739a 21882 main/i18n/Translation-vi 82caa7c535a1c4c7589a7b1647017f53 6510 main/i18n/Translation-vi.bz2 f895594ce62c202132bbbe9ae32f1bc2 2007 main/i18n/Translation-zh 3d2be55ee5ef9a79e0db9f90acc449cf 1215 main/i18n/Translation-zh.bz2 91e9eec000876a989969a700ac7b3821 425199 main/i18n/Translation-zh_CN ab34838b3553d042d515eb65f5aa8816 113621 main/i18n/Translation-zh_CN.bz2 34208715b80dcbd5fd1b87874a6705d4 39965 main/i18n/Translation-zh_TW 6ed487c9d90ac9866174796ce73dec77 14859 main/i18n/Translation-zh_TW.bz2 c8730ab591a9c561bfbe29bb2bd721d9 58277 main/installer-amd64/20210731+deb11u7+b1/images/MD5SUMS 1a197cdc8ba7a3094159a1ebec0b24f9 78097 main/installer-amd64/20210731+deb11u7+b1/images/SHA256SUMS 8521cd018a0e0b50238dab3cf673c4f7 57705 main/installer-amd64/20210731/images/MD5SUMS bb4d5d5a421f536dcaa3f2e4fc96c1c3 77333 main/installer-amd64/20210731/images/SHA256SUMS c8730ab591a9c561bfbe29bb2bd721d9 58277 main/installer-amd64/current/images/MD5SUMS 1a197cdc8ba7a3094159a1ebec0b24f9 78097 main/installer-amd64/current/images/SHA256SUMS 026bc90f5673b695c093e88b6e0ec351 69049 main/installer-arm64/20210731+deb11u7+b1/images/MD5SUMS 5ef21176e2d62d993fdad8fe6f66d13f 94149 main/installer-arm64/20210731+deb11u7+b1/images/SHA256SUMS 8544dac6e811bff5ed42e276cf530ebf 68403 main/installer-arm64/20210731/images/MD5SUMS 7989c6f2e37aeda05d7dfc58de88d7f5 93279 main/installer-arm64/20210731/images/SHA256SUMS 026bc90f5673b695c093e88b6e0ec351 69049 main/installer-arm64/current/images/MD5SUMS 5ef21176e2d62d993fdad8fe6f66d13f 94149 main/installer-arm64/current/images/SHA256SUMS 9d5c1487daa7fbbc0eb09a58cd905102 20678 main/installer-armel/20210731+deb11u7+b1/images/MD5SUMS 9caca58b3425516dd16fec20f1ee05fd 28882 main/installer-armel/20210731+deb11u7+b1/images/SHA256SUMS 6e3afe07880cea11cee1a8ac19ce5d13 20182 main/installer-armel/20210731/images/MD5SUMS 350c18339820cfa3989e1297c80b9f12 28194 main/installer-armel/20210731/images/SHA256SUMS 9d5c1487daa7fbbc0eb09a58cd905102 20678 main/installer-armel/current/images/MD5SUMS 9caca58b3425516dd16fec20f1ee05fd 28882 main/installer-armel/current/images/SHA256SUMS b6629d5e5a8344e0905c72ed18aeaca4 64380 main/installer-armhf/20210731+deb11u7+b1/images/MD5SUMS 3e31a8a4a6eac90bff6befbe1dbfc3cd 92680 main/installer-armhf/20210731+deb11u7+b1/images/SHA256SUMS 3dca9930d681a0ba4186171684027ec6 64240 main/installer-armhf/20210731/images/MD5SUMS 869454c4efa0fcddd91e08ab8ccf9d3b 92476 main/installer-armhf/20210731/images/SHA256SUMS b6629d5e5a8344e0905c72ed18aeaca4 64380 main/installer-armhf/current/images/MD5SUMS 3e31a8a4a6eac90bff6befbe1dbfc3cd 92680 main/installer-armhf/current/images/SHA256SUMS d2556badb036046aff1f8d6eed468533 56840 main/installer-i386/20210731+deb11u7+b1/images/MD5SUMS 87137d3494aed456f81705c70f5a8560 76724 main/installer-i386/20210731+deb11u7+b1/images/SHA256SUMS 8932831dfc7fb479ada48f6936639179 56286 main/installer-i386/20210731/images/MD5SUMS 0ccfb273991e3302a49093743aa9032f 75978 main/installer-i386/20210731/images/SHA256SUMS d2556badb036046aff1f8d6eed468533 56840 main/installer-i386/current/images/MD5SUMS 87137d3494aed456f81705c70f5a8560 76724 main/installer-i386/current/images/SHA256SUMS 998868016e1fdfa2a145942395800280 630 main/installer-mips64el/20210731+deb11u7+b1/images/MD5SUMS 7aa9b76c5e09c5b05445ffa606fe53db 1026 main/installer-mips64el/20210731+deb11u7+b1/images/SHA256SUMS 9533fc15e5b64180b5ad78129a5230b2 627 main/installer-mips64el/20210731/images/MD5SUMS a776640760fbaacfb1681f3abd0fb40b 1023 main/installer-mips64el/20210731/images/SHA256SUMS 998868016e1fdfa2a145942395800280 630 main/installer-mips64el/current/images/MD5SUMS 7aa9b76c5e09c5b05445ffa606fe53db 1026 main/installer-mips64el/current/images/SHA256SUMS fa571598ee1e33c6b2dbee7e30bbf665 630 main/installer-mipsel/20210731+deb11u7+b1/images/MD5SUMS 6755ade8ad0a3238ef992b2b5b055c60 1026 main/installer-mipsel/20210731+deb11u7+b1/images/SHA256SUMS c3a9b6724a2ff5e2abf741f47a7600da 627 main/installer-mipsel/20210731/images/MD5SUMS 01da3e1833ca954309023210e9b16159 1023 main/installer-mipsel/20210731/images/SHA256SUMS fa571598ee1e33c6b2dbee7e30bbf665 630 main/installer-mipsel/current/images/MD5SUMS 6755ade8ad0a3238ef992b2b5b055c60 1026 main/installer-mipsel/current/images/SHA256SUMS a3b2d71556d4030ba67ddd5e2edb63cf 576 main/installer-ppc64el/20210731+deb11u7+b1/images/MD5SUMS fb4c51ffbc1c1c0de08e035cb06a0c63 972 main/installer-ppc64el/20210731+deb11u7+b1/images/SHA256SUMS 37515f49026f1bc4682fefba24e9decf 576 main/installer-ppc64el/20210731/images/MD5SUMS 89c70369e7ab670f721a135f055d81a4 972 main/installer-ppc64el/20210731/images/SHA256SUMS a3b2d71556d4030ba67ddd5e2edb63cf 576 main/installer-ppc64el/current/images/MD5SUMS fb4c51ffbc1c1c0de08e035cb06a0c63 972 main/installer-ppc64el/current/images/SHA256SUMS c89c26c2cc9d407be87915ad5de99f88 374 main/installer-s390x/20210731+deb11u7+b1/images/MD5SUMS 0ac8638a6ff89d2f8e3ceb1c51b39eab 674 main/installer-s390x/20210731+deb11u7+b1/images/SHA256SUMS 580b19117c2b6c6f2a8ad8aca5132826 374 main/installer-s390x/20210731/images/MD5SUMS da16ad53b0185c6e48397e05f2efadfc 674 main/installer-s390x/20210731/images/SHA256SUMS c89c26c2cc9d407be87915ad5de99f88 374 main/installer-s390x/current/images/MD5SUMS 0ac8638a6ff89d2f8e3ceb1c51b39eab 674 main/installer-s390x/current/images/SHA256SUMS 89ad4d3b28d51f39938cf10575544163 117 main/source/Release 4dc0d4fb57d31a820d50565ca5904136 44655922 main/source/Sources 6ca64fd70ce2f771595248c67b1d63ab 11429086 main/source/Sources.gz 632766a36d87c6379182819386228c24 8633788 main/source/Sources.xz 5f624011d3b0a82f23445c2861deac99 17347341 non-free/Contents-all c64dcd5c2b4db85f729afa8623adb65a 888157 non-free/Contents-all.gz d6bec1f2c68aa61c10d5ea048bb61876 1097448 non-free/Contents-amd64 f5a3b5d556d2ac2276e434d47321c42c 79655 non-free/Contents-amd64.gz 2a3fa76ebbc2b8ce1dc696fd4f93d5cf 499970 non-free/Contents-arm64 6fbffff6347fe5e6e7099295803f549c 37376 non-free/Contents-arm64.gz f408ea79e9570389d5ee84acf709fefe 95417 non-free/Contents-armel b7a69ebcb774fa413e4016bb93c3d044 9298 non-free/Contents-armel.gz 6778fabc7cec1e4431b4e6354d7c6331 146124 non-free/Contents-armhf 146fba98ac2f400fe25facd0ca7aa193 13502 non-free/Contents-armhf.gz c2a617bfa92c1ae1471d92c59fe2e012 343198 non-free/Contents-i386 1550b2598d6a74262e40f69cc64ed0e1 29072 non-free/Contents-i386.gz 900df746b6e7accfd8883d31c7d28313 91215 non-free/Contents-mips64el 7c382180d55972ff768bb8a05222a412 8686 non-free/Contents-mips64el.gz 904ab7d197244bdfdbf6b58bc61d09ac 92244 non-free/Contents-mipsel 73868036dab5f62f60ad63ebfb7ca253 9026 non-free/Contents-mipsel.gz 9ff21fb911bfd562eb84f85d9adda009 716110 non-free/Contents-ppc64el 5c487a4250d7e24f4cce14e8e7c430f0 49881 non-free/Contents-ppc64el.gz f3aa91e39f1d170310ec9820ea4dae2d 74537 non-free/Contents-s390x 2b363c4c14b66b56f3009f85c29415dc 7407 non-free/Contents-s390x.gz 28092fe18d286a60369b2baf177a3b66 10803369 non-free/Contents-source a1340038124c66a82eb9afd4e0a5b39e 1063443 non-free/Contents-source.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-all 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-all.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-amd64 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-amd64.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-arm64 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-arm64.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-armel 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-armel.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-armhf 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-armhf.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-i386 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-i386.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-mips64el 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-mips64el.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-mipsel 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-mipsel.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-ppc64el 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-ppc64el.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-s390x 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-s390x.gz 28683b0c800362ab66657f988f8fe158 189021 non-free/binary-all/Packages 8b503f66350a43348e728ef668a3e66d 50928 non-free/binary-all/Packages.gz 89e1a28553ba1bf59ef7a537d0e13dcd 42996 non-free/binary-all/Packages.xz 7e31516542d9449a20d6d5a5be387724 118 non-free/binary-all/Release 48fd35f0f54926f3b555aca2d9cc267c 545576 non-free/binary-amd64/Packages f4a7af068e39f558fb3c7d38d7227d31 122225 non-free/binary-amd64/Packages.gz 90b0a4d2ddb8c4e4a507459f79006f8a 97772 non-free/binary-amd64/Packages.xz e1a343e13638a8191104cc84d9c87347 120 non-free/binary-amd64/Release d1b662147ba2a93fda8daa87bcc45a4f 381335 non-free/binary-arm64/Packages 0ea4ed22af6d2313b0e15670783ff965 88201 non-free/binary-arm64/Packages.gz 471ad96a8a2139576049b8bc0a7541de 72980 non-free/binary-arm64/Packages.xz 9e926156e80b4e4db84524d2f0079024 120 non-free/binary-arm64/Release 0967ff1cbab012d79d544d2fc19bcb3c 227933 non-free/binary-armel/Packages 66f87c4a0607b4d535045f41bb1debbf 61822 non-free/binary-armel/Packages.gz 943edb5f2d977c5e883e123d7a162a3c 51800 non-free/binary-armel/Packages.xz 096a48f395e2487865b756ea3d0e20ff 120 non-free/binary-armel/Release 11aef19231277b7df07bb88b31da40fb 259156 non-free/binary-armhf/Packages f084eff9f9e23dd4f071fc6caf167026 67317 non-free/binary-armhf/Packages.gz 478795a629bddb465e832a8c15908d23 56272 non-free/binary-armhf/Packages.xz b94819d3bb5bb39f9abcf15388d47bf3 120 non-free/binary-armhf/Release cf0f27353a145dc9a999d6ac8f2b242d 422388 non-free/binary-i386/Packages cac7e560af4f05675b65252d54968a1e 96319 non-free/binary-i386/Packages.gz d528af0816ff9a8b491442be615e0875 79344 non-free/binary-i386/Packages.xz 4a714713c871406dae3fee358bf4525b 119 non-free/binary-i386/Release b241349c71327389608d1ed7805fb917 225506 non-free/binary-mips64el/Packages 79ea1e07e0c12ca9587d966e90a803d3 61024 non-free/binary-mips64el/Packages.gz 800788cecc80de3a8dc8555edc4e1f3c 51124 non-free/binary-mips64el/Packages.xz 9673c21044a83dbab7dd0cc54a4e02c6 123 non-free/binary-mips64el/Release 5637ea382ea6ea47628b489854f51823 226162 non-free/binary-mipsel/Packages cb900ebc58b732e246dad1c05c2da62b 61277 non-free/binary-mipsel/Packages.gz eefd4b08c8da7bb89f71627c9f05a04e 51364 non-free/binary-mipsel/Packages.xz c3acf902cc79cfb97370b0efec244dea 121 non-free/binary-mipsel/Release 4404ce86106e7e32bd47bd465f954e8f 381597 non-free/binary-ppc64el/Packages 9e8c1c8f825dd79ed1d335608297770e 86900 non-free/binary-ppc64el/Packages.gz ffe9119e39ab6813cdd7dd7b5b8299a0 71812 non-free/binary-ppc64el/Packages.xz 79b2651c4e8f6dc350c53e634f30ef2d 122 non-free/binary-ppc64el/Release 205f9ec14fe81d12021eba70ac927040 220570 non-free/binary-s390x/Packages 73a6b1dbd8f6c0ffbc4cb90c8737651b 59856 non-free/binary-s390x/Packages.gz d4f95c7b3fed2787ebb231f6e8fea4ef 50216 non-free/binary-s390x/Packages.xz cf48e148549473e729455b280f93e43c 120 non-free/binary-s390x/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-all/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-all/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-all/Packages.xz 7e31516542d9449a20d6d5a5be387724 118 non-free/debian-installer/binary-all/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-amd64/Packages.xz e1a343e13638a8191104cc84d9c87347 120 non-free/debian-installer/binary-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-arm64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-arm64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-arm64/Packages.xz 9e926156e80b4e4db84524d2f0079024 120 non-free/debian-installer/binary-arm64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-armel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-armel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-armel/Packages.xz 096a48f395e2487865b756ea3d0e20ff 120 non-free/debian-installer/binary-armel/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-armhf/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-armhf/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-armhf/Packages.xz b94819d3bb5bb39f9abcf15388d47bf3 120 non-free/debian-installer/binary-armhf/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-i386/Packages.xz 4a714713c871406dae3fee358bf4525b 119 non-free/debian-installer/binary-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mips64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mips64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mips64el/Packages.xz 9673c21044a83dbab7dd0cc54a4e02c6 123 non-free/debian-installer/binary-mips64el/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mipsel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mipsel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mipsel/Packages.xz c3acf902cc79cfb97370b0efec244dea 121 non-free/debian-installer/binary-mipsel/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-ppc64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-ppc64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-ppc64el/Packages.xz 79b2651c4e8f6dc350c53e634f30ef2d 122 non-free/debian-installer/binary-ppc64el/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-s390x/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-s390x/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-s390x/Packages.xz cf48e148549473e729455b280f93e43c 120 non-free/debian-installer/binary-s390x/Release f7208886e345a2c1c5681b7bc1f891f3 278293 non-free/dep11/Components-amd64.yml ab8bcc71919bb29e6a367d9058dc0125 29634 non-free/dep11/Components-amd64.yml.gz afd21b4c476c6b604c4f998d90383234 17904 non-free/dep11/Components-amd64.yml.xz 71e3cebf69c369e3d4e6b64e48fe037b 271451 non-free/dep11/Components-arm64.yml 4b40bf8ff6579f425fd308cc4f32bb26 27686 non-free/dep11/Components-arm64.yml.gz 04fa2b6c4dc8d23f6ee6334754b725df 16392 non-free/dep11/Components-arm64.yml.xz 678290cc20fe4c69fac625c25f48577f 271451 non-free/dep11/Components-armel.yml b76376c24cdd9bb014e63503830766f8 27606 non-free/dep11/Components-armel.yml.gz b431acc1b0f700a021a3ab1305bc3c33 16448 non-free/dep11/Components-armel.yml.xz 7f659804cad02381ed7735779c211771 271451 non-free/dep11/Components-armhf.yml 0221ab3c0654617c6de5d2b74eac7b15 27691 non-free/dep11/Components-armhf.yml.gz 2df1dfb4d502d5c01f744bac99e8a0bc 16364 non-free/dep11/Components-armhf.yml.xz 1422b7cb028418049315374e46dcbf86 280613 non-free/dep11/Components-i386.yml 7a014ddef58173efeb07ce9d7b866331 31098 non-free/dep11/Components-i386.yml.gz ee2f702d30a2274d969a8e9044da54f2 19156 non-free/dep11/Components-i386.yml.xz 2f39022b38ebd28b86acd148ad0389d2 271451 non-free/dep11/Components-mips64el.yml 5e839450348a20fc9f81cdc9dd0b9663 27765 non-free/dep11/Components-mips64el.yml.gz fbf40f634081acbde994e89d8731d159 16380 non-free/dep11/Components-mips64el.yml.xz 4ff7e301bb5eaab539783f39c24b421f 271451 non-free/dep11/Components-ppc64el.yml d7c37af104343f2eb2b10a0980c96661 27592 non-free/dep11/Components-ppc64el.yml.gz afabe491b91df1be19287ea4e978e7aa 16576 non-free/dep11/Components-ppc64el.yml.xz 05dc5f141a7ca96f1aae6d571dd37361 271451 non-free/dep11/Components-s390x.yml 4a5b9e250991cd5d661db03f4bebefa8 27558 non-free/dep11/Components-s390x.yml.gz b0593a88d870f066f1a83dfb382e09c5 16356 non-free/dep11/Components-s390x.yml.xz 40dd67e0e1f81416405be5c0dc8ee47e 8192 non-free/dep11/icons-128x128.tar b117213e4fd39f9c75c1699ebaf3d610 2394 non-free/dep11/icons-128x128.tar.gz 08a465949d80332d065e6f4ec8459930 4096 non-free/dep11/icons-48x48.tar 49466a3c36fe0d0cbb5940896da60960 741 non-free/dep11/icons-48x48.tar.gz 5d6e61a41610797276e5b6f16d60f7e1 36864 non-free/dep11/icons-64x64.tar 0196f7b979db4111a6d9b988e63101a0 27667 non-free/dep11/icons-64x64.tar.gz c423c38128e8f1d7984682751173441c 572893 non-free/i18n/Translation-en 65a9781186757af5a261165878a7f9b0 92419 non-free/i18n/Translation-en.bz2 d48a4039dfcadee2dbc49be8216a78f3 121 non-free/source/Release 1ebf108ffd532e93efc36f22d900441a 360307 non-free/source/Sources 85f6ca3b8dfaa5af893d96ea4b759971 98323 non-free/source/Sources.gz 10afbe839c1da98bc50d6dc6506652a8 81280 non-free/source/Sources.xz SHA256: 3957f28db16e3f28c7b34ae84f1c929c567de6970f3f1b95dac9b498dd80fe63 738242 contrib/Contents-all 3e9a121d599b56c08bc8f144e4830807c77c29d7114316d6984ba54695d3db7b 57319 contrib/Contents-all.gz e60f82140294e076f97a4148cfd8e594ae808c423d40b62be455bb28af8fb6d8 787321 contrib/Contents-amd64 845f71ed2a0a3ea784c355427362164cb316b01e6ce956a38ea95a001711709b 54668 contrib/Contents-amd64.gz 1ad2b49ab401affafeb146c2badf94f1d699abd27f52b57d5e4b0fe3d37c9682 370915 contrib/Contents-arm64 5f54b4d15ca5a9308eee238da9fa9512dcf8ec15a55cc22fce4efc3142146c01 29596 contrib/Contents-arm64.gz b4985377d670dbc4ab9bf0f7fb15d11b100c442050dee7c1e9203d3f0cfd3f37 359292 contrib/Contents-armel f134666bc09535cbc917f63022ea31613da15ec3c0ce1c664981ace325acdd6a 28039 contrib/Contents-armel.gz b5363d1e3ec276a0cb10bc16685bd02bdc330719d76c275bebd344adaa91583b 367655 contrib/Contents-armhf fc4edd280f2b254dbfa98f495e5f4ca6047ec9a1539ccb8754a1f93546ea32b5 29236 contrib/Contents-armhf.gz 77d465435ba8f5bad03b76624835f91e9ebf3bb09b124ab1a06e70c8b2629b30 407328 contrib/Contents-i386 e4a82b31ac7b5b139fd3bd93ad466de75f7bf7d54410967253044895e41c36fb 33556 contrib/Contents-i386.gz c0efa60eaa3b47bd93ca71220c6fc734d54b257e16bb6dd8dde43ca722f242dc 359402 contrib/Contents-mips64el 4fccf5298ef664c2de3dc7eeb203eefa3bf8ec82b95b1c696b856a43af35e395 27962 contrib/Contents-mips64el.gz db2388b4b8d300fdc265fe064288a8de5f69958b06ed6cfeff3b8528e719015b 360549 contrib/Contents-mipsel 27db69688406433748363f4a70cac108f29b99555a6d5dc3eaba6b2e8b526dfc 27942 contrib/Contents-mipsel.gz e62412c1f585461c8ae27d4d2a79b82c27dba109ac19df81a15ae7f53369cf65 370025 contrib/Contents-ppc64el 8ac6ff54ba23486d9c139ee79a6296760dc20022209ffc321296967717a37fd2 29381 contrib/Contents-ppc64el.gz bb1fdc3fafd28760f57d951e96a150e8ec7d6b0fb75443de93f08a61ffbd7042 357860 contrib/Contents-s390x 009373ff8cde80de63a4303b8c6eab79af34d6c2c0c831d1b38e1f9329c396cc 27518 contrib/Contents-s390x.gz 7d79e95f92007f2885bba7ff9d40a81cefea96959cb090dc7cde26a77e7f1ea5 6722669 contrib/Contents-source d6655657ff285c9372e18b0ebff346e922694de31669d6c0260e789306841e9d 469817 contrib/Contents-source.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-all f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-all.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-amd64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-amd64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-arm64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-arm64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-armel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-armel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-armhf f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-armhf.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-i386 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-i386.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-mips64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-mips64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-mipsel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-mipsel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-ppc64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-ppc64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-s390x f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-s390x.gz 70d58353b3bc6083f3946ebcdc1f150204988bed60df8c0389fa23b26924adcd 103239 contrib/binary-all/Packages 9baa8f0dbe243eea5e03bc9551b0e5774ea0ba690db28ae63d1f81cd6e16aef7 27385 contrib/binary-all/Packages.gz 24cb5963261a9cb0a4671061d65ee51e211e00ea754e4f5ec6426a1a78745ec1 23916 contrib/binary-all/Packages.xz 93a2ce91dbee932c8b48caae660d67b864819f239de1cf9c85cbfeb3c450e396 117 contrib/binary-all/Release 25bba54443595d2760419c8873b026880ad3553697b4254f0473b7c859c3526f 231878 contrib/binary-amd64/Packages 05b545380de2e24307c4b33497327a397b5fac53c53c2479d487280c69c55b7b 60884 contrib/binary-amd64/Packages.gz 572aa5c4767342e411f9ec261ebb871a48da20400d37e9f960c0f3960a26fc66 50588 contrib/binary-amd64/Packages.xz 4c337ceffea66616199c9d6f6f0996dac105940b4e220425a12c9ecba87a1ff6 119 contrib/binary-amd64/Release 7ab66ca6c3c1f575100f8e39fee460115ba8292a489c07e9ea1b0a914e47f67c 180884 contrib/binary-arm64/Packages 4da911f1c6926b85d6a9a025d73be907124db4a3e99872b0128ad2187a5af5ef 48958 contrib/binary-arm64/Packages.gz 07b68a663f305c1a676642f078a3d9243072e2f2402ad87c405f0a4c7744cab1 40964 contrib/binary-arm64/Packages.xz 1b6ff9a1c182ed456e4aeff56a54eddfb128ce6c39877b70769dd79e012143f6 119 contrib/binary-arm64/Release d353d3f7b451cb07472d111221866fd89c6e7b28ad0fe66044f35e2eca6189fc 163042 contrib/binary-armel/Packages 5333591cd2ee7e750d864f875799c83b4985f0473a02e525365db3fc5b27ab36 44389 contrib/binary-armel/Packages.gz 6493591c5f010aa3b50e7052c4746f6afe40a0fd31ffcce08c706aec6e7b672d 37452 contrib/binary-armel/Packages.xz 04ff4b12d802b8291b4408a1435e0e11424b96e1628d10981b18d7bfbe481708 119 contrib/binary-armel/Release 75d98358dbea38501853ae9cd7a2da4f84d02eb4543bd9e96f0c3e6cd5945533 175566 contrib/binary-armhf/Packages fde856e3b07624cb5e3d6c11dd450aae8e56f38646c4b3f3b7cbe0423f78970e 47805 contrib/binary-armhf/Packages.gz c572038b5ced50f74da2baa5cda8150846cface0b285218336f6af4e1365b9b0 40220 contrib/binary-armhf/Packages.xz d37bedd8d7cdad30b0f6699f0b0c12d60cf2a9a24866e5a256a957d625b62b8b 119 contrib/binary-armhf/Release 6b9d6d64b15686f83bf58c5e2255bdef26a5f2cdd97c76b047ea46f533aeb0bc 203514 contrib/binary-i386/Packages 010b321fd585b2d1c45512db80e60aefdd0fc7bbc60a53e1594ba9ad5f9ba45a 54100 contrib/binary-i386/Packages.gz a17c01bbbba0f218b3a38cb5b7fc3053a7cfb6364453b46b6b80687d11eab142 45340 contrib/binary-i386/Packages.xz 4ce72f7efaa89af0624897fe2cd8495e137d4e5e0f5320cb44de27fbc3b02986 118 contrib/binary-i386/Release 4c71f56a967f6f390c1e6d381f399d74da5a545c8906f014fe805859ba9ae55c 163507 contrib/binary-mips64el/Packages 49f3fc82266f184e331b2b0ea0762540b8ef68486f299a5673b247f8c03d3858 44652 contrib/binary-mips64el/Packages.gz e0c365ed89f4538b36ab3366293d3b9f4e8472b9537d91b770f650650021f4e1 37496 contrib/binary-mips64el/Packages.xz 59e8e1e1ec5e0d469be59b6d3321aba3f9ddd686e440bde74616b2acce355b41 122 contrib/binary-mips64el/Release a951b730b4a059ef33073627d50a40f204591c3a5348fbe1c5e3b21782a77e5a 164647 contrib/binary-mipsel/Packages 662a2fb412beb7130ef5ba0440ec368825d21713392a55ea33048673bbcca3a0 44883 contrib/binary-mipsel/Packages.gz 7a01af1780b68648eec3923fbe4fe766e210e83f0ba8b03f6bc8b9a8d4c0169f 37816 contrib/binary-mipsel/Packages.xz 9df253300a3c33585a18f1c8b91018a558e04a222a70ce8072f76ea2e2b27ad1 120 contrib/binary-mipsel/Release 8ff5ce44abf0d9fba97b3ce63b2d41db58d24b463dfe23cf06069a71724f7047 180387 contrib/binary-ppc64el/Packages ddf5d43553c9af8a6dfa0ff6f51236dee72fe15d2a09ecc9212bfeee5e667e92 48843 contrib/binary-ppc64el/Packages.gz 84cd02fcb4a610501538fd06ebf77a67ef7badcbc6f5b1f338c6d013329ea38e 40808 contrib/binary-ppc64el/Packages.xz 57f78f401d86eaadc5fe6ca190f162e4a0fc1e77021a6118f27aab68db0d7f82 121 contrib/binary-ppc64el/Release cfc032377fc264eff4a6319ecfd2722e95de7364a63b29eed53cc78603a8a8aa 162250 contrib/binary-s390x/Packages 72be2806452fee7d70ef80ffac98e3f408e7389dbbbaaa6d9228f48a6733b773 44334 contrib/binary-s390x/Packages.gz 9a14a52c690b24eb92939192abc4d4e8b23a2347a838232774016ac79c3d8ec8 37244 contrib/binary-s390x/Packages.xz cb54af7d630a4046eb41cc3096838019e16b72f3c0f505136788bcf09fa632c5 119 contrib/binary-s390x/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-all/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-all/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-all/Packages.xz 93a2ce91dbee932c8b48caae660d67b864819f239de1cf9c85cbfeb3c450e396 117 contrib/debian-installer/binary-all/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-amd64/Packages.xz 4c337ceffea66616199c9d6f6f0996dac105940b4e220425a12c9ecba87a1ff6 119 contrib/debian-installer/binary-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-arm64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-arm64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-arm64/Packages.xz 1b6ff9a1c182ed456e4aeff56a54eddfb128ce6c39877b70769dd79e012143f6 119 contrib/debian-installer/binary-arm64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-armel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-armel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-armel/Packages.xz 04ff4b12d802b8291b4408a1435e0e11424b96e1628d10981b18d7bfbe481708 119 contrib/debian-installer/binary-armel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-armhf/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-armhf/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-armhf/Packages.xz d37bedd8d7cdad30b0f6699f0b0c12d60cf2a9a24866e5a256a957d625b62b8b 119 contrib/debian-installer/binary-armhf/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-i386/Packages.xz 4ce72f7efaa89af0624897fe2cd8495e137d4e5e0f5320cb44de27fbc3b02986 118 contrib/debian-installer/binary-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mips64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mips64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mips64el/Packages.xz 59e8e1e1ec5e0d469be59b6d3321aba3f9ddd686e440bde74616b2acce355b41 122 contrib/debian-installer/binary-mips64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mipsel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mipsel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mipsel/Packages.xz 9df253300a3c33585a18f1c8b91018a558e04a222a70ce8072f76ea2e2b27ad1 120 contrib/debian-installer/binary-mipsel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-ppc64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-ppc64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-ppc64el/Packages.xz 57f78f401d86eaadc5fe6ca190f162e4a0fc1e77021a6118f27aab68db0d7f82 121 contrib/debian-installer/binary-ppc64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-s390x/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-s390x/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-s390x/Packages.xz cb54af7d630a4046eb41cc3096838019e16b72f3c0f505136788bcf09fa632c5 119 contrib/debian-installer/binary-s390x/Release f0a51e6d75f883bdecf739b214104a17dba111de8b42022f6b8b053870c83851 119152 contrib/dep11/Components-amd64.yml e14a1bb3690a18ec7c5b7997fabf4d8d4fa633efdf84a25e071a1f62a2c064b2 15579 contrib/dep11/Components-amd64.yml.gz 58921318632f77413bee8d9e980689f8f139eb1169b5ce201da06e6f280d485f 13564 contrib/dep11/Components-amd64.yml.xz 26538634f90cd6f04a6be602151fa6a098075c3013b66a81439a7bbdbfaa40f5 113437 contrib/dep11/Components-arm64.yml 840908ab753dba952e073216007f93d351577792911dcc09a15a16abfc32c8a7 14251 contrib/dep11/Components-arm64.yml.gz 3afec5908036aa2d47b9a9a33c13eca12bba1aaf8d8bbb06ffb1627e93f6526f 12480 contrib/dep11/Components-arm64.yml.xz fb35649f6c32b71b9d85388c2c238011161c250df5c62e2c4d3446e369dced4c 113437 contrib/dep11/Components-armel.yml c305f1c0826e0414bbf36524d8b0fc2723ffc0fb222275e1e1728914fc334c75 14029 contrib/dep11/Components-armel.yml.gz fe15a53774801f8d9cb04aa8324cbdb9d741ec75ae0999e033873458bd6160b0 12524 contrib/dep11/Components-armel.yml.xz 0ed24b6d7ff891c82697497dddfbbbb6818c168c55b41ae710e9cc9240d0d9b2 113437 contrib/dep11/Components-armhf.yml f5260cdac915ff5eba0a48757c93f8f8b6421a673e641285f43d83f62be3eb8c 14127 contrib/dep11/Components-armhf.yml.gz db97becd2ab6a05bcef05d824b89080a1e7c03a69735df3bf5945f6989a9e504 12480 contrib/dep11/Components-armhf.yml.xz 9adf35216113140c31c2e9c169a3eaa465044f41f8803afaac955c467a1e5a49 118972 contrib/dep11/Components-i386.yml c1d4ea9c0ac26f2b62d45c8c595ec9a5bc1c737b50634d7f86a4bfac17c9b180 15566 contrib/dep11/Components-i386.yml.gz 51ff60d5f02b46e08acea4054484f5c66d721c19beff4857cb2570f43e881a69 13560 contrib/dep11/Components-i386.yml.xz 50b6970af7de299a90ac651cceb6cc011e8d165ea0701f7b1c9daf6c1be485f0 113437 contrib/dep11/Components-mips64el.yml 78aad16ddec6b18d30ce4e20f52008f72efc78ba55688fa462741f4bb514043f 14056 contrib/dep11/Components-mips64el.yml.gz efb0fb003bbd3997128bef56f12104872604fad320b38fd99bca25e68210d98e 12500 contrib/dep11/Components-mips64el.yml.xz 05c2268c20e748baf8da20f7169918e2f6dcffb6e4f6dfc22829607cec7ea564 113437 contrib/dep11/Components-ppc64el.yml 19f600014e245e7d07762b7f07d8de6884b1208a280a19274e56b4174931082a 14219 contrib/dep11/Components-ppc64el.yml.gz dc8b525d7043ba3a85154ad39d0c809e7215c5b2f3865efbd94ff3daabe54810 12496 contrib/dep11/Components-ppc64el.yml.xz 5d43b650d261ac23815d98e9a4f644d56f4113e63f8a42b1558ff1c82e925d2f 113437 contrib/dep11/Components-s390x.yml c1811e0538dad96441a4172e661b9ef7fca9c05d86c4b157a66046bf49aa70e1 14050 contrib/dep11/Components-s390x.yml.gz 42356b4c04801189947748d6fce6e28e356a114869a7895e4921a3b4901e678c 12488 contrib/dep11/Components-s390x.yml.xz 641e9a50f98d7e4921102164e7737b095c9faead09f6de4459086b598b3bf0d0 271360 contrib/dep11/icons-128x128.tar 34b531c5292651ac5a18d0477bb8cf1420f3d969ad73d45fd596641d768b853d 195507 contrib/dep11/icons-128x128.tar.gz fa3a19603046c258e647b0c1fcdc6110f0b5c1f2801ee950eb1261e8c02e03d6 83968 contrib/dep11/icons-48x48.tar 28a6f153e56e9b567cc7fc03d6faa6dfb8480ee3f36e0c8d9646e4de3898480b 47168 contrib/dep11/icons-48x48.tar.gz d882fc33534a8677ed8d3ecf81f7a076fa57e8e8135bf586f8af20371edb195b 138752 contrib/dep11/icons-64x64.tar 45c8eda64d05f1feee0040809128760f9489665d66bed0502cb179fe0ec79f6e 93294 contrib/dep11/icons-64x64.tar.gz 094badc305c90db005324c484a55d88f14dfc805aa429856a5863a96518a88e8 192685 contrib/i18n/Translation-en ce7d3d607194cdfabf421c313030e88876ee899d5cd01f5b023cfdc0c0ed0f40 46929 contrib/i18n/Translation-en.bz2 b89a3b9258ada994f8857f734110206864802d179201da6fa97a666db306ada9 120 contrib/source/Release e331ac856d30949d3d70b299678f1f23462785681c70a62205ae35903d2c50d0 178776 contrib/source/Sources b34bb0d3527f1086ae23a6d2ae47bf790572a7d07ff0ad444f0f2c68afd3c504 51355 contrib/source/Sources.gz 99262e6c7f527f6654eb8e8b3415ee29fa5f2669d9bc22ce95881422b4b9b603 43208 contrib/source/Sources.xz 2400074e2a3897ad55b2e0e110b3ad66af9446b0cb77e28c7d5c92abf0a60db1 477769406 main/Contents-all a61ae2ae233b5eb73a624cc09c8df2eb3beab0ff44fd7cc75d2e64eaf36d2204 31069218 main/Contents-all.gz 226a3117b453b3350ee326fa65963b4936e6f5f0f0baabfc71ebe9458b3a5735 129058022 main/Contents-amd64 ee49ff0f5accae61de15bab5f6afd31d6b0b4676d59c9930fbe6dc24ed54954c 10270460 main/Contents-amd64.gz 13b617dbf9aee8e874fe709647f47bd2ee3780f4cf7c717f33aa7e1cd58d5e3c 122426895 main/Contents-arm64 68d31c4707f80bb72cd02c1276b53e22b5c0175a7f46bf75da6eecb754f8aff3 9831920 main/Contents-arm64.gz 5586eebc2846a2c4537cdb9020b216dd67b8c0eddc5a3bb8a9a0a6155e5946d5 104683113 main/Contents-armel 780507976f07c70aa2e787b9a6f9cab2ed8b1aed99b726906677d8e4ce1c8436 8703570 main/Contents-armel.gz 6f02632c558a77c4d6a78d64b437bc1c25857a4d04250abb51c5f13b3e86c119 113716591 main/Contents-armhf 22f19d2f3ae739ba4f7b0d0bf2effab552e64aa65c8a236b16c069e9fb8e5e90 9305906 main/Contents-armhf.gz 1c9cecfb8e79dfebf5d5cf0dc17271c2419fa72a4ef6e3b4b9e5ef1e3acad18c 129088857 main/Contents-i386 b826bd0b623bdce4568f0f1f8205c8f6f4e50b8ecfcd99a3b26bbddaf3900f8e 10208982 main/Contents-i386.gz 2a03448109546da0c72c31d0a534637306106e2195bd10b58aa2237ea60095f9 111097071 main/Contents-mips64el 147af2223dc310a089b0d18c820421f926d33e24ce2d0dbc6b20203c35cfffb7 9042221 main/Contents-mips64el.gz 6ef7f5d32e074dfe0231fbb8ac14f3cc67b511f924ec502736afe36cd549774a 112593872 main/Contents-mipsel a28b893a37dd761f6c95c0f6c722b9ac5324869d91bfc97cd7a1270159ac939e 9178325 main/Contents-mipsel.gz 720f513250bebd466149094ff4ca8f8e1b412810a218f1cddfaa31163577f44f 116027632 main/Contents-ppc64el a852312c04f59070951821eda6893270b28d23e12977f77a0933cce2882547e5 9355024 main/Contents-ppc64el.gz c92fc53215a097d7be1cc62c20946a4744221ba8dd58f62a81258fa79021aa06 103638209 main/Contents-s390x e1ed13910c59f0df90724c116450ac3aa2936a2d89497bbeb263993b9e767102 8711885 main/Contents-s390x.gz 19cb2eeeb6bb6459bf824cfbe9a82c44298fbd2ccb614ad130583fb5b07f3be3 690410830 main/Contents-source 2d5b1d50f3f42a073f6b27127bdbc0e19870188aecab8417dc32dde30138fbe1 73501881 main/Contents-source.gz b709d41e19af82147c367d90a74eae144ab18744d78817b6395fc1344fb99c76 157382 main/Contents-udeb-all f9801d96354f0b11d5357633cb9068dff1f39b9210eaeb70455db63ee0ecbdbc 13516 main/Contents-udeb-all.gz 88d816aa94f2071b483a84751d8109af7e89e049d9a5d690e2fc75a1fd86a9dd 477050 main/Contents-udeb-amd64 1344217ca4f19362a2bcbeb119e0a6d36e853481086431794142a930b46b13b8 36011 main/Contents-udeb-amd64.gz 5860a70ba4852152099c974ee16e92c0a935f6f96257204313ca99e8169826fe 508817 main/Contents-udeb-arm64 71a73fbf6e739034fd57e1a8255565d260b91cbce409128dcc69fa059623dcd2 38139 main/Contents-udeb-arm64.gz b4326a16088882aa0a038240624002e1994e232d98f4194b65907be2f94270b3 323083 main/Contents-udeb-armel 53c51078092e821f51bfa9477f35bd2a2148f045b5f6ae06a42b4ac79d440c42 25477 main/Contents-udeb-armel.gz e85592b3fbaaa08298eb08c7ee40c80c3826b961f3fcee0de1b6cedc0bf283aa 579793 main/Contents-udeb-armhf a9694e389e0c7eb23c9bad861b0f07db9114a4f4abf4648081b7640783c1e52c 43153 main/Contents-udeb-armhf.gz 286e7790529e1012095eeedadef806ab30696dbf3ca55ecb55cd91247d239287 751383 main/Contents-udeb-i386 bbe85229c4d8e20b737bf432e365a3efd51fcf557df061db147e9f63a322b69f 53984 main/Contents-udeb-i386.gz fcc311dbf697321971d9608ffc05555edbce48bd126b6d1d2b7bcd9a8eab0a25 760534 main/Contents-udeb-mips64el 15bcf854ec4356278e912856e3904938ea994ae9742818854912126ee15f9cfc 52873 main/Contents-udeb-mips64el.gz 572ddd8f7183d851c2fcfcda55166cd4ddb95b6eba0b73c07572dff8e74f797a 760210 main/Contents-udeb-mipsel d51989963ffcccba95d5591fe78e9aa6ecefd480f7464a199288d7153ea1a637 52810 main/Contents-udeb-mipsel.gz c6e87c5351596a66921e0559dcfdfae17c52cb422c709f2e44b19cf6064e80c9 401639 main/Contents-udeb-ppc64el 3a94166a9523c86e71d08304a2bd46dd72392738f22b608a4b2b45fb77491f58 29533 main/Contents-udeb-ppc64el.gz 42b53406c44e9439e86506343040298b5e1405e6791594953bb058ca6effe8f0 258318 main/Contents-udeb-s390x ce12cd039c002aeef6d9b364d73e313712d4d39970241953919fa6e8db0ce628 20894 main/Contents-udeb-s390x.gz b42ce26db7c150a2dbac237732eb0e5dd5ef28e2ca51a5482cd9293dc64d8357 20423830 main/binary-all/Packages 33eec3157da3c566e1f078bff8b46bd6074dcf3c9f242c760b8fcb2233bc5d32 5208282 main/binary-all/Packages.gz 09728ec87e7b549eaa43b80fbb9432e36043b9874cb4b3f95428a1eb2a96582f 3918264 main/binary-all/Packages.xz 5fca0b091a4008553328742c4e5509375042ae86fd25e078e5641da80c6e35ed 114 main/binary-all/Release 35eb7de95c102ffbea4818ea91e470962ddafc97ae539384d7f95d2836d7aa2e 45534962 main/binary-amd64/Packages a445d7472b76164584ebd9aebed31517837dac1f792164bba926278dcb166255 11096605 main/binary-amd64/Packages.gz 9b3d1e096767eae5ade343b1b123e1787cc49cc78b139db247fbe96f8f3f545d 8182920 main/binary-amd64/Packages.xz ab78444b1bbaa56630b4f90edc8982f4fd965ac4db2b5530855b768c1c8fa9f9 116 main/binary-amd64/Release d908fe964d366107388f445a2afa408224ccf6a665ef087f26afd1cfd2b9ad04 44816551 main/binary-arm64/Packages 1afdf5fece156bfb26fcb25409a00defecc507b38ae69097a09b18ff6b1d2b50 10941625 main/binary-arm64/Packages.gz d2b7315d4fda95e5a5f2ce7ca6e2e44d9bf1b1d9e9d980ce416d35a4d00f1a2f 8071508 main/binary-arm64/Packages.xz fc1fcedbe9926a4b0b8eb49c4ad003eeb5d656f7a447864ebab16f026100f6f7 116 main/binary-arm64/Release 6b115f03bd7e988bade97cb51a9ada488bad7623ad3f085da265df9e4e64cfec 43343990 main/binary-armel/Packages c2564b86e9dd83293f0a43f4fb18506ab8487878bf518115dc42b4e2125ca5d2 10677432 main/binary-armel/Packages.gz a81082ad524af5c8ff7fe7674bf715daa82de2ce1bfc39dde407dfb0d6bb6ad8 7871888 main/binary-armel/Packages.xz abb6c54c329433e32610e26704ca667256c1ad24cbdef67431ded86b67b9df8d 116 main/binary-armel/Release e14f5af333a1e465450a88a9a40806b8d4b0e2dd903e9b9c698f4004eac6f0b0 43846413 main/binary-armhf/Packages 7cb2281126c6161b691eaa41e647209b5240c660a99e2b083119e6c701a0a5d3 10775534 main/binary-armhf/Packages.gz ba960fa5d4178671db25ac4be29a375496edb695aac902f99c04aa482a60a379 7944712 main/binary-armhf/Packages.xz 07c1cebfbbc800619727cfabb5bbd313a65ff1ad3df60fe04b680de8c63846cf 116 main/binary-armhf/Release 164486fd11378f87865c09143df1514fca7045166c9c1ba61f2c50cffb987ea6 45094980 main/binary-i386/Packages 216af7eb177d93f2004318058ff3f833dd6cb66bc23a3ad17b0c27edbbacc923 11013153 main/binary-i386/Packages.gz cfd786ed196f7a512764069e09f20ef97c536552f777ecd303b4a1538de5fe9c 8121972 main/binary-i386/Packages.xz 598ab0b654f7296c5dd22bf8ebc2f1452e7585bb4fee5b0318d08a7700d59f39 115 main/binary-i386/Release 2f4b83b3beff8e697aa7aba63b87a3841eda7e121dca7efeeba2fdd6c46d4708 43733274 main/binary-mips64el/Packages 5d3435e4b966e83eff68bdc0f1390639ee4cf8ca85a0912086118d18fca56895 10720185 main/binary-mips64el/Packages.gz 2f5114b8774c2ebb9e4bde58f4f61228413faf25c6f0f8cfdfef166d59194d1c 7907404 main/binary-mips64el/Packages.xz f3e83d91633067c9cc7c22a7b17331307039cb7a194534c86c45a0ae8b15e159 119 main/binary-mips64el/Release 94dfcf07165f1f9da1d465a87d0978f2cd267341b0cb100a976db872731b0861 43667386 main/binary-mipsel/Packages dc8003ba9043dc725eb21a2d51f70fd0f68a98398e0819083663de884cc73721 10726366 main/binary-mipsel/Packages.gz 886bc8567cdd318d3380636c313f736e35220acc8be711584ea919d5265e96a8 7906936 main/binary-mipsel/Packages.xz 56e88cdccc438d85773e9d9dcd4626dc93905cc85c28492cf1115e0f6d6d86c4 117 main/binary-mipsel/Release 53f4716144d0126ec83ade49820c2737e4097d058c7ec55c26a94401aff90799 44671240 main/binary-ppc64el/Packages 0d7e6d81bc985f84d71bfa9dc1568b5bacde58766499fb50c9f9615627eb64d9 10884852 main/binary-ppc64el/Packages.gz 8bd383fa40a08bde86f78b7768a3c8eb8aff0a16f380fe3ba259258db8cd89dd 8031816 main/binary-ppc64el/Packages.xz 32c55acd12e6699b68c50747b5d72a0d2252a1db5856ab75fea6771c8311ba21 118 main/binary-ppc64el/Release 1e53bd7f1a45174fdb3db7ecebeaabfbfecfa0a88aaea4a9d060039c99b0580f 43340190 main/binary-s390x/Packages 07462d6e7a7e6ef042830e993747f9d471ae8dc0ba792c3056811c64d37c0e6d 10686656 main/binary-s390x/Packages.gz be641a245bcbd2b2138762c88793df74b04bad687f2c8185137254e9cb6bb229 7877060 main/binary-s390x/Packages.xz 612cf5c4ef5247bb112bcb8af86780ecfc13514729575fce1087ec12340965d7 116 main/binary-s390x/Release 4f60d86324cc91f8ac32625dfd1f8750a7f79e866376a34a478d2d3f8033ce84 61160 main/debian-installer/binary-all/Packages 1e0c3c1d9f21267ec4183fa21ffb26808808678d6393cde03820b5f8c677977c 16449 main/debian-installer/binary-all/Packages.gz 3831da178354890a18394e5d531c28c77f70c6fcc628e369eb584fbf7ce28812 14676 main/debian-installer/binary-all/Packages.xz 5fca0b091a4008553328742c4e5509375042ae86fd25e078e5641da80c6e35ed 114 main/debian-installer/binary-all/Release 8e6eade3d4d6600d25629ef41a6e7d7f1735cb999923c20962ab96c4c60cab8b 274352 main/debian-installer/binary-amd64/Packages 127cbf365fb6430a108efe73be70b65c93a156c3e9d54a26515fb0637fecf7a0 67349 main/debian-installer/binary-amd64/Packages.gz b15c72bd10652b7c5a456b8dbce9ee1002d9ee36b4c8377d5224bf71d7c343e5 56064 main/debian-installer/binary-amd64/Packages.xz ab78444b1bbaa56630b4f90edc8982f4fd965ac4db2b5530855b768c1c8fa9f9 116 main/debian-installer/binary-amd64/Release 42d0cbedcd391dcd0ae974c2feb668676aa33b430b213d23a913e411c817f23f 257349 main/debian-installer/binary-arm64/Packages 1e7d6c63aeeb7b5923f514df4586dd7c9a23415f318e4d99c03c435fed764ded 64271 main/debian-installer/binary-arm64/Packages.gz 155a73d0f9cb8c70eb64cf86204fb88a81585d79136dec3399b54571307daf5d 53980 main/debian-installer/binary-arm64/Packages.xz fc1fcedbe9926a4b0b8eb49c4ad003eeb5d656f7a447864ebab16f026100f6f7 116 main/debian-installer/binary-arm64/Release 01175829fcfa8f2d6599c49971251106ace55e9b660a6ab2b6cb84990b615f23 248363 main/debian-installer/binary-armel/Packages 41e38adbe03f5e12ce7bb71a17a1afa385a19129f3e2c4fe064358e83c41f50f 63792 main/debian-installer/binary-armel/Packages.gz a669674d70b74c4f3928ee0824025cd032a2cd681bee9608194da11bd96140ee 53168 main/debian-installer/binary-armel/Packages.xz abb6c54c329433e32610e26704ca667256c1ad24cbdef67431ded86b67b9df8d 116 main/debian-installer/binary-armel/Release 7805822347f4d4a5c174408573f6d212e6f639a8d2587c1358dd1273c1e4bfd1 251788 main/debian-installer/binary-armhf/Packages e39dc55b91aecd52890df43e9661536022c68301e6d2d46140f0d883ea0d4097 64864 main/debian-installer/binary-armhf/Packages.gz 508561858e1d7d9533704014303d875ddecb6c8a9be3a5692e4db28b8673bd0f 53852 main/debian-installer/binary-armhf/Packages.xz 07c1cebfbbc800619727cfabb5bbd313a65ff1ad3df60fe04b680de8c63846cf 116 main/debian-installer/binary-armhf/Release 545fe891b7ccfa9058a34a9ca644eec47d4d1e32b8d19731577719914d57b1cf 349445 main/debian-installer/binary-i386/Packages b3dcfa8a62aa51c55cb0cd999fe2930828eec945d947c737a4e0251299d031a5 77230 main/debian-installer/binary-i386/Packages.gz bb6f1ba125b73e6031b0db1aff6666d674614b2900f829edc00f5422b71a9ba6 64124 main/debian-installer/binary-i386/Packages.xz 598ab0b654f7296c5dd22bf8ebc2f1452e7585bb4fee5b0318d08a7700d59f39 115 main/debian-installer/binary-i386/Release e99d10f54387b1515192c78420b8320f19226950e45628b464419a16cbbe0851 364716 main/debian-installer/binary-mips64el/Packages c16ea980c78ef318d090f661bb8a32b013b9aba1e4e03cfc7a1fcdc710b315bb 79498 main/debian-installer/binary-mips64el/Packages.gz 0fe50a043e08a0c0f92cb774acbaefc95f78d7123efa606770dd02f9fdeff404 66396 main/debian-installer/binary-mips64el/Packages.xz f3e83d91633067c9cc7c22a7b17331307039cb7a194534c86c45a0ae8b15e159 119 main/debian-installer/binary-mips64el/Release e9b79bdf2204d27512128a1f1d85e8455d94c402be68b815c24f66be4f496e8b 364202 main/debian-installer/binary-mipsel/Packages 94265e6e880e2c55618fcde79440b3060922932eb14eac1beaa3c7b1c6865d17 79784 main/debian-installer/binary-mipsel/Packages.gz 803db2a15312c03059f31f2a20cde06935f7a3ca6c3f35e043b3d1881eaed353 66500 main/debian-installer/binary-mipsel/Packages.xz 56e88cdccc438d85773e9d9dcd4626dc93905cc85c28492cf1115e0f6d6d86c4 117 main/debian-installer/binary-mipsel/Release d779769699bad795292351e1d2bf4c294d0df53f43a8e812e607d2ef5d979fc6 256933 main/debian-installer/binary-ppc64el/Packages 6d2b2b5ac8b21d5dcec79146959b1bc617b65c5fb69a72bde8fe9b494bf03e30 64920 main/debian-installer/binary-ppc64el/Packages.gz adf0f93f39ffbdf3efc60e423653d16ca020f9d40d76c51b153462d4c556fac0 53960 main/debian-installer/binary-ppc64el/Packages.xz 32c55acd12e6699b68c50747b5d72a0d2252a1db5856ab75fea6771c8311ba21 118 main/debian-installer/binary-ppc64el/Release 08fac5f6592875d7466899b2bab7a44d8eea409b2b05dd8a334f0bd4e7bac807 226275 main/debian-installer/binary-s390x/Packages dad6130f7794acf153f2654ef56ce0f51ad202a6652862332025ef08d299b092 60464 main/debian-installer/binary-s390x/Packages.gz 255a06d1829ff337a371c2e3565ad96ea789703016ce91735b36a9dd6fab1647 50116 main/debian-installer/binary-s390x/Packages.xz 612cf5c4ef5247bb112bcb8af86780ecfc13514729575fce1087ec12340965d7 116 main/debian-installer/binary-s390x/Release 99d8d572b0219a7b37addc91ff4e4ff238a33b3452580d4bd2469588a2225cad 18520413 main/dep11/Components-amd64.yml 9c5522d811abead85a73407f6b56b171207105bb3641e22d76f2146482d4750b 6213469 main/dep11/Components-amd64.yml.gz 0b517038e27fe4864c35de9459537d91f5d274800a172be69f91e90bb3631589 4048504 main/dep11/Components-amd64.yml.xz ed767617ad156481cc8948fb72c2d699d6292bfd2d83fb2f24b2b155612dc539 18436837 main/dep11/Components-arm64.yml 1732a30dff783f891da2245f955becf3a43be40f0400b722087ba626316e980a 6191092 main/dep11/Components-arm64.yml.gz a02d6259b836d37804838b6de8f40568332a9a78cb4bc7668b32208f6062e782 4033216 main/dep11/Components-arm64.yml.xz aa3eea13a49b29dba27956d6fb6093817775361e29fef3f751e8e70b7065e54d 17658848 main/dep11/Components-armel.yml ca3d41da75c25408834b265c9c95f700a1241189f6bf62270e14b85920f5cdc2 5952269 main/dep11/Components-armel.yml.gz 5c90b5a79fb5cf11b4e822396183bd3b4d3712e5f8e9363c5fce4a3a6c42a58b 3879744 main/dep11/Components-armel.yml.xz 9d95db48c33d5671c96a2931458a92b6290e9c3f880c7ec7d7aef2b23a681eb3 18205252 main/dep11/Components-armhf.yml 55c47f2e4607828ad1d875c1ade2aea6565916e9dce3e043f6de2e85b6cd74c4 6110587 main/dep11/Components-armhf.yml.gz 20797715d417813ddd77d1bf746b8ea9f6353ad0e8be2e67f1700813d992268d 3983180 main/dep11/Components-armhf.yml.xz 5579083d9a290f05eeb86967fd664c46464b3bafc00c073887560523a1793a64 18485654 main/dep11/Components-i386.yml ac8dd6c8b9e575785646a7d41adc7783956e22bcc757a60c80f225328c769f08 6201776 main/dep11/Components-i386.yml.gz 589f93188296c83e394c89ccdaae1565436dc203161958e96f3a5cf2797684ca 4041608 main/dep11/Components-i386.yml.xz 2b028df6a795c2a4b058b0f239745da363ea0f8b9fb8ce1a7955bedf579cc8cc 17819116 main/dep11/Components-mips64el.yml 0865e497ec87d5d45f84106166bb035610443e87528aacc1a43f13000542a3f5 5977494 main/dep11/Components-mips64el.yml.gz 46745049532f14f438f41704b442c157ee0f2990baed5d06da8fda3b41501547 3896708 main/dep11/Components-mips64el.yml.xz c0e1c64172edc19edcc287b0e617adff28b31354028de4c755cdf1fd077de913 17947079 main/dep11/Components-ppc64el.yml ba4eb9c1ab3f03a7fd184e5fc47dce250c083a617d9e2ba49a70c920fd957b29 6023058 main/dep11/Components-ppc64el.yml.gz aa34918432eeb8a82d912d86f69d82e84a4bc0eb48056ebe321b83d2757d1052 3925796 main/dep11/Components-ppc64el.yml.xz dc222c504c71bbc9ff6b698bf5ef7942e098efff1031861e5eb8670afdd18452 17735785 main/dep11/Components-s390x.yml 29584e8fd8bc91d9d9099893ae4951601430b1df4f55659e089d34e4525540e5 5976062 main/dep11/Components-s390x.yml.gz 1f9ca828b916aabab9b41f75950df49f71dc5e8a42f674ff4cb2138f85274314 3894008 main/dep11/Components-s390x.yml.xz 057f28adb7c2452ab2c810fdfbfce0305ba8143ffe2e24969b2ece077aba7e9f 13048320 main/dep11/icons-128x128.tar 4f46415e13538a05743752a630c9b8795a9772d0ab4ebe83c9d7e19f0e4bf179 11409337 main/dep11/icons-128x128.tar.gz e0c306e3293ecdcb8392faa372b00f1fb979c327c3e4370452acf7713ab885a4 4878336 main/dep11/icons-48x48.tar 93c4366d8b6ef489bb935434d9a2c56d842978922e941dd4ee716ede2a805494 3477622 main/dep11/icons-48x48.tar.gz 910ec31c85f12f0edefbb43fa2514b9896d105ce7316272a4c55263af864c238 9378816 main/dep11/icons-64x64.tar a94629c3e4fbe9607fb2921e1c906f88343a7cadc484a1087983181ae6df66a3 7315395 main/dep11/icons-64x64.tar.gz e061ee16e4478c39875bc3d977fdd5f880a71a3ea97c9f5119ac127a4305579a 6191 main/i18n/Translation-ca ed06627194c667d774188bcf0d9b859625ec60d2098238ee3c1cd5e1c147c4f7 2673 main/i18n/Translation-ca.bz2 857bef6538df7a4e2ae01a6ef40f8a5c9e0512797a769d8813caaa57ca867f29 1205166 main/i18n/Translation-cs bdd79636af5f08f4c40bb5266a41e4707b7bdc84d5458451df0255b787c380a6 323247 main/i18n/Translation-cs.bz2 2c7c6d7013e3d04a62c457525567fac4ac2747ef59f1b2a93cad8c0904c960b9 20240560 main/i18n/Translation-da 8935ec6ddfeaeb542fe444013ad9fefd6ffd2da2afe818efeb417fb50568b52e 4411163 main/i18n/Translation-da.bz2 55e94848df1df7d0963f3cb02cfb4171031350c549e4ae64f6aed517ed08ca6d 7801238 main/i18n/Translation-de b68fe8718325ebd1e2a8dd30f52b17c003e315f3468f9b7890fe5b1b91c709cd 1717951 main/i18n/Translation-de.bz2 284169348b8bd4e0de4cc5641eeb05577e80d2bd736452e454976c052cf3cbe2 1347 main/i18n/Translation-de_DE 481a435ad350105b74c4972859c44f447b7a8b5edea0d42f6dd635792e00a461 830 main/i18n/Translation-de_DE.bz2 9f3b3bc0da0653f0ac8484024a7f77aeda681474907f3a94b8a0a0933775d14d 6257 main/i18n/Translation-el 807de361285151534654b83681415016d443e4abd1a7ba36e1e78b4ac337b973 1835 main/i18n/Translation-el.bz2 87a5cc96d599e93f7cd76ea6f32b27e9742abd8027c9c76c40ad1a091e0d8950 30246698 main/i18n/Translation-en 4d7cf2aa527bdd9129bd6e5974c41f574de06f1963d9062af0787972b4a76b7c 6240167 main/i18n/Translation-en.bz2 abccaeb24d409c21b94883b74785053d0f8fad3e94449078ebe92af38861bc5a 2261 main/i18n/Translation-eo 747ab457a83de3b107e25b9cc5536aea2f19e0fe1f08d5357475acea0d788fae 1196 main/i18n/Translation-eo.bz2 38345d246390b3845920937338647a70b1a6a93f354615da725fbf426ac3e332 1325929 main/i18n/Translation-es d6bd3bb26fb52e553bdaa40a041aa167f8a0c207149ebf626bea65c90ff7e99f 317946 main/i18n/Translation-es.bz2 80c3ff00f3b37b64e73c85b11eab47fe88901b6f8d9f189de0e95a387e02ebed 10093 main/i18n/Translation-eu 7ce6c68ef8a577bd215da5f7a12153bee27268b0b6b9503aaf88244b225f20a1 3914 main/i18n/Translation-eu.bz2 54c5db1926c3309513d37990460a51c586ae6f01bcaaf2732e537ae400b6f5f5 269212 main/i18n/Translation-fi a0c315c9c517ac029e5981f14a3c15fa022c7c0e1e86edf123e05027343974d7 75849 main/i18n/Translation-fi.bz2 bd258bc1f5bbc6694e24f58fe4dfb5f5636afc86a431795b931225e9e336feb3 11857302 main/i18n/Translation-fr ef77125783dc8b1125ea85050ba00bfe042e6f38fa1f73613387fe30cae47c5c 2433064 main/i18n/Translation-fr.bz2 ce1a70b1000909a09166e30d574c717f3d60ba173bb65ad65e768374dc73232d 1427 main/i18n/Translation-gl fa1eb924fc1473b81f7790ccd909de1dc274f4f266df8af544261f03e1d21079 824 main/i18n/Translation-gl.bz2 22e19c218655a9a4d09e9930a66715aeb5d0b02bdc4d147e5816067873e71861 21069 main/i18n/Translation-hr 04e538e90503a9238d071bba89039e563d4c03ee038c217708a4f8c8672c28d6 4695 main/i18n/Translation-hr.bz2 a275d9da1b509fc6c1d8307ff33daea14669cec8b8f89bb4c4fdf4d50ff48135 65236 main/i18n/Translation-hu 94827a9f6e251237fb3b093360f88ba469d2be8d4a7c2c02c84298c94faceaa5 22243 main/i18n/Translation-hu.bz2 0f4bfaba954ffa37332a34df69c8844b7334cc0b61515e9510513e2c43e140b1 3983 main/i18n/Translation-id 11aebe26133b1249ebc06ec6d1a8b76f5975b9a3630daf71ecb7e2f6521a2fd2 1780 main/i18n/Translation-id.bz2 d965461960f14ff1f614bcd0ba757874e098cd460b8ae0e018fb4aba254ce641 24489940 main/i18n/Translation-it 451a92cd21dc98889f43a39223dc8863284bd1a8e515bc58633bdb7bf96dd37c 4844227 main/i18n/Translation-it.bz2 1cb8cbfe8b502cc64639b02150e6f805bdeebedae3eb69273146c03ca6c9287c 4511401 main/i18n/Translation-ja 0c00e0a8cff6fb13bdc4ed3387e3faf4f9db94f3ed4ca8e72d324c0a03d8f018 803966 main/i18n/Translation-ja.bz2 7238152be74233d91630f7100ef7ff2bb8a95598b5fbc11c21c7afeecfc0fecd 11879 main/i18n/Translation-km 01577e06c8e41b3a914ae539147af0fcdc7a0f883f50d82b57b263cf62fe1bf8 2371 main/i18n/Translation-km.bz2 232cb289feae187cf94ad451662d7ce36be8014c40b69e645d19b9534dd586df 2606190 main/i18n/Translation-ko 894aba3a34a47f3d59deca3bda07f8aa288e9f4ed6ae92422eab3fd9dd370ad5 584643 main/i18n/Translation-ko.bz2 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/i18n/Translation-ml d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 main/i18n/Translation-ml.bz2 16be336bba03786450a43321709eca2fce7fa7b50a135a97da71e16eb5e7d60b 1193 main/i18n/Translation-nb fdec5fc00fe2d0e3c7730462f95273492d278eb8a6957c1b437969833366c217 738 main/i18n/Translation-nb.bz2 ce65092fbb0a09286644912bfaf3a9535921705519e16d07617ad85ec44ccf3a 174332 main/i18n/Translation-nl e12b923a6f3f83636a31e6e1b2503d8a213e1e4112586a27700fc17bb48ce564 47973 main/i18n/Translation-nl.bz2 8999184566c11a42f9a31c810d9252316dc4f52ba738db43e0be2cd760c823a1 2051811 main/i18n/Translation-pl 17fe48deb79b044bdf5894d0d129823b1d86653b9759f848667a74b563625379 491993 main/i18n/Translation-pl.bz2 2dbf3c4316bba32571abc589b177be93c8e72885131940c9993d3fb6b8d58cb4 1074959 main/i18n/Translation-pt 991a66952f6395d7588f38e68e1032f4dcc72da61322a59460c34a24d7713400 272186 main/i18n/Translation-pt.bz2 5d7ec6fe173a67789c445369b7ebf8709cbc9ce4f3e06a75cf36c562a16580a1 3306707 main/i18n/Translation-pt_BR 1583cdd6a71e29b6eaea0d29dee9ce903fc8ced1f9f57e5ad4de154938799bd0 802734 main/i18n/Translation-pt_BR.bz2 c90708ca8975ced4acf4be98a4ac1f5c8092fd826b4d928e35c3650e705553d4 1717 main/i18n/Translation-ro 35f2449dba7bd93e0aece908f4c4de53cc864a48c8f7aeaa5a64f67384e1bcda 982 main/i18n/Translation-ro.bz2 f8b907289a1970413a47a3450c59b04e166c08cb387ee3ae4f6c0d2e4774c379 3058931 main/i18n/Translation-ru 8685feba7a33fef7ad8d7fe5db5f59e837eba69134deb87610742cf564e47258 494782 main/i18n/Translation-ru.bz2 ee2a1713ba3ccf4aa7ef3ee1b5786874c38ecc15db012bc15c3efbf5ad8facd2 5984088 main/i18n/Translation-sk 0dfec1c42d581b3fe8f95bbe26f649f45234d419c7e709dc881f1994bfb20974 1304539 main/i18n/Translation-sk.bz2 5ff9c60997a547f07d212476a8f50b4942f012d7952765c6c1925c52495711d1 323953 main/i18n/Translation-sr b4608fc3c0c7f6aefe0f6e5e19d0fbe0d5035333e74044e29358b3e3efa99536 58385 main/i18n/Translation-sr.bz2 5656d4e913760691e99cd4805e76c8f18c4441fe707a02e621a2a172da756d5b 85612 main/i18n/Translation-sv fbad8c083b9985e53a2a82d7e32f26f683bd5b8e2f1bf09a3e0fc3f8f7abf6da 27320 main/i18n/Translation-sv.bz2 2e50dd5fdf1dd6157c0db51afb4457fcfbd427ebb6d1268aeeea1daf50da78f0 14670 main/i18n/Translation-tr 401a0f8d754d92c562bafe54aa0cb2dd7686ca015425513b666b50b8c9dc36a7 5362 main/i18n/Translation-tr.bz2 6c66f49d6c9df7ef28f92aaab2620a2151fa16f74bf96deb3b74987183e43b86 3740343 main/i18n/Translation-uk bd760427bda1a65895dd7b3bd6a3e2b2a0ee6b4060ce726ec4b7c02b89a72204 576766 main/i18n/Translation-uk.bz2 c2207dfa8d62c7e2a31851842dd928739bc147515f69fb7a28db93196dd1a601 21882 main/i18n/Translation-vi e3eab47e1acdc01ee2d774dba5b0f9d29c98ff48b25a57d469eeecf60d3035ca 6510 main/i18n/Translation-vi.bz2 7133134d1b1b6c869b4b700fed9778e93a0b774391402ad3399e9ff46984efff 2007 main/i18n/Translation-zh 8cbeadbbcec613b8476f8e2aa40b15772909109e10a83317c111fcf7c28d0219 1215 main/i18n/Translation-zh.bz2 d88628c7a7a16a042234daf91a709daa6d5f9de15406ec78530891354fa25c75 425199 main/i18n/Translation-zh_CN 1ef87b145198090deb2d037bc16b5b940c0e757a2511f4ff84a7c750720b2723 113621 main/i18n/Translation-zh_CN.bz2 564fdb3059cffbe78dde61697e77edd7bc94005a358cc4b5dffb436776d1b2b0 39965 main/i18n/Translation-zh_TW 0a4d5ecccec7069a32b30de129018034b2f6f2b318f1530e1edc239182442cf8 14859 main/i18n/Translation-zh_TW.bz2 343fe56ad4f39f517c6b504106ce828f6ab57b71fd8fe11ded31b5d217950b9a 58277 main/installer-amd64/20210731+deb11u7+b1/images/MD5SUMS 3dddfa19f9ca9bd20c0f0249d68427e5a70cabb845c8dc9736f3949c96ec1188 78097 main/installer-amd64/20210731+deb11u7+b1/images/SHA256SUMS 91e63d03c43f9feaed6c255a510c30c35c547c517f395c2574900b0119fad790 57705 main/installer-amd64/20210731/images/MD5SUMS a3a16cc4af2d688613ce8df4d224974629ad3383a1969350c24ea68bfdd5f1e5 77333 main/installer-amd64/20210731/images/SHA256SUMS 343fe56ad4f39f517c6b504106ce828f6ab57b71fd8fe11ded31b5d217950b9a 58277 main/installer-amd64/current/images/MD5SUMS 3dddfa19f9ca9bd20c0f0249d68427e5a70cabb845c8dc9736f3949c96ec1188 78097 main/installer-amd64/current/images/SHA256SUMS 1df7955a3c09498e279431cb6304f4e616cb7ea5a8ee5d4b9db85ba9d2a05bed 69049 main/installer-arm64/20210731+deb11u7+b1/images/MD5SUMS fd710c158d06fae3de80d23198806c9101e7e6cc640fad6b366d3f06eed9e91f 94149 main/installer-arm64/20210731+deb11u7+b1/images/SHA256SUMS 291e81049aa85b147063ec1aa5bec87da60d3196c06c3098de5210c3346837eb 68403 main/installer-arm64/20210731/images/MD5SUMS 5dfc89487fc8717ab9a9b75cdaaf01a295ab3021cc3310d3fe9dd3e78fc1f666 93279 main/installer-arm64/20210731/images/SHA256SUMS 1df7955a3c09498e279431cb6304f4e616cb7ea5a8ee5d4b9db85ba9d2a05bed 69049 main/installer-arm64/current/images/MD5SUMS fd710c158d06fae3de80d23198806c9101e7e6cc640fad6b366d3f06eed9e91f 94149 main/installer-arm64/current/images/SHA256SUMS 54528ee7dfb52dc1ce6680b4a8b898d9454936c892012a677747465fa8f506d9 20678 main/installer-armel/20210731+deb11u7+b1/images/MD5SUMS 86396ff61efdee365e4ab688b91f773409a12d6950f61a7e8671a9b64777458c 28882 main/installer-armel/20210731+deb11u7+b1/images/SHA256SUMS ee9f639b7a0304207f23c84f5396284720a6fc6c638ee7be6873944a0f224c95 20182 main/installer-armel/20210731/images/MD5SUMS 07353d4c378ea579803ed8c1aca3fe6df2cbc89788736c7d01102a7b3ebad859 28194 main/installer-armel/20210731/images/SHA256SUMS 54528ee7dfb52dc1ce6680b4a8b898d9454936c892012a677747465fa8f506d9 20678 main/installer-armel/current/images/MD5SUMS 86396ff61efdee365e4ab688b91f773409a12d6950f61a7e8671a9b64777458c 28882 main/installer-armel/current/images/SHA256SUMS f899f04724b1fbce7e9a9060e82e1dcb942919914bdc808d120b7e52fb7b38b2 64380 main/installer-armhf/20210731+deb11u7+b1/images/MD5SUMS cf5b025aef61b2ea4e0c5f94d36e22e5ed26b01da945f498f9b6cb5156171b1f 92680 main/installer-armhf/20210731+deb11u7+b1/images/SHA256SUMS 8c1f810a60fc7daf099e608b763cec563f59c82203a07bbf4469a6213a8946eb 64240 main/installer-armhf/20210731/images/MD5SUMS 67c5b636e3fc02747ca9593e6fc7e906a3ec95d4947740fec81b1e942f0643ae 92476 main/installer-armhf/20210731/images/SHA256SUMS f899f04724b1fbce7e9a9060e82e1dcb942919914bdc808d120b7e52fb7b38b2 64380 main/installer-armhf/current/images/MD5SUMS cf5b025aef61b2ea4e0c5f94d36e22e5ed26b01da945f498f9b6cb5156171b1f 92680 main/installer-armhf/current/images/SHA256SUMS 393b9f170f9732a04cee8abf0dc9d0a52272bd577c47d30310dd88c2552db5b7 56840 main/installer-i386/20210731+deb11u7+b1/images/MD5SUMS fb5c92b43fcaaa6850fe79473a5fac3c6a27e31b72a52d81297eb283fdbc46d1 76724 main/installer-i386/20210731+deb11u7+b1/images/SHA256SUMS 96e8acb8eb827ce7032587400fbe848b6f53921c661d52e1b16fd243cb8e57aa 56286 main/installer-i386/20210731/images/MD5SUMS bced74c95a3688a9a2a28abb8190cb7efd7e1f6372dc8989e260771752ef571b 75978 main/installer-i386/20210731/images/SHA256SUMS 393b9f170f9732a04cee8abf0dc9d0a52272bd577c47d30310dd88c2552db5b7 56840 main/installer-i386/current/images/MD5SUMS fb5c92b43fcaaa6850fe79473a5fac3c6a27e31b72a52d81297eb283fdbc46d1 76724 main/installer-i386/current/images/SHA256SUMS d1eb4b5cef71f7c78971aa99bf86ed4980ebcb8bab8d0e45835731d0ce173969 630 main/installer-mips64el/20210731+deb11u7+b1/images/MD5SUMS 275fc83d164449c94cfc9c4039f38eb08e123bb11d6f6acc2724441f752a3727 1026 main/installer-mips64el/20210731+deb11u7+b1/images/SHA256SUMS af3b55dea76e91f1565bd54bc1af76a6a0bb4991eef9abe281a22d9fd8d54a7b 627 main/installer-mips64el/20210731/images/MD5SUMS 995cda8278b101eb25849d56f3ef33290fb57a940fa1c6837f19df00ceafaaff 1023 main/installer-mips64el/20210731/images/SHA256SUMS d1eb4b5cef71f7c78971aa99bf86ed4980ebcb8bab8d0e45835731d0ce173969 630 main/installer-mips64el/current/images/MD5SUMS 275fc83d164449c94cfc9c4039f38eb08e123bb11d6f6acc2724441f752a3727 1026 main/installer-mips64el/current/images/SHA256SUMS 74028a1b5cf4c8a3e8b30fadaa3c4a2237b9032b93a3abfb3d3edb64667cbe61 630 main/installer-mipsel/20210731+deb11u7+b1/images/MD5SUMS 1dd26a64b20327c1718dec6cf314168dbf68a225b1e68cedb2c8d4f4ee218087 1026 main/installer-mipsel/20210731+deb11u7+b1/images/SHA256SUMS ca77bbc823d1bf6999e141cd42c1bb4c18179cbe4a3fbb6da3e40e1055848ed7 627 main/installer-mipsel/20210731/images/MD5SUMS 28589449e1b3ac9a73bdf6f266edc83e70ebbbca587a228b15b0dbe5e1a634fa 1023 main/installer-mipsel/20210731/images/SHA256SUMS 74028a1b5cf4c8a3e8b30fadaa3c4a2237b9032b93a3abfb3d3edb64667cbe61 630 main/installer-mipsel/current/images/MD5SUMS 1dd26a64b20327c1718dec6cf314168dbf68a225b1e68cedb2c8d4f4ee218087 1026 main/installer-mipsel/current/images/SHA256SUMS 1703a54e2b260ec691ffecd444e7507f03bbefce7cb8341b73ad78ed16ca750c 576 main/installer-ppc64el/20210731+deb11u7+b1/images/MD5SUMS c234d16ddedfbb72bffb5cb22b32b981e03b3461f6720c10c7d5b8dc726e912c 972 main/installer-ppc64el/20210731+deb11u7+b1/images/SHA256SUMS d162b2da6777c1ea0643921cc1a3dde78ae48cf022711eb98c7e9dd030b89a44 576 main/installer-ppc64el/20210731/images/MD5SUMS 73e281bce56df3c7512ffa1a1cb13886064759a461621db4acf9b1f71965c676 972 main/installer-ppc64el/20210731/images/SHA256SUMS 1703a54e2b260ec691ffecd444e7507f03bbefce7cb8341b73ad78ed16ca750c 576 main/installer-ppc64el/current/images/MD5SUMS c234d16ddedfbb72bffb5cb22b32b981e03b3461f6720c10c7d5b8dc726e912c 972 main/installer-ppc64el/current/images/SHA256SUMS 20b3ae961820dbc6df8275c2efa95d4ed34775cd22f9d5dc0d656bd699c9f99d 374 main/installer-s390x/20210731+deb11u7+b1/images/MD5SUMS 1082cf1f5b94b3c234dea741a0ed81e03cf3f78b0a55affcf58d517bf37fee2d 674 main/installer-s390x/20210731+deb11u7+b1/images/SHA256SUMS b2c58a9c5b97a59742a8056e3e9d7f4f22d4d11e51c71d7a0051dc4649a717b9 374 main/installer-s390x/20210731/images/MD5SUMS 61447263ea7318c444fde199afc718a8498fe67bc0e7116f2e1103cc65ef672b 674 main/installer-s390x/20210731/images/SHA256SUMS 20b3ae961820dbc6df8275c2efa95d4ed34775cd22f9d5dc0d656bd699c9f99d 374 main/installer-s390x/current/images/MD5SUMS 1082cf1f5b94b3c234dea741a0ed81e03cf3f78b0a55affcf58d517bf37fee2d 674 main/installer-s390x/current/images/SHA256SUMS de9a48c211839c666254f2eba37417143bf6d0db56abfe1d07e4c35609d3f04f 117 main/source/Release dced89e82fac92fdc1cb92f99321787f26c8c9b0d72da39ec091dd96234ae3d1 44655922 main/source/Sources 006a5628b8afa45bf77cc449afa6f98647573b0e98b119a5944e65741094bdeb 11429086 main/source/Sources.gz a7e9e21d852dc2b685e9c28e0b06a9a4043220367cec57bd0e7043bd58c1a069 8633788 main/source/Sources.xz 29cac69ab0fd86e224587eea8e2ed2fb9b1b2e3c936fb1dc7165b8ed8d00528a 17347341 non-free/Contents-all 3b87590d0360ae141f3688fbafb5fdad35d4dd4b1a239888c911743c4357862d 888157 non-free/Contents-all.gz 1335601f3e9b7f67c279a4c1619203dd6461fab7c16c29e1d71970a9bd023052 1097448 non-free/Contents-amd64 df4bb7a18156a7f33c70f36d1709ae7ba48716d96ec1b940bd3bbb47ba432de7 79655 non-free/Contents-amd64.gz 6f4902fb02e2f1092d88d8101024129a4af0fd245e75803b0b93b0475feef42e 499970 non-free/Contents-arm64 c2715365833d3d97cb90e1fbf44df3c6835b323ef1e5dfd660b1cce148cf62e9 37376 non-free/Contents-arm64.gz 386c53a056d4aedb9d48a332056c51a302e1b043480cc24fc9ea9053ff8fe002 95417 non-free/Contents-armel 5fc23867def6ff06cf0c72080f1862ea142b20d25ca0a1e8e8b9c83ca3b82519 9298 non-free/Contents-armel.gz e2fe020c8c47e80e483acfe05462706e063c6932f9bb857e54d59383d415a44f 146124 non-free/Contents-armhf ac08720d4fc801273e1a8b2e0d7d7f80d07220f09089011a577ba47f12172ebb 13502 non-free/Contents-armhf.gz 6468671814b9daa924278df786f198b0b34d8f525b7a9c0ff8cdd6db3dbc661a 343198 non-free/Contents-i386 d85698eb7c99ba6fb568afcb497365ebbc59421c89dea8b6186b661e8c19fd12 29072 non-free/Contents-i386.gz 6bdcba453cc1369f93e7157d5d7f9c67198edc62e4e194b079b0572186a95b34 91215 non-free/Contents-mips64el 0986d6fc85dcf209edbf39b1ee2c84b370ea02dfe810ac33cd9cc89a2f3a2a18 8686 non-free/Contents-mips64el.gz 5102cb8d1b74daa60d4d6444e563dbdaf73ffaa2b7ce71a304987ff575da7f4e 92244 non-free/Contents-mipsel 53bd140b538ffea9c0bd8b6b073b3ef613ec1d452bb1bad5a5f86a029f11e3dc 9026 non-free/Contents-mipsel.gz 03756e78d0f8004d0cdd2e4fe2238a6c851f94c42b0ca7064629b55a4ca494d6 716110 non-free/Contents-ppc64el e3321e93f91e779a59e4ca94c61d1eedd13d02a847824c459419c29203ca6959 49881 non-free/Contents-ppc64el.gz 6d2b11e017bf520a64870b3ceecfac7944f991928095bd2715429987a342c37e 74537 non-free/Contents-s390x 228df45a42a42dd62cc747f2abe99dccd25c384aa423c17896a6196955cd9c12 7407 non-free/Contents-s390x.gz 1d53da6b88f2d7252351b65dafa6ec6453ef19326ce8490ea48d865557f30c52 10803369 non-free/Contents-source de64ec721f3e9589c6f7efc4f23c2713a40afcce15e033eddbfa0674dc81ae4c 1063443 non-free/Contents-source.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-all f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-all.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-amd64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-amd64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-arm64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-arm64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-armel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-armel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-armhf f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-armhf.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-i386 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-i386.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-mips64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-mips64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-mipsel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-mipsel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-ppc64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-ppc64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-s390x f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-s390x.gz 68ddf090986f56743010180da8d3e05a41bd5185e0047a98c97adb038cc5fc4b 189021 non-free/binary-all/Packages 569cc71a40dffea02aa6cf8b516370e08587ec71d34558cf6f1fe688c9629468 50928 non-free/binary-all/Packages.gz b9d8d7fb507a77a6222770fbe09815bc0cae22af92d0c16538d53b4576af6784 42996 non-free/binary-all/Packages.xz 3f87c1d57bbb196bc7d6a2bec129e82e4f4296b3743a105f53104fa82e3d6f07 118 non-free/binary-all/Release 41eae996375149a4854537915bf8162c5a22c77f3fa88c6466ce16d5f1b7d1d3 545576 non-free/binary-amd64/Packages 6bebe66d1f22f6dc11b186fbd34d029402a0848057dfa5a8afa193cad65bc205 122225 non-free/binary-amd64/Packages.gz a108aa5d825e98f766b4e20d261c21c1fafd9340547006244aa6fbb51b77d837 97772 non-free/binary-amd64/Packages.xz 9a0edbc466a3e91231c1ba756996d5fb598d3b14166a2a2b72899d4672f53a82 120 non-free/binary-amd64/Release 514482332f1c35020f2ba2ac2cff8e956dc5ba0a9a5533251321cf3e2e50ff89 381335 non-free/binary-arm64/Packages c2b9e19b24c3c9f859da6a28fd8cf27bc1b698111d4bd48728a8b8cb093085b1 88201 non-free/binary-arm64/Packages.gz 2ab2f8d500ce30e6b4e70fa5ef5678a3eef0743deaec93a24011949bc5911f75 72980 non-free/binary-arm64/Packages.xz 76a1c234c80cbabd279f721e53350404c3cffb523962e44161ded825f87c673c 120 non-free/binary-arm64/Release f5738f5a5d9f4391ba0719b7bb175892d93561b688137917a4cdc75537ca70e5 227933 non-free/binary-armel/Packages 89cb801437910d9b6076d9caf85f2144b224cb1eff7dfbd014219242df514b82 61822 non-free/binary-armel/Packages.gz bf2bfec078bdf2dcd2d0d411109257f3ec2d652087399062023d2fcce2e43710 51800 non-free/binary-armel/Packages.xz 7148bdadd1b6755cc63ffebb30bb3f228e3d6d2565e18ae6641eb62cbc802fa1 120 non-free/binary-armel/Release 4a9f94f9f510ff6c829677b8dd08ed0c5ff7b33f2118f152d2a4e6b410f8425a 259156 non-free/binary-armhf/Packages d7ae0acddc9f6a9acff311a662f78729a610fec44101cd8275fdbddebce7b5d4 67317 non-free/binary-armhf/Packages.gz 21f37dc3d988493e921f40cd37cc6ef2391b2d7cccf5c83fbf1b037602c0e521 56272 non-free/binary-armhf/Packages.xz 404c43c7b78d9a5b45b1d0c1851c58ac77a4b4ffe83c81d5c184b114c7c65804 120 non-free/binary-armhf/Release 54c7fe6dbb5eba9498c1726c1e2119d86697ef32300d3bab99048f1b4141c482 422388 non-free/binary-i386/Packages 54d73d03945551ef08f0c0b74828b3d78d2747a5f26c3a5d7d7fc446a79f383b 96319 non-free/binary-i386/Packages.gz 3f0a14b592ba6bf04c31da2ccbbe82bf058d62e341c1777c02f3fd5c00aab76f 79344 non-free/binary-i386/Packages.xz fda2cc9eaf856a91a54c1c893a273d148234734ffea5e1ae811d3404c07700b8 119 non-free/binary-i386/Release f7e9a5d9f19cc5b819efa1aac30c9d833ed9e41dfdce9abf2bc48d0467abae1a 225506 non-free/binary-mips64el/Packages 2d01bd458989434fd6555cdc4d4f9dc554881de09ced2db213fc26395f4108c8 61024 non-free/binary-mips64el/Packages.gz ed53056d18b6b8589fbbebffd26f8fbda708f71870e1bbffd4a4cfc7249283b2 51124 non-free/binary-mips64el/Packages.xz 19a2da1050283b31ebd2f6664572c326fe39fa70de30821b9a5410e5e5ae0daa 123 non-free/binary-mips64el/Release c690e75e4633fad47565d5afcef96622ec6e02b2fa824e5c0508f1119044c906 226162 non-free/binary-mipsel/Packages fd05e8f63760b2163ba4b40cdf200a9b113edfbf81d5a2a318a2b5605812891d 61277 non-free/binary-mipsel/Packages.gz 87cb9361adbac3f2604906109b21c6b685fda9caf3525395dd4ee057d7c4e43d 51364 non-free/binary-mipsel/Packages.xz 7d90fbb38122b89666a80ad2665d91fc0eac09bab9f4f7603cc4547504abae06 121 non-free/binary-mipsel/Release 74efb451a4beb4d707ceac0597842d515b78b7d9effb56a06663fb7428ef129e 381597 non-free/binary-ppc64el/Packages c4b451037905b8277fe0a2c0699c3e4ab0de2eb69559c19ac89361440f0439d5 86900 non-free/binary-ppc64el/Packages.gz 7bc21cd6ac30fce563e47909e7ec989071941134e89b2d895100059749cf3a47 71812 non-free/binary-ppc64el/Packages.xz c83ec7a841e5fc039ecef935b1b67f91cebad518a361463db2f804fcb32aaf91 122 non-free/binary-ppc64el/Release 79ebd2f1278b5db689359d517f88af2ae9acd8d493bf791e5cb5f73b9c81479d 220570 non-free/binary-s390x/Packages f7240f44940160f2d9b7cb553f6f47713186ebba6646c18a093e61bc4088e720 59856 non-free/binary-s390x/Packages.gz 4a1d593c1cd1adb67b9ab6bd5c2558536c284486eb714f89b9ce09229bbb1eef 50216 non-free/binary-s390x/Packages.xz e51de0ad0c2a44d2a9054242a462481f42bf24e4da5f58fd0ef35993dd35693c 120 non-free/binary-s390x/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-all/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-all/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-all/Packages.xz 3f87c1d57bbb196bc7d6a2bec129e82e4f4296b3743a105f53104fa82e3d6f07 118 non-free/debian-installer/binary-all/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-amd64/Packages.xz 9a0edbc466a3e91231c1ba756996d5fb598d3b14166a2a2b72899d4672f53a82 120 non-free/debian-installer/binary-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-arm64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-arm64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-arm64/Packages.xz 76a1c234c80cbabd279f721e53350404c3cffb523962e44161ded825f87c673c 120 non-free/debian-installer/binary-arm64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-armel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-armel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-armel/Packages.xz 7148bdadd1b6755cc63ffebb30bb3f228e3d6d2565e18ae6641eb62cbc802fa1 120 non-free/debian-installer/binary-armel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-armhf/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-armhf/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-armhf/Packages.xz 404c43c7b78d9a5b45b1d0c1851c58ac77a4b4ffe83c81d5c184b114c7c65804 120 non-free/debian-installer/binary-armhf/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-i386/Packages.xz fda2cc9eaf856a91a54c1c893a273d148234734ffea5e1ae811d3404c07700b8 119 non-free/debian-installer/binary-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mips64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mips64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mips64el/Packages.xz 19a2da1050283b31ebd2f6664572c326fe39fa70de30821b9a5410e5e5ae0daa 123 non-free/debian-installer/binary-mips64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mipsel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mipsel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mipsel/Packages.xz 7d90fbb38122b89666a80ad2665d91fc0eac09bab9f4f7603cc4547504abae06 121 non-free/debian-installer/binary-mipsel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-ppc64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-ppc64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-ppc64el/Packages.xz c83ec7a841e5fc039ecef935b1b67f91cebad518a361463db2f804fcb32aaf91 122 non-free/debian-installer/binary-ppc64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-s390x/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-s390x/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-s390x/Packages.xz e51de0ad0c2a44d2a9054242a462481f42bf24e4da5f58fd0ef35993dd35693c 120 non-free/debian-installer/binary-s390x/Release e13d055f233a81a77666f0ff8dd9d748917b2829740756e1dc2b8a350309bcb0 278293 non-free/dep11/Components-amd64.yml f51b1a07cd72a36b2a9f36742ab26819a7808aa7765cbf3e2ff4abe6be66b50c 29634 non-free/dep11/Components-amd64.yml.gz e113163e116c137577fc9d3a4f7c95e0934ddbae7bdae5e083aaa1ce095435b6 17904 non-free/dep11/Components-amd64.yml.xz 6177cb908c067306c11bd8728a5b65a205d999be63930c079e3ff4250a24ce8e 271451 non-free/dep11/Components-arm64.yml 1b6107a1fa771a8fff50e0b182362fd679dc01f58f7a1f3fe9fe0183daf3be0d 27686 non-free/dep11/Components-arm64.yml.gz 7ff5eda9a37e07b9bcfa479c89863d7b2b1aafbedbe4b37ea6c32a16f2eaa241 16392 non-free/dep11/Components-arm64.yml.xz f54eccd2dbf23fa45cab9e9e7abfafeb667397ea70b6197a3653e8499ffea8bf 271451 non-free/dep11/Components-armel.yml 5581d7f4c159a5cbd33927294f7fc9918e7deaf04b313001965c83412b6a81f7 27606 non-free/dep11/Components-armel.yml.gz 0830d150400c82255a52a74f6af9f1a11007bf4b92fc814513f9e13cfac0b22c 16448 non-free/dep11/Components-armel.yml.xz 15d1524c660c8fb1ee911775a9b59cebbc66843eb97cc0a15a361009f153e6ff 271451 non-free/dep11/Components-armhf.yml 3fa04d7715c8955987742dc376d10327a975f9583cf656da055d13895e460a67 27691 non-free/dep11/Components-armhf.yml.gz bbf5a05de96a53c0e10af6019cb7b053b83b0f5def488cde4d8359475adb08da 16364 non-free/dep11/Components-armhf.yml.xz 716cec6e00d8303375812c8c9be7cbfa5fc858fdb3d9af3f0c72a696d8f7cb2d 280613 non-free/dep11/Components-i386.yml 40f189b3b3a74bc85652829d0c67b21aad7e60ce389f26fe1959db1e1e8ec48c 31098 non-free/dep11/Components-i386.yml.gz 18507e0a03c74ed39b9bec853eb9216b458f2fe2b7535c2622c126b9cd35301e 19156 non-free/dep11/Components-i386.yml.xz d82d6fadb06b6a1f0d36c155b70a02eb2281838aee3ce1b9bf51b7ae06136721 271451 non-free/dep11/Components-mips64el.yml 25d788e157070218396bafba65ff087551830ba0d0ba3e3cec5342bb150aec57 27765 non-free/dep11/Components-mips64el.yml.gz 2d0aa3979fd6093dc6de8ba902166a985235c8c4926e07cab7aa2a9b4ad0c11d 16380 non-free/dep11/Components-mips64el.yml.xz c55445f6f87fd566212bb018f9fae1a4eb43c1a66fe1b0e198b1c7d7e500b009 271451 non-free/dep11/Components-ppc64el.yml f525af23f1a1eb26ee786c36e2afd4aa5e4102b646f33f8c6788aee395b752bf 27592 non-free/dep11/Components-ppc64el.yml.gz 0ee03164cca5098ec7c6f98a469818b40b61da7846451cc223d0b9e01585c57c 16576 non-free/dep11/Components-ppc64el.yml.xz 359af9af71c00d90265395225b75313966435729cf1f6cfb1085fe1721b01e72 271451 non-free/dep11/Components-s390x.yml 47ef508dff3dfdf17ceeed229d98a2e3992c1a26f28eb328a2d1958d2ddfe070 27558 non-free/dep11/Components-s390x.yml.gz 181db8b5130910114256e8809ff9a1637efac55b1f33d1f516983521b8d51e7b 16356 non-free/dep11/Components-s390x.yml.xz 601045de5331d63b7ef2a24f8f74a7452d7be785f94ae6c46002c5dc2608188f 8192 non-free/dep11/icons-128x128.tar 4fb59feb5d5afe99980ea36c3d7c14577a4b5f11705e7d16524767708666ed54 2394 non-free/dep11/icons-128x128.tar.gz 977a5470a45ec30f5e230361a446f4692f9cf9bc2abccf6eabac2df0291f1ee4 4096 non-free/dep11/icons-48x48.tar 07a401f7b03554c2d8ab32dea5885c43b7da7badeea0569b9ce5c9dbbb7cf66f 741 non-free/dep11/icons-48x48.tar.gz 159551b3012db94a70261cb8f88619a6bb148318da051479ade6df7211c41a34 36864 non-free/dep11/icons-64x64.tar 872b7437de6fb938db8b26d9de9a3113bc722cd6ed682973151722e2b7a190be 27667 non-free/dep11/icons-64x64.tar.gz db924f2bd81a5875019d05bea92accc667c5a99099512ee11862db412c21d7fb 572893 non-free/i18n/Translation-en 91ff4a231eff217916da9113aa017d4090fe442fa54f1edf21af3811e0bb255a 92419 non-free/i18n/Translation-en.bz2 6372d37a918ae4dc1be5a748e9e02e57573e765e14a3c8aa0f37208b223555cc 121 non-free/source/Release 2bd47d8b576397abf753f06eb5bec85b2036e84b80b8d8646a0e784380d0d53e 360307 non-free/source/Sources c9d5108699279e6cb2946d907c13655ebe8b6fce12986a4ba8b0ece0257977c1 98323 non-free/source/Sources.gz 3f3f09477a76bf44bbd93e7efc74f55783f0841c6692d6188b91e8f58a0c7999 81280 non-free/source/Sources.xz -----BEGIN PGP SIGNATURE----- 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 EXyj =h5YC -----END PGP SIGNATURE----- ")?; assert_eq!(remaining, b""); let mut keyring = Keyring::default(); keyring.add_keyring(include_bytes!( "../contrib/debian-archive-bullseye-automatic.gpg" ))?; keyring.add_keyring(include_bytes!( "../contrib/debian-archive-bullseye-stable.gpg" ))?; let content = b"Origin: Debian Label: Debian Suite: stable Version: 11.6 Codename: bullseye Changelogs: https://metadata.ftp-master.debian.org/changelogs/@CHANGEPATH@_changelog Date: Sat, 17 Dec 2022 10:14:37 UTC Acquire-By-Hash: yes No-Support-for-Architecture-all: Packages Architectures: all amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x Components: main contrib non-free Description: Debian 11.6 Released 17 December 2022 MD5Sum: 7fdf4db15250af5368cc52a91e8edbce 738242 contrib/Contents-all cbd7bc4d3eb517ac2b22f929dfc07b47 57319 contrib/Contents-all.gz 6e4ef0f159fa08f5ba74067e0a94b5e6 787321 contrib/Contents-amd64 98583d055424774c060fdf4b02291da5 54668 contrib/Contents-amd64.gz 61e10f1703d718d584f381a943bfe4d7 370915 contrib/Contents-arm64 86a145a0d8d7346449f2cf62098a5553 29596 contrib/Contents-arm64.gz b6d2673f17fbdb3a5ce92404a62c2d7e 359292 contrib/Contents-armel d02d94be587d56a1246b407669d2a24c 28039 contrib/Contents-armel.gz d272ba9da0f302b6c09a36899e738115 367655 contrib/Contents-armhf 317aa67ea34d625837d245f6fb00bdc4 29236 contrib/Contents-armhf.gz ccb13401b0f48dded08ed089f8074765 407328 contrib/Contents-i386 e496015d7e6e8d5a91cec31fc4bde74c 33556 contrib/Contents-i386.gz 44384de1db64f592fc69693b355a0ec7 359402 contrib/Contents-mips64el a2abf38d14c1c7e3aafcb21881b0fe7d 27962 contrib/Contents-mips64el.gz 457feed233db5ce7db62cc69e7a8a5c6 360549 contrib/Contents-mipsel 90ec76d0dca539a4c4aa33404de4c633 27942 contrib/Contents-mipsel.gz 02985cbbdd1e790b29a9911ba00b5650 370025 contrib/Contents-ppc64el b34b90df14207eafe94313e6d466b28e 29381 contrib/Contents-ppc64el.gz e2089c91540f7adb693675935dacf9e5 357860 contrib/Contents-s390x bb90fb42e72d39da53b3e1e2c2f46bc3 27518 contrib/Contents-s390x.gz ba62d5cf69ffc155d75fa9e16228b039 6722669 contrib/Contents-source fec97c652e41904e73f17cc5f7b0b2ff 469817 contrib/Contents-source.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-all 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-all.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-amd64 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-amd64.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-arm64 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-arm64.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-armel 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-armel.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-armhf 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-armhf.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-i386 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-i386.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-mips64el 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-mips64el.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-mipsel 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-mipsel.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-ppc64el 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-ppc64el.gz d41d8cd98f00b204e9800998ecf8427e 0 contrib/Contents-udeb-s390x 4a4dd3598707603b3f76a2378a4504aa 20 contrib/Contents-udeb-s390x.gz 73d0ad5df01464248f578fb7d7ba10b0 103239 contrib/binary-all/Packages 6848b84ab94b0624ad15f5afea5f49bd 27385 contrib/binary-all/Packages.gz a9e21972669e0355e9a875ea31f25c63 23916 contrib/binary-all/Packages.xz 3c9131b20395850cbf9735dfbc0cd6a7 117 contrib/binary-all/Release b6541899bd7907d9dc5afe604d26a719 231878 contrib/binary-amd64/Packages 7cb1a35df9e7ef744685d28932cc1ef2 60884 contrib/binary-amd64/Packages.gz 4ee4184e78f4b0d06e981706a6118dc7 50588 contrib/binary-amd64/Packages.xz 7edd7af81aa30d5a929cad55b259de23 119 contrib/binary-amd64/Release 4b9c68a7d2d23357dc171d29a03565c6 180884 contrib/binary-arm64/Packages c2d2253fb81e2a397e4a42d4d475bd24 48958 contrib/binary-arm64/Packages.gz f57a0a52945226cc76c241ce57c182be 40964 contrib/binary-arm64/Packages.xz 34b661285be33d5dd033de35b00b0b52 119 contrib/binary-arm64/Release 1636c115e53ef208266fcc6b024f7b34 163042 contrib/binary-armel/Packages ed80c2afd00562cee8543a3835ed0907 44389 contrib/binary-armel/Packages.gz ef8175333695e1554eeb8766d74c4795 37452 contrib/binary-armel/Packages.xz f5908602701eedda3f627be810655de2 119 contrib/binary-armel/Release 900f4a8949a535dfd1af4326b43e6fa4 175566 contrib/binary-armhf/Packages 11db111d1dd40616866a8b6d4e59ca8d 47805 contrib/binary-armhf/Packages.gz 512198b43afc25d9da1e078b44f5b4a8 40220 contrib/binary-armhf/Packages.xz 7271fc19a10e612fcdc17bfc361a4805 119 contrib/binary-armhf/Release feb05a736bdfbd41bfdd4d87fd34f72a 203514 contrib/binary-i386/Packages 89a79f0c9d4bb2df7d3dc3d165f02242 54100 contrib/binary-i386/Packages.gz 130d6b77d3b32c1ec94097e694d66718 45340 contrib/binary-i386/Packages.xz 8dc8ab0c142d7166f1a8cb8ef5c8dcaa 118 contrib/binary-i386/Release 825bc5698936bc26f5bb28c20287aeb1 163507 contrib/binary-mips64el/Packages 190dd8f6a3e97c3ebe8ab216e79ed867 44652 contrib/binary-mips64el/Packages.gz 9302a32bad830648c066bfb13a35b6b9 37496 contrib/binary-mips64el/Packages.xz 268c4243d0a655c886c9533779085b8e 122 contrib/binary-mips64el/Release 4e717be16d235fb7e6e118c898ac80af 164647 contrib/binary-mipsel/Packages f73fd75fc0a6371ae7e6b709a4d8d939 44883 contrib/binary-mipsel/Packages.gz 9c8d77e03dcdc178465c28095f4e8d64 37816 contrib/binary-mipsel/Packages.xz 5e4a6cc21b9343c50ab7eeb20be00166 120 contrib/binary-mipsel/Release 1343f3307bbeea9f0b04dd64e8d23d62 180387 contrib/binary-ppc64el/Packages 831c14a6428bbe7b05d290e9aa225785 48843 contrib/binary-ppc64el/Packages.gz 8daa347dc96d3f69e7510c0d3f51916e 40808 contrib/binary-ppc64el/Packages.xz 44eda0cdaff945cc2cb4f8bdfad50371 121 contrib/binary-ppc64el/Release 1a2b7365b25b44a4304271198bda5094 162250 contrib/binary-s390x/Packages 103b59f69a5c230eab05d06289ad7c9b 44334 contrib/binary-s390x/Packages.gz e4109e4637f7b1c233130da040451fd9 37244 contrib/binary-s390x/Packages.xz aa08c18b750a7efa1a4c3f23650132a4 119 contrib/binary-s390x/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-all/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-all/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-all/Packages.xz 3c9131b20395850cbf9735dfbc0cd6a7 117 contrib/debian-installer/binary-all/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-amd64/Packages.xz 7edd7af81aa30d5a929cad55b259de23 119 contrib/debian-installer/binary-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-arm64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-arm64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-arm64/Packages.xz 34b661285be33d5dd033de35b00b0b52 119 contrib/debian-installer/binary-arm64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-armel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-armel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-armel/Packages.xz f5908602701eedda3f627be810655de2 119 contrib/debian-installer/binary-armel/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-armhf/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-armhf/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-armhf/Packages.xz 7271fc19a10e612fcdc17bfc361a4805 119 contrib/debian-installer/binary-armhf/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-i386/Packages.xz 8dc8ab0c142d7166f1a8cb8ef5c8dcaa 118 contrib/debian-installer/binary-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mips64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mips64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mips64el/Packages.xz 268c4243d0a655c886c9533779085b8e 122 contrib/debian-installer/binary-mips64el/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mipsel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mipsel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mipsel/Packages.xz 5e4a6cc21b9343c50ab7eeb20be00166 120 contrib/debian-installer/binary-mipsel/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-ppc64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-ppc64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-ppc64el/Packages.xz 44eda0cdaff945cc2cb4f8bdfad50371 121 contrib/debian-installer/binary-ppc64el/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-s390x/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-s390x/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-s390x/Packages.xz aa08c18b750a7efa1a4c3f23650132a4 119 contrib/debian-installer/binary-s390x/Release fc412a0e8fed50416ae55ca3a34c2654 119152 contrib/dep11/Components-amd64.yml 7473c932902284e9c636636a5ff0587b 15579 contrib/dep11/Components-amd64.yml.gz 751b272121122fce4882d17a9d099c44 13564 contrib/dep11/Components-amd64.yml.xz 49911a9d2f76ed13124c7cff0081266b 113437 contrib/dep11/Components-arm64.yml ee72e145d0e71d94c0d418d36dabfd8c 14251 contrib/dep11/Components-arm64.yml.gz 65f48dc9acec772076e60ce35239703f 12480 contrib/dep11/Components-arm64.yml.xz b1f970bbcdd889ccff5c2646bc2835ba 113437 contrib/dep11/Components-armel.yml d2a414b1147562c0ecfa1aab53fc0260 14029 contrib/dep11/Components-armel.yml.gz b450a677c3a5d4a52d2a0df274c222cf 12524 contrib/dep11/Components-armel.yml.xz 75c6b8bd42fc863caa66c454306c7d39 113437 contrib/dep11/Components-armhf.yml ac52f103d1c493d0f8d8e5662d758f78 14127 contrib/dep11/Components-armhf.yml.gz 80f4310b2d68bf09c7fbba34a0eec794 12480 contrib/dep11/Components-armhf.yml.xz a46b6878a89f45fab86aca68bffe081d 118972 contrib/dep11/Components-i386.yml 751ea67ac68d2e755726b4e9d62ab15e 15566 contrib/dep11/Components-i386.yml.gz 82c956565311c8a7d90bff6e0a226fbe 13560 contrib/dep11/Components-i386.yml.xz 6f822ef8f2c13dc4212ade261b4a8752 113437 contrib/dep11/Components-mips64el.yml a072aab0fb45dab4a6e25295f23e9b5f 14056 contrib/dep11/Components-mips64el.yml.gz e5c2dd7fd785fa1ab66099d7763bd670 12500 contrib/dep11/Components-mips64el.yml.xz 432a29a22c4a782f6edad376f386937f 113437 contrib/dep11/Components-ppc64el.yml b5202b5037949e593060f92290d6f949 14219 contrib/dep11/Components-ppc64el.yml.gz dd92a500c7807091665dbc207c9bef68 12496 contrib/dep11/Components-ppc64el.yml.xz 53c6b87820861b0ed316a88f7542cd76 113437 contrib/dep11/Components-s390x.yml 5a4872d3187bc79418b468890be4b5fe 14050 contrib/dep11/Components-s390x.yml.gz eefb3301e486aedbbbb1d735e2522a00 12488 contrib/dep11/Components-s390x.yml.xz 5d8e37f26e7e15f367751089fa13c876 271360 contrib/dep11/icons-128x128.tar 500b14a4cafa23b9106b402737f863a7 195507 contrib/dep11/icons-128x128.tar.gz d9651fb188be2221d2f583aeba83d8fc 83968 contrib/dep11/icons-48x48.tar 6b5ea4675ad78554aaa53b344f1bd146 47168 contrib/dep11/icons-48x48.tar.gz 7115d3a3d41fc9bca9cfcc3c608bebf2 138752 contrib/dep11/icons-64x64.tar c839e679f1d60d294d39884d0911e514 93294 contrib/dep11/icons-64x64.tar.gz 01e75740c90a7df7e474a1c6152b2aa6 192685 contrib/i18n/Translation-en a2e9608c3e388d26e031583f200e2f92 46929 contrib/i18n/Translation-en.bz2 7b851a6fc52e455ec6e64d1bbd002e60 120 contrib/source/Release d615756c28aa372e2bc408abe1d9ec5b 178776 contrib/source/Sources c19b950adb0b02bb84fec45d11d257d8 51355 contrib/source/Sources.gz 0e1710e68ffbd6a7b3542844610a69fc 43208 contrib/source/Sources.xz 052421edd3e77801652c5e82cea27172 477769406 main/Contents-all c6642306466300d5b980a46ab2da3448 31069218 main/Contents-all.gz 4f76cfae77ca68a2534e4776c1ba603a 129058022 main/Contents-amd64 d00bf88e20a9167d72c15f914e2f6ae6 10270460 main/Contents-amd64.gz 4c143d623f5b8d26d47c079554c17287 122426895 main/Contents-arm64 44ba782a6a21b58a1ff85d2c04785f8d 9831920 main/Contents-arm64.gz 801e7ed91bc44eb81525999ec2a8291e 104683113 main/Contents-armel a5a18ca6cde98c20f5b89666cc6ada02 8703570 main/Contents-armel.gz 307b7ca5872bf53d92aced5dc4fa75ba 113716591 main/Contents-armhf ec3f7e25caefcde0999e74f88fe29c25 9305906 main/Contents-armhf.gz 39e08183dd281004ce0853d8138db6b9 129088857 main/Contents-i386 4339b5c20026a75c512e5c97c56ac03c 10208982 main/Contents-i386.gz 1468642d6dbe21a9b910d360f52d1a71 111097071 main/Contents-mips64el f5727ac1ba4208d6994869b64251d40f 9042221 main/Contents-mips64el.gz 30ac6e6b838d5fc79a6139fc5b4e7337 112593872 main/Contents-mipsel 13fcab9f9e956d966bf9975da41bec6c 9178325 main/Contents-mipsel.gz 985636740f62394375012f87593d5c21 116027632 main/Contents-ppc64el 97f1aaf6603044158ce139c2570992d0 9355024 main/Contents-ppc64el.gz 332ff60dc3b48ca16f5bf3baa139b530 103638209 main/Contents-s390x 1dfb6d3460020eb28ef7ab36bd7d0c08 8711885 main/Contents-s390x.gz 30e2a744a0a8fc6c48325fa30d7d0e70 690410830 main/Contents-source 453c66c682ee49babee0fac4ec460ac7 73501881 main/Contents-source.gz 1f4bf598c355a2bbb0c8ddf889d9636e 157382 main/Contents-udeb-all 708ed31f29f9daf4c980b7abdd66c356 13516 main/Contents-udeb-all.gz 069860439eabdda442aa81afb59f8644 477050 main/Contents-udeb-amd64 6e95b271bba66b8135cdd9ee13cad982 36011 main/Contents-udeb-amd64.gz 8884d6660508188095f2991c73ede3a2 508817 main/Contents-udeb-arm64 a972a7d9191733ca34c65bbec0c4da30 38139 main/Contents-udeb-arm64.gz 72cc361d1b9ae73eeb7e3798a52564b2 323083 main/Contents-udeb-armel 2521b5dc40ca4ce0c2cf495642512931 25477 main/Contents-udeb-armel.gz b74da65320e8e14ccd398d9b3a0af741 579793 main/Contents-udeb-armhf a6b01ebd28d333afe285226a6d3902b5 43153 main/Contents-udeb-armhf.gz 02f78f33d39614e8f2c1ae4a5971637a 751383 main/Contents-udeb-i386 f77c976f4226372caba729cd86720f36 53984 main/Contents-udeb-i386.gz fc8c6638ad4e7036abcfb74c9ca40e67 760534 main/Contents-udeb-mips64el b29f9bef4f9b6237adac6822c3f644ee 52873 main/Contents-udeb-mips64el.gz 8851f799ab3bac7dbe3ade6ca88058d3 760210 main/Contents-udeb-mipsel f5b4e16d70afd5fe145bbcff78ed60c7 52810 main/Contents-udeb-mipsel.gz b0c21603250d55447094b00f1438aef7 401639 main/Contents-udeb-ppc64el 9cc88f8f084a1bf1b0f4a3f7d4d2baa1 29533 main/Contents-udeb-ppc64el.gz 942cbd0dfe1ec1bbc24f50b6a22102e0 258318 main/Contents-udeb-s390x bdeed95042d0b946c8d8f72cb49fd28d 20894 main/Contents-udeb-s390x.gz 779c0c7072ee9cd9b776167e3b0d8694 20423830 main/binary-all/Packages 78a6edfff04a3b7505c0b8b1cc468c68 5208282 main/binary-all/Packages.gz 296b8e6e27112ca9610cde0fbc84f34f 3918264 main/binary-all/Packages.xz d8d2edd733e3235987c8c0c9565344d8 114 main/binary-all/Release ee0b34bb7ba7a8e1a7964ebd20187def 45534962 main/binary-amd64/Packages c14373e666988e64b30c26f3b6c3fbf2 11096605 main/binary-amd64/Packages.gz f30e2d1e8f395c903155dda0c4ba0970 8182920 main/binary-amd64/Packages.xz dbeadc926a4f14b4a73390c82832052b 116 main/binary-amd64/Release e02c425b41e1c7f2e910960cb80b8fc6 44816551 main/binary-arm64/Packages 854700a00d0c4c7b9f8b7946d97b85fc 10941625 main/binary-arm64/Packages.gz 3fd4c3700b238504448734039842d4fd 8071508 main/binary-arm64/Packages.xz f02cb9aab85fccb7a19d168b5acb2390 116 main/binary-arm64/Release a0174a68bcedce8fba19bde6cd1208b3 43343990 main/binary-armel/Packages 56c75313e445b1b136fd240122a4a207 10677432 main/binary-armel/Packages.gz 797f4ee8e47a372aae0a83ea352fe2fa 7871888 main/binary-armel/Packages.xz 358a6eb5337f79950b79beaae6d06bd4 116 main/binary-armel/Release d4028809623d98cbf20cb043be845906 43846413 main/binary-armhf/Packages 8326ddf7c01158570ca901a8827c0449 10775534 main/binary-armhf/Packages.gz 5845702f6c696189347091fd5cb51276 7944712 main/binary-armhf/Packages.xz 8811dc441114bb1b2f90dfce9ff6acfc 116 main/binary-armhf/Release 99f2432683f72cb4833cc0392f8a1313 45094980 main/binary-i386/Packages 1c5363ed68d7894cf94ab51ec66bf926 11013153 main/binary-i386/Packages.gz 534024b184373545b78e74aa164ba211 8121972 main/binary-i386/Packages.xz 50b3c16ad95352c06904ec1341afe2d2 115 main/binary-i386/Release 87f3a748abd585d485b04e11a8f75fa8 43733274 main/binary-mips64el/Packages e7ee93fdf444409e1d751e3160a599e3 10720185 main/binary-mips64el/Packages.gz c2f655d6e0fb46a1eb029045054e5b52 7907404 main/binary-mips64el/Packages.xz c0cc63128ced0d323a714281b3f78ba2 119 main/binary-mips64el/Release d5fc8d1553a24222dda3e6fc804b2aeb 43667386 main/binary-mipsel/Packages 88a8a5f188c1a0e18255daab88d8c83f 10726366 main/binary-mipsel/Packages.gz c9568fef286c9fe7d80cdcf9dece78bc 7906936 main/binary-mipsel/Packages.xz 0ac20990fd13d5eaf32c0041fd37c568 117 main/binary-mipsel/Release 735e4dcaafa4c558fd21e8a7075f4997 44671240 main/binary-ppc64el/Packages 5f14e959fec4dfca2d5b3f8b7bd090af 10884852 main/binary-ppc64el/Packages.gz 1b587b581cb630066fa51c8ea85ea327 8031816 main/binary-ppc64el/Packages.xz 641a1901dc2496b912f4f49e9f7d4db8 118 main/binary-ppc64el/Release d93e11281b31f88d89a0d1eb73cc13ca 43340190 main/binary-s390x/Packages 1ca35cf8189cbb3fe643b9be4ca39e48 10686656 main/binary-s390x/Packages.gz 9f00d6b29f1659c08eea54ca8e0e652e 7877060 main/binary-s390x/Packages.xz 40a1a7ba21820ed919518a0e4f6cbbbd 116 main/binary-s390x/Release 8523f5593a344ec29029e3e20b8e10fa 61160 main/debian-installer/binary-all/Packages 8322a8e0b943187cc1ad41f5e91e0c8c 16449 main/debian-installer/binary-all/Packages.gz 73f68ee665b0ba4fe8b1d5bd0986e6a1 14676 main/debian-installer/binary-all/Packages.xz d8d2edd733e3235987c8c0c9565344d8 114 main/debian-installer/binary-all/Release e5156b114c9a46b50dc7b14217399795 274352 main/debian-installer/binary-amd64/Packages fa8d2c9b9be51d30622654b67ecac5c5 67349 main/debian-installer/binary-amd64/Packages.gz 79cadb77602e77b501f0d9354d6a940b 56064 main/debian-installer/binary-amd64/Packages.xz dbeadc926a4f14b4a73390c82832052b 116 main/debian-installer/binary-amd64/Release bf5150ba5d1823e80ce45b268a79a392 257349 main/debian-installer/binary-arm64/Packages 74c5e0915ec84c2c336d97652ffa0a7a 64271 main/debian-installer/binary-arm64/Packages.gz cca08998fcdd03ca3284112927344e20 53980 main/debian-installer/binary-arm64/Packages.xz f02cb9aab85fccb7a19d168b5acb2390 116 main/debian-installer/binary-arm64/Release 79673899cedce0be43ebc1d416fb58bd 248363 main/debian-installer/binary-armel/Packages 80bf080680db4b7b02ed444454b8981f 63792 main/debian-installer/binary-armel/Packages.gz 7cfb8b710c1228c6359c7b48041cc8c0 53168 main/debian-installer/binary-armel/Packages.xz 358a6eb5337f79950b79beaae6d06bd4 116 main/debian-installer/binary-armel/Release 1f43e9a44586e87494ec1a7269ec7f2c 251788 main/debian-installer/binary-armhf/Packages 262d12c86cfee6e0c82383272d15c377 64864 main/debian-installer/binary-armhf/Packages.gz b4db61d6a2322a13cf8d6b0f49e9ffbe 53852 main/debian-installer/binary-armhf/Packages.xz 8811dc441114bb1b2f90dfce9ff6acfc 116 main/debian-installer/binary-armhf/Release cd8f8bf8d19b9ba5a1efc7a75930121a 349445 main/debian-installer/binary-i386/Packages 41400360bb68ffe289e94a68da63e79f 77230 main/debian-installer/binary-i386/Packages.gz 2a77d691876cab7b5f0803b7611ca267 64124 main/debian-installer/binary-i386/Packages.xz 50b3c16ad95352c06904ec1341afe2d2 115 main/debian-installer/binary-i386/Release c22d0ce635eb0fae86afba6242116a19 364716 main/debian-installer/binary-mips64el/Packages 1aef85058cd12a9638321fedd2ffff31 79498 main/debian-installer/binary-mips64el/Packages.gz 9d5da1ee87189d9671b42c4bc122c48a 66396 main/debian-installer/binary-mips64el/Packages.xz c0cc63128ced0d323a714281b3f78ba2 119 main/debian-installer/binary-mips64el/Release 18bc2f5de2b576eee963afeb65375aab 364202 main/debian-installer/binary-mipsel/Packages a1b8c712b5272debb29e8c07de9caf0b 79784 main/debian-installer/binary-mipsel/Packages.gz cce1945593d8c4b82fd33b6e5f761521 66500 main/debian-installer/binary-mipsel/Packages.xz 0ac20990fd13d5eaf32c0041fd37c568 117 main/debian-installer/binary-mipsel/Release d7b8901246bae032e5ddbc9e45cc872c 256933 main/debian-installer/binary-ppc64el/Packages 70a122a874633fde8db5504f98ee7439 64920 main/debian-installer/binary-ppc64el/Packages.gz f2e4f1994de7021fbfc39fa44056b2b1 53960 main/debian-installer/binary-ppc64el/Packages.xz 641a1901dc2496b912f4f49e9f7d4db8 118 main/debian-installer/binary-ppc64el/Release 1b44e25a26eefd464c288608423d6e42 226275 main/debian-installer/binary-s390x/Packages 095ad8009e027e93ec3bbe8678eef9f6 60464 main/debian-installer/binary-s390x/Packages.gz e513ca8104e23a972e147e86ef1bf5ab 50116 main/debian-installer/binary-s390x/Packages.xz 40a1a7ba21820ed919518a0e4f6cbbbd 116 main/debian-installer/binary-s390x/Release 97a6eda13094854f8838218d5869a796 18520413 main/dep11/Components-amd64.yml 9cd807c0b66a8489b5385bf4f343b288 6213469 main/dep11/Components-amd64.yml.gz c16ba02c289510dce9857dfa6cde4550 4048504 main/dep11/Components-amd64.yml.xz 3e8ecb0bbaecb88d0b16dfaa037dba73 18436837 main/dep11/Components-arm64.yml 09ef5a87673c946f916b0d8ef0c2471d 6191092 main/dep11/Components-arm64.yml.gz fef127cee05f3efb96261e78b4fe4568 4033216 main/dep11/Components-arm64.yml.xz 67becc674b536e310fe22492d55c8652 17658848 main/dep11/Components-armel.yml 34cd8a6a1206f804e6d5c54dcdd3ef63 5952269 main/dep11/Components-armel.yml.gz d7cc0222cae53bcfa1de29218fe5cb94 3879744 main/dep11/Components-armel.yml.xz 09010fea4c1cf082bd54aecc24182e45 18205252 main/dep11/Components-armhf.yml f5b7fd1a9cb147fa6b90e60a4d2139c1 6110587 main/dep11/Components-armhf.yml.gz f1f223ca9e69ad1901345ceb404a5666 3983180 main/dep11/Components-armhf.yml.xz ee8f83c597007ab84b58feec05d647fa 18485654 main/dep11/Components-i386.yml 5a6b35ea7b54d88842ab30bbbd469623 6201776 main/dep11/Components-i386.yml.gz 239cc12774e7c2925d1d783faaf01b5d 4041608 main/dep11/Components-i386.yml.xz dd59f50383f269a8e1ec09c49d8a786c 17819116 main/dep11/Components-mips64el.yml e3f03ed2f2c22dac3207e5f3fb98f862 5977494 main/dep11/Components-mips64el.yml.gz 437c9fa1e058fc9a3486fb8b224740f6 3896708 main/dep11/Components-mips64el.yml.xz 09d0cb63fdf4a4904155dc0d56ccc04b 17947079 main/dep11/Components-ppc64el.yml 3d396ef7d8293620c5160a75fda04d39 6023058 main/dep11/Components-ppc64el.yml.gz 23ebc600f44eb4973c351a4a324ba219 3925796 main/dep11/Components-ppc64el.yml.xz 64acc85d1d2ce3e3dc551ae85e80ca57 17735785 main/dep11/Components-s390x.yml b7f851e780c93532c1707895dfa22474 5976062 main/dep11/Components-s390x.yml.gz 117c2f52a672bca008f2c206ad8527a6 3894008 main/dep11/Components-s390x.yml.xz 3f40799bee1a72a060f7dff19efa7b05 13048320 main/dep11/icons-128x128.tar 6ac207d4fb6b76c25dc59edb50c3bf6b 11409337 main/dep11/icons-128x128.tar.gz 66ce5f075d189138824e736123711450 4878336 main/dep11/icons-48x48.tar 260bbc45bfa6b33e31399b4adb3b1f6d 3477622 main/dep11/icons-48x48.tar.gz 47dea6d08e37b4a5154a072f3ad92cf0 9378816 main/dep11/icons-64x64.tar 417f46677b9086f9dd0a425f0f39ee31 7315395 main/dep11/icons-64x64.tar.gz 180389879ed6715b463d05b637e191dc 6191 main/i18n/Translation-ca 8f8b7ffa4659d4f03b65ed28e69821f9 2673 main/i18n/Translation-ca.bz2 b4ef33a20d80c576c7b352e96a86e063 1205166 main/i18n/Translation-cs d70ae6198f35f876b3070d928d5cdba2 323247 main/i18n/Translation-cs.bz2 3fa5a10989da6ec5b19b5b6ba161b0bf 20240560 main/i18n/Translation-da e83f678061ca99aaedd2f20cb75bba77 4411163 main/i18n/Translation-da.bz2 9f5077418506388082a72c7023c56f8f 7801238 main/i18n/Translation-de a57e3821e975f45d21bf2388a190b770 1717951 main/i18n/Translation-de.bz2 a344219bf0eec9139d5270017ecfceee 1347 main/i18n/Translation-de_DE 0fe0725f74bb5249f15f30ce965142d5 830 main/i18n/Translation-de_DE.bz2 87bf9810c05aba15fb4aca6791feb73d 6257 main/i18n/Translation-el 002ddfc4187acd8414873fe9f0a6442a 1835 main/i18n/Translation-el.bz2 36467cceb9cb2cea759d49c8759be7f9 30246698 main/i18n/Translation-en b4a727f22675ec9db1426d7dbc7a34f0 6240167 main/i18n/Translation-en.bz2 0fdd8948881357f49ead0845c7e621c1 2261 main/i18n/Translation-eo 43bd21f8b5d52b955e509e5893eef37e 1196 main/i18n/Translation-eo.bz2 2ad9740f4bf39f163c04bd0b7266c1aa 1325929 main/i18n/Translation-es b4d4140461b4d6195e3337dcf541554f 317946 main/i18n/Translation-es.bz2 2f7f0aac6c4ae5bd9c1499fd612ef996 10093 main/i18n/Translation-eu 3178567e5f21fe43e4cf1f1a38ed6adc 3914 main/i18n/Translation-eu.bz2 d1e71d50a88504d6b48c27960250acae 269212 main/i18n/Translation-fi 9ca11408c191cfc5270f39467ed80f9b 75849 main/i18n/Translation-fi.bz2 945a63eed28af4c45fd5185b334b33b3 11857302 main/i18n/Translation-fr 06100e8db22b6d72d2c466bc85ea117b 2433064 main/i18n/Translation-fr.bz2 f543980d7c6e8335eb0bb5d00b787418 1427 main/i18n/Translation-gl 09c22bb0dfa3874802c4e7e4389f2b58 824 main/i18n/Translation-gl.bz2 363537eb238e19bd527554a2d1de2533 21069 main/i18n/Translation-hr 3fbd3535dcc2e805f0283d54bd38f5f3 4695 main/i18n/Translation-hr.bz2 5393df220c56a4a92b91b2cac6843067 65236 main/i18n/Translation-hu 61236a1bada04fd4ab090269498c5393 22243 main/i18n/Translation-hu.bz2 d8d93a0510fedeb68fbbdae0342520c0 3983 main/i18n/Translation-id 7542ee230bbc1f2f9f873c265b3b467f 1780 main/i18n/Translation-id.bz2 87ba73fdeb9bac4348a4be42b2386f32 24489940 main/i18n/Translation-it 9c9cd08156baf73f9f088bb97ac00662 4844227 main/i18n/Translation-it.bz2 0f39595a0a049759d0d50ead781f73fd 4511401 main/i18n/Translation-ja 74ff41ba40e19c9ceb4c607b122b7811 803966 main/i18n/Translation-ja.bz2 85c4f9ec1e8e2d6faab177ef030ad2aa 11879 main/i18n/Translation-km 46d57c586859cecf5c1a4470f666000d 2371 main/i18n/Translation-km.bz2 def6a2d200b3c67b6a1c497524d0a631 2606190 main/i18n/Translation-ko 3210a7e112a3f29ecf785ba05a78559a 584643 main/i18n/Translation-ko.bz2 d41d8cd98f00b204e9800998ecf8427e 0 main/i18n/Translation-ml 4059d198768f9f8dc9372dc1c54bc3c3 14 main/i18n/Translation-ml.bz2 904af013a9ba73cd72f71a1ca451be5a 1193 main/i18n/Translation-nb bf917a722cf4d90cf2f56acb8edb1b31 738 main/i18n/Translation-nb.bz2 cb57eb70e5645204174caec8edcc4a2b 174332 main/i18n/Translation-nl ad8c86dde21a892ff20203dc71eb981c 47973 main/i18n/Translation-nl.bz2 bc88d84933fd8ae64ea0a7ba32a1e814 2051811 main/i18n/Translation-pl 3095483ca3926b759de515651199283a 491993 main/i18n/Translation-pl.bz2 d1736cf50b7994e7c6ce66962b7f4b03 1074959 main/i18n/Translation-pt 7f9e024af1c410635fc69db5bf5d090a 272186 main/i18n/Translation-pt.bz2 c3453467a749e3888da35949b643835d 3306707 main/i18n/Translation-pt_BR 89726f5a5abac29bd3a6069e27019c9a 802734 main/i18n/Translation-pt_BR.bz2 b50c9c49ea0a9da73b0a76db38a36ea4 1717 main/i18n/Translation-ro 22696f68e30228ffbd84b26dbc821f81 982 main/i18n/Translation-ro.bz2 52035b6ff376a4d7c38eea8bbd406751 3058931 main/i18n/Translation-ru d6c7de740e63ee4ce0e2044a0d449804 494782 main/i18n/Translation-ru.bz2 2b383f6dbb23852965418241eda484de 5984088 main/i18n/Translation-sk 04f2970e8de7fc5a090b84ab700cbb23 1304539 main/i18n/Translation-sk.bz2 cf58326418b53f94289ad593878bfda2 323953 main/i18n/Translation-sr 096b962e3404fbc28ebfb174e7587136 58385 main/i18n/Translation-sr.bz2 366024c5bc4dabb550f8481c2d662611 85612 main/i18n/Translation-sv 22b0c4eaa8e59ee11318ce2e68953f4b 27320 main/i18n/Translation-sv.bz2 ced97abb44ee155f744680871aa5a6e2 14670 main/i18n/Translation-tr 233a8366a334283e9b802cae336ed09b 5362 main/i18n/Translation-tr.bz2 c8840c6e4bbe54b098d5b589e5d9e08b 3740343 main/i18n/Translation-uk 7ed20cfd2585b8f77be6e2bab7561133 576766 main/i18n/Translation-uk.bz2 2adb559c8ab8415644e43781db4f739a 21882 main/i18n/Translation-vi 82caa7c535a1c4c7589a7b1647017f53 6510 main/i18n/Translation-vi.bz2 f895594ce62c202132bbbe9ae32f1bc2 2007 main/i18n/Translation-zh 3d2be55ee5ef9a79e0db9f90acc449cf 1215 main/i18n/Translation-zh.bz2 91e9eec000876a989969a700ac7b3821 425199 main/i18n/Translation-zh_CN ab34838b3553d042d515eb65f5aa8816 113621 main/i18n/Translation-zh_CN.bz2 34208715b80dcbd5fd1b87874a6705d4 39965 main/i18n/Translation-zh_TW 6ed487c9d90ac9866174796ce73dec77 14859 main/i18n/Translation-zh_TW.bz2 c8730ab591a9c561bfbe29bb2bd721d9 58277 main/installer-amd64/20210731+deb11u7+b1/images/MD5SUMS 1a197cdc8ba7a3094159a1ebec0b24f9 78097 main/installer-amd64/20210731+deb11u7+b1/images/SHA256SUMS 8521cd018a0e0b50238dab3cf673c4f7 57705 main/installer-amd64/20210731/images/MD5SUMS bb4d5d5a421f536dcaa3f2e4fc96c1c3 77333 main/installer-amd64/20210731/images/SHA256SUMS c8730ab591a9c561bfbe29bb2bd721d9 58277 main/installer-amd64/current/images/MD5SUMS 1a197cdc8ba7a3094159a1ebec0b24f9 78097 main/installer-amd64/current/images/SHA256SUMS 026bc90f5673b695c093e88b6e0ec351 69049 main/installer-arm64/20210731+deb11u7+b1/images/MD5SUMS 5ef21176e2d62d993fdad8fe6f66d13f 94149 main/installer-arm64/20210731+deb11u7+b1/images/SHA256SUMS 8544dac6e811bff5ed42e276cf530ebf 68403 main/installer-arm64/20210731/images/MD5SUMS 7989c6f2e37aeda05d7dfc58de88d7f5 93279 main/installer-arm64/20210731/images/SHA256SUMS 026bc90f5673b695c093e88b6e0ec351 69049 main/installer-arm64/current/images/MD5SUMS 5ef21176e2d62d993fdad8fe6f66d13f 94149 main/installer-arm64/current/images/SHA256SUMS 9d5c1487daa7fbbc0eb09a58cd905102 20678 main/installer-armel/20210731+deb11u7+b1/images/MD5SUMS 9caca58b3425516dd16fec20f1ee05fd 28882 main/installer-armel/20210731+deb11u7+b1/images/SHA256SUMS 6e3afe07880cea11cee1a8ac19ce5d13 20182 main/installer-armel/20210731/images/MD5SUMS 350c18339820cfa3989e1297c80b9f12 28194 main/installer-armel/20210731/images/SHA256SUMS 9d5c1487daa7fbbc0eb09a58cd905102 20678 main/installer-armel/current/images/MD5SUMS 9caca58b3425516dd16fec20f1ee05fd 28882 main/installer-armel/current/images/SHA256SUMS b6629d5e5a8344e0905c72ed18aeaca4 64380 main/installer-armhf/20210731+deb11u7+b1/images/MD5SUMS 3e31a8a4a6eac90bff6befbe1dbfc3cd 92680 main/installer-armhf/20210731+deb11u7+b1/images/SHA256SUMS 3dca9930d681a0ba4186171684027ec6 64240 main/installer-armhf/20210731/images/MD5SUMS 869454c4efa0fcddd91e08ab8ccf9d3b 92476 main/installer-armhf/20210731/images/SHA256SUMS b6629d5e5a8344e0905c72ed18aeaca4 64380 main/installer-armhf/current/images/MD5SUMS 3e31a8a4a6eac90bff6befbe1dbfc3cd 92680 main/installer-armhf/current/images/SHA256SUMS d2556badb036046aff1f8d6eed468533 56840 main/installer-i386/20210731+deb11u7+b1/images/MD5SUMS 87137d3494aed456f81705c70f5a8560 76724 main/installer-i386/20210731+deb11u7+b1/images/SHA256SUMS 8932831dfc7fb479ada48f6936639179 56286 main/installer-i386/20210731/images/MD5SUMS 0ccfb273991e3302a49093743aa9032f 75978 main/installer-i386/20210731/images/SHA256SUMS d2556badb036046aff1f8d6eed468533 56840 main/installer-i386/current/images/MD5SUMS 87137d3494aed456f81705c70f5a8560 76724 main/installer-i386/current/images/SHA256SUMS 998868016e1fdfa2a145942395800280 630 main/installer-mips64el/20210731+deb11u7+b1/images/MD5SUMS 7aa9b76c5e09c5b05445ffa606fe53db 1026 main/installer-mips64el/20210731+deb11u7+b1/images/SHA256SUMS 9533fc15e5b64180b5ad78129a5230b2 627 main/installer-mips64el/20210731/images/MD5SUMS a776640760fbaacfb1681f3abd0fb40b 1023 main/installer-mips64el/20210731/images/SHA256SUMS 998868016e1fdfa2a145942395800280 630 main/installer-mips64el/current/images/MD5SUMS 7aa9b76c5e09c5b05445ffa606fe53db 1026 main/installer-mips64el/current/images/SHA256SUMS fa571598ee1e33c6b2dbee7e30bbf665 630 main/installer-mipsel/20210731+deb11u7+b1/images/MD5SUMS 6755ade8ad0a3238ef992b2b5b055c60 1026 main/installer-mipsel/20210731+deb11u7+b1/images/SHA256SUMS c3a9b6724a2ff5e2abf741f47a7600da 627 main/installer-mipsel/20210731/images/MD5SUMS 01da3e1833ca954309023210e9b16159 1023 main/installer-mipsel/20210731/images/SHA256SUMS fa571598ee1e33c6b2dbee7e30bbf665 630 main/installer-mipsel/current/images/MD5SUMS 6755ade8ad0a3238ef992b2b5b055c60 1026 main/installer-mipsel/current/images/SHA256SUMS a3b2d71556d4030ba67ddd5e2edb63cf 576 main/installer-ppc64el/20210731+deb11u7+b1/images/MD5SUMS fb4c51ffbc1c1c0de08e035cb06a0c63 972 main/installer-ppc64el/20210731+deb11u7+b1/images/SHA256SUMS 37515f49026f1bc4682fefba24e9decf 576 main/installer-ppc64el/20210731/images/MD5SUMS 89c70369e7ab670f721a135f055d81a4 972 main/installer-ppc64el/20210731/images/SHA256SUMS a3b2d71556d4030ba67ddd5e2edb63cf 576 main/installer-ppc64el/current/images/MD5SUMS fb4c51ffbc1c1c0de08e035cb06a0c63 972 main/installer-ppc64el/current/images/SHA256SUMS c89c26c2cc9d407be87915ad5de99f88 374 main/installer-s390x/20210731+deb11u7+b1/images/MD5SUMS 0ac8638a6ff89d2f8e3ceb1c51b39eab 674 main/installer-s390x/20210731+deb11u7+b1/images/SHA256SUMS 580b19117c2b6c6f2a8ad8aca5132826 374 main/installer-s390x/20210731/images/MD5SUMS da16ad53b0185c6e48397e05f2efadfc 674 main/installer-s390x/20210731/images/SHA256SUMS c89c26c2cc9d407be87915ad5de99f88 374 main/installer-s390x/current/images/MD5SUMS 0ac8638a6ff89d2f8e3ceb1c51b39eab 674 main/installer-s390x/current/images/SHA256SUMS 89ad4d3b28d51f39938cf10575544163 117 main/source/Release 4dc0d4fb57d31a820d50565ca5904136 44655922 main/source/Sources 6ca64fd70ce2f771595248c67b1d63ab 11429086 main/source/Sources.gz 632766a36d87c6379182819386228c24 8633788 main/source/Sources.xz 5f624011d3b0a82f23445c2861deac99 17347341 non-free/Contents-all c64dcd5c2b4db85f729afa8623adb65a 888157 non-free/Contents-all.gz d6bec1f2c68aa61c10d5ea048bb61876 1097448 non-free/Contents-amd64 f5a3b5d556d2ac2276e434d47321c42c 79655 non-free/Contents-amd64.gz 2a3fa76ebbc2b8ce1dc696fd4f93d5cf 499970 non-free/Contents-arm64 6fbffff6347fe5e6e7099295803f549c 37376 non-free/Contents-arm64.gz f408ea79e9570389d5ee84acf709fefe 95417 non-free/Contents-armel b7a69ebcb774fa413e4016bb93c3d044 9298 non-free/Contents-armel.gz 6778fabc7cec1e4431b4e6354d7c6331 146124 non-free/Contents-armhf 146fba98ac2f400fe25facd0ca7aa193 13502 non-free/Contents-armhf.gz c2a617bfa92c1ae1471d92c59fe2e012 343198 non-free/Contents-i386 1550b2598d6a74262e40f69cc64ed0e1 29072 non-free/Contents-i386.gz 900df746b6e7accfd8883d31c7d28313 91215 non-free/Contents-mips64el 7c382180d55972ff768bb8a05222a412 8686 non-free/Contents-mips64el.gz 904ab7d197244bdfdbf6b58bc61d09ac 92244 non-free/Contents-mipsel 73868036dab5f62f60ad63ebfb7ca253 9026 non-free/Contents-mipsel.gz 9ff21fb911bfd562eb84f85d9adda009 716110 non-free/Contents-ppc64el 5c487a4250d7e24f4cce14e8e7c430f0 49881 non-free/Contents-ppc64el.gz f3aa91e39f1d170310ec9820ea4dae2d 74537 non-free/Contents-s390x 2b363c4c14b66b56f3009f85c29415dc 7407 non-free/Contents-s390x.gz 28092fe18d286a60369b2baf177a3b66 10803369 non-free/Contents-source a1340038124c66a82eb9afd4e0a5b39e 1063443 non-free/Contents-source.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-all 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-all.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-amd64 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-amd64.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-arm64 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-arm64.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-armel 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-armel.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-armhf 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-armhf.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-i386 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-i386.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-mips64el 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-mips64el.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-mipsel 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-mipsel.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-ppc64el 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-ppc64el.gz d41d8cd98f00b204e9800998ecf8427e 0 non-free/Contents-udeb-s390x 4a4dd3598707603b3f76a2378a4504aa 20 non-free/Contents-udeb-s390x.gz 28683b0c800362ab66657f988f8fe158 189021 non-free/binary-all/Packages 8b503f66350a43348e728ef668a3e66d 50928 non-free/binary-all/Packages.gz 89e1a28553ba1bf59ef7a537d0e13dcd 42996 non-free/binary-all/Packages.xz 7e31516542d9449a20d6d5a5be387724 118 non-free/binary-all/Release 48fd35f0f54926f3b555aca2d9cc267c 545576 non-free/binary-amd64/Packages f4a7af068e39f558fb3c7d38d7227d31 122225 non-free/binary-amd64/Packages.gz 90b0a4d2ddb8c4e4a507459f79006f8a 97772 non-free/binary-amd64/Packages.xz e1a343e13638a8191104cc84d9c87347 120 non-free/binary-amd64/Release d1b662147ba2a93fda8daa87bcc45a4f 381335 non-free/binary-arm64/Packages 0ea4ed22af6d2313b0e15670783ff965 88201 non-free/binary-arm64/Packages.gz 471ad96a8a2139576049b8bc0a7541de 72980 non-free/binary-arm64/Packages.xz 9e926156e80b4e4db84524d2f0079024 120 non-free/binary-arm64/Release 0967ff1cbab012d79d544d2fc19bcb3c 227933 non-free/binary-armel/Packages 66f87c4a0607b4d535045f41bb1debbf 61822 non-free/binary-armel/Packages.gz 943edb5f2d977c5e883e123d7a162a3c 51800 non-free/binary-armel/Packages.xz 096a48f395e2487865b756ea3d0e20ff 120 non-free/binary-armel/Release 11aef19231277b7df07bb88b31da40fb 259156 non-free/binary-armhf/Packages f084eff9f9e23dd4f071fc6caf167026 67317 non-free/binary-armhf/Packages.gz 478795a629bddb465e832a8c15908d23 56272 non-free/binary-armhf/Packages.xz b94819d3bb5bb39f9abcf15388d47bf3 120 non-free/binary-armhf/Release cf0f27353a145dc9a999d6ac8f2b242d 422388 non-free/binary-i386/Packages cac7e560af4f05675b65252d54968a1e 96319 non-free/binary-i386/Packages.gz d528af0816ff9a8b491442be615e0875 79344 non-free/binary-i386/Packages.xz 4a714713c871406dae3fee358bf4525b 119 non-free/binary-i386/Release b241349c71327389608d1ed7805fb917 225506 non-free/binary-mips64el/Packages 79ea1e07e0c12ca9587d966e90a803d3 61024 non-free/binary-mips64el/Packages.gz 800788cecc80de3a8dc8555edc4e1f3c 51124 non-free/binary-mips64el/Packages.xz 9673c21044a83dbab7dd0cc54a4e02c6 123 non-free/binary-mips64el/Release 5637ea382ea6ea47628b489854f51823 226162 non-free/binary-mipsel/Packages cb900ebc58b732e246dad1c05c2da62b 61277 non-free/binary-mipsel/Packages.gz eefd4b08c8da7bb89f71627c9f05a04e 51364 non-free/binary-mipsel/Packages.xz c3acf902cc79cfb97370b0efec244dea 121 non-free/binary-mipsel/Release 4404ce86106e7e32bd47bd465f954e8f 381597 non-free/binary-ppc64el/Packages 9e8c1c8f825dd79ed1d335608297770e 86900 non-free/binary-ppc64el/Packages.gz ffe9119e39ab6813cdd7dd7b5b8299a0 71812 non-free/binary-ppc64el/Packages.xz 79b2651c4e8f6dc350c53e634f30ef2d 122 non-free/binary-ppc64el/Release 205f9ec14fe81d12021eba70ac927040 220570 non-free/binary-s390x/Packages 73a6b1dbd8f6c0ffbc4cb90c8737651b 59856 non-free/binary-s390x/Packages.gz d4f95c7b3fed2787ebb231f6e8fea4ef 50216 non-free/binary-s390x/Packages.xz cf48e148549473e729455b280f93e43c 120 non-free/binary-s390x/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-all/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-all/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-all/Packages.xz 7e31516542d9449a20d6d5a5be387724 118 non-free/debian-installer/binary-all/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-amd64/Packages.xz e1a343e13638a8191104cc84d9c87347 120 non-free/debian-installer/binary-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-arm64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-arm64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-arm64/Packages.xz 9e926156e80b4e4db84524d2f0079024 120 non-free/debian-installer/binary-arm64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-armel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-armel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-armel/Packages.xz 096a48f395e2487865b756ea3d0e20ff 120 non-free/debian-installer/binary-armel/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-armhf/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-armhf/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-armhf/Packages.xz b94819d3bb5bb39f9abcf15388d47bf3 120 non-free/debian-installer/binary-armhf/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-i386/Packages.xz 4a714713c871406dae3fee358bf4525b 119 non-free/debian-installer/binary-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mips64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mips64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mips64el/Packages.xz 9673c21044a83dbab7dd0cc54a4e02c6 123 non-free/debian-installer/binary-mips64el/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mipsel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mipsel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mipsel/Packages.xz c3acf902cc79cfb97370b0efec244dea 121 non-free/debian-installer/binary-mipsel/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-ppc64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-ppc64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-ppc64el/Packages.xz 79b2651c4e8f6dc350c53e634f30ef2d 122 non-free/debian-installer/binary-ppc64el/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-s390x/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-s390x/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-s390x/Packages.xz cf48e148549473e729455b280f93e43c 120 non-free/debian-installer/binary-s390x/Release f7208886e345a2c1c5681b7bc1f891f3 278293 non-free/dep11/Components-amd64.yml ab8bcc71919bb29e6a367d9058dc0125 29634 non-free/dep11/Components-amd64.yml.gz afd21b4c476c6b604c4f998d90383234 17904 non-free/dep11/Components-amd64.yml.xz 71e3cebf69c369e3d4e6b64e48fe037b 271451 non-free/dep11/Components-arm64.yml 4b40bf8ff6579f425fd308cc4f32bb26 27686 non-free/dep11/Components-arm64.yml.gz 04fa2b6c4dc8d23f6ee6334754b725df 16392 non-free/dep11/Components-arm64.yml.xz 678290cc20fe4c69fac625c25f48577f 271451 non-free/dep11/Components-armel.yml b76376c24cdd9bb014e63503830766f8 27606 non-free/dep11/Components-armel.yml.gz b431acc1b0f700a021a3ab1305bc3c33 16448 non-free/dep11/Components-armel.yml.xz 7f659804cad02381ed7735779c211771 271451 non-free/dep11/Components-armhf.yml 0221ab3c0654617c6de5d2b74eac7b15 27691 non-free/dep11/Components-armhf.yml.gz 2df1dfb4d502d5c01f744bac99e8a0bc 16364 non-free/dep11/Components-armhf.yml.xz 1422b7cb028418049315374e46dcbf86 280613 non-free/dep11/Components-i386.yml 7a014ddef58173efeb07ce9d7b866331 31098 non-free/dep11/Components-i386.yml.gz ee2f702d30a2274d969a8e9044da54f2 19156 non-free/dep11/Components-i386.yml.xz 2f39022b38ebd28b86acd148ad0389d2 271451 non-free/dep11/Components-mips64el.yml 5e839450348a20fc9f81cdc9dd0b9663 27765 non-free/dep11/Components-mips64el.yml.gz fbf40f634081acbde994e89d8731d159 16380 non-free/dep11/Components-mips64el.yml.xz 4ff7e301bb5eaab539783f39c24b421f 271451 non-free/dep11/Components-ppc64el.yml d7c37af104343f2eb2b10a0980c96661 27592 non-free/dep11/Components-ppc64el.yml.gz afabe491b91df1be19287ea4e978e7aa 16576 non-free/dep11/Components-ppc64el.yml.xz 05dc5f141a7ca96f1aae6d571dd37361 271451 non-free/dep11/Components-s390x.yml 4a5b9e250991cd5d661db03f4bebefa8 27558 non-free/dep11/Components-s390x.yml.gz b0593a88d870f066f1a83dfb382e09c5 16356 non-free/dep11/Components-s390x.yml.xz 40dd67e0e1f81416405be5c0dc8ee47e 8192 non-free/dep11/icons-128x128.tar b117213e4fd39f9c75c1699ebaf3d610 2394 non-free/dep11/icons-128x128.tar.gz 08a465949d80332d065e6f4ec8459930 4096 non-free/dep11/icons-48x48.tar 49466a3c36fe0d0cbb5940896da60960 741 non-free/dep11/icons-48x48.tar.gz 5d6e61a41610797276e5b6f16d60f7e1 36864 non-free/dep11/icons-64x64.tar 0196f7b979db4111a6d9b988e63101a0 27667 non-free/dep11/icons-64x64.tar.gz c423c38128e8f1d7984682751173441c 572893 non-free/i18n/Translation-en 65a9781186757af5a261165878a7f9b0 92419 non-free/i18n/Translation-en.bz2 d48a4039dfcadee2dbc49be8216a78f3 121 non-free/source/Release 1ebf108ffd532e93efc36f22d900441a 360307 non-free/source/Sources 85f6ca3b8dfaa5af893d96ea4b759971 98323 non-free/source/Sources.gz 10afbe839c1da98bc50d6dc6506652a8 81280 non-free/source/Sources.xz SHA256: 3957f28db16e3f28c7b34ae84f1c929c567de6970f3f1b95dac9b498dd80fe63 738242 contrib/Contents-all 3e9a121d599b56c08bc8f144e4830807c77c29d7114316d6984ba54695d3db7b 57319 contrib/Contents-all.gz e60f82140294e076f97a4148cfd8e594ae808c423d40b62be455bb28af8fb6d8 787321 contrib/Contents-amd64 845f71ed2a0a3ea784c355427362164cb316b01e6ce956a38ea95a001711709b 54668 contrib/Contents-amd64.gz 1ad2b49ab401affafeb146c2badf94f1d699abd27f52b57d5e4b0fe3d37c9682 370915 contrib/Contents-arm64 5f54b4d15ca5a9308eee238da9fa9512dcf8ec15a55cc22fce4efc3142146c01 29596 contrib/Contents-arm64.gz b4985377d670dbc4ab9bf0f7fb15d11b100c442050dee7c1e9203d3f0cfd3f37 359292 contrib/Contents-armel f134666bc09535cbc917f63022ea31613da15ec3c0ce1c664981ace325acdd6a 28039 contrib/Contents-armel.gz b5363d1e3ec276a0cb10bc16685bd02bdc330719d76c275bebd344adaa91583b 367655 contrib/Contents-armhf fc4edd280f2b254dbfa98f495e5f4ca6047ec9a1539ccb8754a1f93546ea32b5 29236 contrib/Contents-armhf.gz 77d465435ba8f5bad03b76624835f91e9ebf3bb09b124ab1a06e70c8b2629b30 407328 contrib/Contents-i386 e4a82b31ac7b5b139fd3bd93ad466de75f7bf7d54410967253044895e41c36fb 33556 contrib/Contents-i386.gz c0efa60eaa3b47bd93ca71220c6fc734d54b257e16bb6dd8dde43ca722f242dc 359402 contrib/Contents-mips64el 4fccf5298ef664c2de3dc7eeb203eefa3bf8ec82b95b1c696b856a43af35e395 27962 contrib/Contents-mips64el.gz db2388b4b8d300fdc265fe064288a8de5f69958b06ed6cfeff3b8528e719015b 360549 contrib/Contents-mipsel 27db69688406433748363f4a70cac108f29b99555a6d5dc3eaba6b2e8b526dfc 27942 contrib/Contents-mipsel.gz e62412c1f585461c8ae27d4d2a79b82c27dba109ac19df81a15ae7f53369cf65 370025 contrib/Contents-ppc64el 8ac6ff54ba23486d9c139ee79a6296760dc20022209ffc321296967717a37fd2 29381 contrib/Contents-ppc64el.gz bb1fdc3fafd28760f57d951e96a150e8ec7d6b0fb75443de93f08a61ffbd7042 357860 contrib/Contents-s390x 009373ff8cde80de63a4303b8c6eab79af34d6c2c0c831d1b38e1f9329c396cc 27518 contrib/Contents-s390x.gz 7d79e95f92007f2885bba7ff9d40a81cefea96959cb090dc7cde26a77e7f1ea5 6722669 contrib/Contents-source d6655657ff285c9372e18b0ebff346e922694de31669d6c0260e789306841e9d 469817 contrib/Contents-source.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-all f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-all.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-amd64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-amd64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-arm64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-arm64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-armel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-armel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-armhf f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-armhf.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-i386 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-i386.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-mips64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-mips64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-mipsel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-mipsel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-ppc64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-ppc64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/Contents-udeb-s390x f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/Contents-udeb-s390x.gz 70d58353b3bc6083f3946ebcdc1f150204988bed60df8c0389fa23b26924adcd 103239 contrib/binary-all/Packages 9baa8f0dbe243eea5e03bc9551b0e5774ea0ba690db28ae63d1f81cd6e16aef7 27385 contrib/binary-all/Packages.gz 24cb5963261a9cb0a4671061d65ee51e211e00ea754e4f5ec6426a1a78745ec1 23916 contrib/binary-all/Packages.xz 93a2ce91dbee932c8b48caae660d67b864819f239de1cf9c85cbfeb3c450e396 117 contrib/binary-all/Release 25bba54443595d2760419c8873b026880ad3553697b4254f0473b7c859c3526f 231878 contrib/binary-amd64/Packages 05b545380de2e24307c4b33497327a397b5fac53c53c2479d487280c69c55b7b 60884 contrib/binary-amd64/Packages.gz 572aa5c4767342e411f9ec261ebb871a48da20400d37e9f960c0f3960a26fc66 50588 contrib/binary-amd64/Packages.xz 4c337ceffea66616199c9d6f6f0996dac105940b4e220425a12c9ecba87a1ff6 119 contrib/binary-amd64/Release 7ab66ca6c3c1f575100f8e39fee460115ba8292a489c07e9ea1b0a914e47f67c 180884 contrib/binary-arm64/Packages 4da911f1c6926b85d6a9a025d73be907124db4a3e99872b0128ad2187a5af5ef 48958 contrib/binary-arm64/Packages.gz 07b68a663f305c1a676642f078a3d9243072e2f2402ad87c405f0a4c7744cab1 40964 contrib/binary-arm64/Packages.xz 1b6ff9a1c182ed456e4aeff56a54eddfb128ce6c39877b70769dd79e012143f6 119 contrib/binary-arm64/Release d353d3f7b451cb07472d111221866fd89c6e7b28ad0fe66044f35e2eca6189fc 163042 contrib/binary-armel/Packages 5333591cd2ee7e750d864f875799c83b4985f0473a02e525365db3fc5b27ab36 44389 contrib/binary-armel/Packages.gz 6493591c5f010aa3b50e7052c4746f6afe40a0fd31ffcce08c706aec6e7b672d 37452 contrib/binary-armel/Packages.xz 04ff4b12d802b8291b4408a1435e0e11424b96e1628d10981b18d7bfbe481708 119 contrib/binary-armel/Release 75d98358dbea38501853ae9cd7a2da4f84d02eb4543bd9e96f0c3e6cd5945533 175566 contrib/binary-armhf/Packages fde856e3b07624cb5e3d6c11dd450aae8e56f38646c4b3f3b7cbe0423f78970e 47805 contrib/binary-armhf/Packages.gz c572038b5ced50f74da2baa5cda8150846cface0b285218336f6af4e1365b9b0 40220 contrib/binary-armhf/Packages.xz d37bedd8d7cdad30b0f6699f0b0c12d60cf2a9a24866e5a256a957d625b62b8b 119 contrib/binary-armhf/Release 6b9d6d64b15686f83bf58c5e2255bdef26a5f2cdd97c76b047ea46f533aeb0bc 203514 contrib/binary-i386/Packages 010b321fd585b2d1c45512db80e60aefdd0fc7bbc60a53e1594ba9ad5f9ba45a 54100 contrib/binary-i386/Packages.gz a17c01bbbba0f218b3a38cb5b7fc3053a7cfb6364453b46b6b80687d11eab142 45340 contrib/binary-i386/Packages.xz 4ce72f7efaa89af0624897fe2cd8495e137d4e5e0f5320cb44de27fbc3b02986 118 contrib/binary-i386/Release 4c71f56a967f6f390c1e6d381f399d74da5a545c8906f014fe805859ba9ae55c 163507 contrib/binary-mips64el/Packages 49f3fc82266f184e331b2b0ea0762540b8ef68486f299a5673b247f8c03d3858 44652 contrib/binary-mips64el/Packages.gz e0c365ed89f4538b36ab3366293d3b9f4e8472b9537d91b770f650650021f4e1 37496 contrib/binary-mips64el/Packages.xz 59e8e1e1ec5e0d469be59b6d3321aba3f9ddd686e440bde74616b2acce355b41 122 contrib/binary-mips64el/Release a951b730b4a059ef33073627d50a40f204591c3a5348fbe1c5e3b21782a77e5a 164647 contrib/binary-mipsel/Packages 662a2fb412beb7130ef5ba0440ec368825d21713392a55ea33048673bbcca3a0 44883 contrib/binary-mipsel/Packages.gz 7a01af1780b68648eec3923fbe4fe766e210e83f0ba8b03f6bc8b9a8d4c0169f 37816 contrib/binary-mipsel/Packages.xz 9df253300a3c33585a18f1c8b91018a558e04a222a70ce8072f76ea2e2b27ad1 120 contrib/binary-mipsel/Release 8ff5ce44abf0d9fba97b3ce63b2d41db58d24b463dfe23cf06069a71724f7047 180387 contrib/binary-ppc64el/Packages ddf5d43553c9af8a6dfa0ff6f51236dee72fe15d2a09ecc9212bfeee5e667e92 48843 contrib/binary-ppc64el/Packages.gz 84cd02fcb4a610501538fd06ebf77a67ef7badcbc6f5b1f338c6d013329ea38e 40808 contrib/binary-ppc64el/Packages.xz 57f78f401d86eaadc5fe6ca190f162e4a0fc1e77021a6118f27aab68db0d7f82 121 contrib/binary-ppc64el/Release cfc032377fc264eff4a6319ecfd2722e95de7364a63b29eed53cc78603a8a8aa 162250 contrib/binary-s390x/Packages 72be2806452fee7d70ef80ffac98e3f408e7389dbbbaaa6d9228f48a6733b773 44334 contrib/binary-s390x/Packages.gz 9a14a52c690b24eb92939192abc4d4e8b23a2347a838232774016ac79c3d8ec8 37244 contrib/binary-s390x/Packages.xz cb54af7d630a4046eb41cc3096838019e16b72f3c0f505136788bcf09fa632c5 119 contrib/binary-s390x/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-all/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-all/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-all/Packages.xz 93a2ce91dbee932c8b48caae660d67b864819f239de1cf9c85cbfeb3c450e396 117 contrib/debian-installer/binary-all/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-amd64/Packages.xz 4c337ceffea66616199c9d6f6f0996dac105940b4e220425a12c9ecba87a1ff6 119 contrib/debian-installer/binary-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-arm64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-arm64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-arm64/Packages.xz 1b6ff9a1c182ed456e4aeff56a54eddfb128ce6c39877b70769dd79e012143f6 119 contrib/debian-installer/binary-arm64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-armel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-armel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-armel/Packages.xz 04ff4b12d802b8291b4408a1435e0e11424b96e1628d10981b18d7bfbe481708 119 contrib/debian-installer/binary-armel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-armhf/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-armhf/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-armhf/Packages.xz d37bedd8d7cdad30b0f6699f0b0c12d60cf2a9a24866e5a256a957d625b62b8b 119 contrib/debian-installer/binary-armhf/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-i386/Packages.xz 4ce72f7efaa89af0624897fe2cd8495e137d4e5e0f5320cb44de27fbc3b02986 118 contrib/debian-installer/binary-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mips64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mips64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mips64el/Packages.xz 59e8e1e1ec5e0d469be59b6d3321aba3f9ddd686e440bde74616b2acce355b41 122 contrib/debian-installer/binary-mips64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mipsel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mipsel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mipsel/Packages.xz 9df253300a3c33585a18f1c8b91018a558e04a222a70ce8072f76ea2e2b27ad1 120 contrib/debian-installer/binary-mipsel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-ppc64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-ppc64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-ppc64el/Packages.xz 57f78f401d86eaadc5fe6ca190f162e4a0fc1e77021a6118f27aab68db0d7f82 121 contrib/debian-installer/binary-ppc64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-s390x/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-s390x/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-s390x/Packages.xz cb54af7d630a4046eb41cc3096838019e16b72f3c0f505136788bcf09fa632c5 119 contrib/debian-installer/binary-s390x/Release f0a51e6d75f883bdecf739b214104a17dba111de8b42022f6b8b053870c83851 119152 contrib/dep11/Components-amd64.yml e14a1bb3690a18ec7c5b7997fabf4d8d4fa633efdf84a25e071a1f62a2c064b2 15579 contrib/dep11/Components-amd64.yml.gz 58921318632f77413bee8d9e980689f8f139eb1169b5ce201da06e6f280d485f 13564 contrib/dep11/Components-amd64.yml.xz 26538634f90cd6f04a6be602151fa6a098075c3013b66a81439a7bbdbfaa40f5 113437 contrib/dep11/Components-arm64.yml 840908ab753dba952e073216007f93d351577792911dcc09a15a16abfc32c8a7 14251 contrib/dep11/Components-arm64.yml.gz 3afec5908036aa2d47b9a9a33c13eca12bba1aaf8d8bbb06ffb1627e93f6526f 12480 contrib/dep11/Components-arm64.yml.xz fb35649f6c32b71b9d85388c2c238011161c250df5c62e2c4d3446e369dced4c 113437 contrib/dep11/Components-armel.yml c305f1c0826e0414bbf36524d8b0fc2723ffc0fb222275e1e1728914fc334c75 14029 contrib/dep11/Components-armel.yml.gz fe15a53774801f8d9cb04aa8324cbdb9d741ec75ae0999e033873458bd6160b0 12524 contrib/dep11/Components-armel.yml.xz 0ed24b6d7ff891c82697497dddfbbbb6818c168c55b41ae710e9cc9240d0d9b2 113437 contrib/dep11/Components-armhf.yml f5260cdac915ff5eba0a48757c93f8f8b6421a673e641285f43d83f62be3eb8c 14127 contrib/dep11/Components-armhf.yml.gz db97becd2ab6a05bcef05d824b89080a1e7c03a69735df3bf5945f6989a9e504 12480 contrib/dep11/Components-armhf.yml.xz 9adf35216113140c31c2e9c169a3eaa465044f41f8803afaac955c467a1e5a49 118972 contrib/dep11/Components-i386.yml c1d4ea9c0ac26f2b62d45c8c595ec9a5bc1c737b50634d7f86a4bfac17c9b180 15566 contrib/dep11/Components-i386.yml.gz 51ff60d5f02b46e08acea4054484f5c66d721c19beff4857cb2570f43e881a69 13560 contrib/dep11/Components-i386.yml.xz 50b6970af7de299a90ac651cceb6cc011e8d165ea0701f7b1c9daf6c1be485f0 113437 contrib/dep11/Components-mips64el.yml 78aad16ddec6b18d30ce4e20f52008f72efc78ba55688fa462741f4bb514043f 14056 contrib/dep11/Components-mips64el.yml.gz efb0fb003bbd3997128bef56f12104872604fad320b38fd99bca25e68210d98e 12500 contrib/dep11/Components-mips64el.yml.xz 05c2268c20e748baf8da20f7169918e2f6dcffb6e4f6dfc22829607cec7ea564 113437 contrib/dep11/Components-ppc64el.yml 19f600014e245e7d07762b7f07d8de6884b1208a280a19274e56b4174931082a 14219 contrib/dep11/Components-ppc64el.yml.gz dc8b525d7043ba3a85154ad39d0c809e7215c5b2f3865efbd94ff3daabe54810 12496 contrib/dep11/Components-ppc64el.yml.xz 5d43b650d261ac23815d98e9a4f644d56f4113e63f8a42b1558ff1c82e925d2f 113437 contrib/dep11/Components-s390x.yml c1811e0538dad96441a4172e661b9ef7fca9c05d86c4b157a66046bf49aa70e1 14050 contrib/dep11/Components-s390x.yml.gz 42356b4c04801189947748d6fce6e28e356a114869a7895e4921a3b4901e678c 12488 contrib/dep11/Components-s390x.yml.xz 641e9a50f98d7e4921102164e7737b095c9faead09f6de4459086b598b3bf0d0 271360 contrib/dep11/icons-128x128.tar 34b531c5292651ac5a18d0477bb8cf1420f3d969ad73d45fd596641d768b853d 195507 contrib/dep11/icons-128x128.tar.gz fa3a19603046c258e647b0c1fcdc6110f0b5c1f2801ee950eb1261e8c02e03d6 83968 contrib/dep11/icons-48x48.tar 28a6f153e56e9b567cc7fc03d6faa6dfb8480ee3f36e0c8d9646e4de3898480b 47168 contrib/dep11/icons-48x48.tar.gz d882fc33534a8677ed8d3ecf81f7a076fa57e8e8135bf586f8af20371edb195b 138752 contrib/dep11/icons-64x64.tar 45c8eda64d05f1feee0040809128760f9489665d66bed0502cb179fe0ec79f6e 93294 contrib/dep11/icons-64x64.tar.gz 094badc305c90db005324c484a55d88f14dfc805aa429856a5863a96518a88e8 192685 contrib/i18n/Translation-en ce7d3d607194cdfabf421c313030e88876ee899d5cd01f5b023cfdc0c0ed0f40 46929 contrib/i18n/Translation-en.bz2 b89a3b9258ada994f8857f734110206864802d179201da6fa97a666db306ada9 120 contrib/source/Release e331ac856d30949d3d70b299678f1f23462785681c70a62205ae35903d2c50d0 178776 contrib/source/Sources b34bb0d3527f1086ae23a6d2ae47bf790572a7d07ff0ad444f0f2c68afd3c504 51355 contrib/source/Sources.gz 99262e6c7f527f6654eb8e8b3415ee29fa5f2669d9bc22ce95881422b4b9b603 43208 contrib/source/Sources.xz 2400074e2a3897ad55b2e0e110b3ad66af9446b0cb77e28c7d5c92abf0a60db1 477769406 main/Contents-all a61ae2ae233b5eb73a624cc09c8df2eb3beab0ff44fd7cc75d2e64eaf36d2204 31069218 main/Contents-all.gz 226a3117b453b3350ee326fa65963b4936e6f5f0f0baabfc71ebe9458b3a5735 129058022 main/Contents-amd64 ee49ff0f5accae61de15bab5f6afd31d6b0b4676d59c9930fbe6dc24ed54954c 10270460 main/Contents-amd64.gz 13b617dbf9aee8e874fe709647f47bd2ee3780f4cf7c717f33aa7e1cd58d5e3c 122426895 main/Contents-arm64 68d31c4707f80bb72cd02c1276b53e22b5c0175a7f46bf75da6eecb754f8aff3 9831920 main/Contents-arm64.gz 5586eebc2846a2c4537cdb9020b216dd67b8c0eddc5a3bb8a9a0a6155e5946d5 104683113 main/Contents-armel 780507976f07c70aa2e787b9a6f9cab2ed8b1aed99b726906677d8e4ce1c8436 8703570 main/Contents-armel.gz 6f02632c558a77c4d6a78d64b437bc1c25857a4d04250abb51c5f13b3e86c119 113716591 main/Contents-armhf 22f19d2f3ae739ba4f7b0d0bf2effab552e64aa65c8a236b16c069e9fb8e5e90 9305906 main/Contents-armhf.gz 1c9cecfb8e79dfebf5d5cf0dc17271c2419fa72a4ef6e3b4b9e5ef1e3acad18c 129088857 main/Contents-i386 b826bd0b623bdce4568f0f1f8205c8f6f4e50b8ecfcd99a3b26bbddaf3900f8e 10208982 main/Contents-i386.gz 2a03448109546da0c72c31d0a534637306106e2195bd10b58aa2237ea60095f9 111097071 main/Contents-mips64el 147af2223dc310a089b0d18c820421f926d33e24ce2d0dbc6b20203c35cfffb7 9042221 main/Contents-mips64el.gz 6ef7f5d32e074dfe0231fbb8ac14f3cc67b511f924ec502736afe36cd549774a 112593872 main/Contents-mipsel a28b893a37dd761f6c95c0f6c722b9ac5324869d91bfc97cd7a1270159ac939e 9178325 main/Contents-mipsel.gz 720f513250bebd466149094ff4ca8f8e1b412810a218f1cddfaa31163577f44f 116027632 main/Contents-ppc64el a852312c04f59070951821eda6893270b28d23e12977f77a0933cce2882547e5 9355024 main/Contents-ppc64el.gz c92fc53215a097d7be1cc62c20946a4744221ba8dd58f62a81258fa79021aa06 103638209 main/Contents-s390x e1ed13910c59f0df90724c116450ac3aa2936a2d89497bbeb263993b9e767102 8711885 main/Contents-s390x.gz 19cb2eeeb6bb6459bf824cfbe9a82c44298fbd2ccb614ad130583fb5b07f3be3 690410830 main/Contents-source 2d5b1d50f3f42a073f6b27127bdbc0e19870188aecab8417dc32dde30138fbe1 73501881 main/Contents-source.gz b709d41e19af82147c367d90a74eae144ab18744d78817b6395fc1344fb99c76 157382 main/Contents-udeb-all f9801d96354f0b11d5357633cb9068dff1f39b9210eaeb70455db63ee0ecbdbc 13516 main/Contents-udeb-all.gz 88d816aa94f2071b483a84751d8109af7e89e049d9a5d690e2fc75a1fd86a9dd 477050 main/Contents-udeb-amd64 1344217ca4f19362a2bcbeb119e0a6d36e853481086431794142a930b46b13b8 36011 main/Contents-udeb-amd64.gz 5860a70ba4852152099c974ee16e92c0a935f6f96257204313ca99e8169826fe 508817 main/Contents-udeb-arm64 71a73fbf6e739034fd57e1a8255565d260b91cbce409128dcc69fa059623dcd2 38139 main/Contents-udeb-arm64.gz b4326a16088882aa0a038240624002e1994e232d98f4194b65907be2f94270b3 323083 main/Contents-udeb-armel 53c51078092e821f51bfa9477f35bd2a2148f045b5f6ae06a42b4ac79d440c42 25477 main/Contents-udeb-armel.gz e85592b3fbaaa08298eb08c7ee40c80c3826b961f3fcee0de1b6cedc0bf283aa 579793 main/Contents-udeb-armhf a9694e389e0c7eb23c9bad861b0f07db9114a4f4abf4648081b7640783c1e52c 43153 main/Contents-udeb-armhf.gz 286e7790529e1012095eeedadef806ab30696dbf3ca55ecb55cd91247d239287 751383 main/Contents-udeb-i386 bbe85229c4d8e20b737bf432e365a3efd51fcf557df061db147e9f63a322b69f 53984 main/Contents-udeb-i386.gz fcc311dbf697321971d9608ffc05555edbce48bd126b6d1d2b7bcd9a8eab0a25 760534 main/Contents-udeb-mips64el 15bcf854ec4356278e912856e3904938ea994ae9742818854912126ee15f9cfc 52873 main/Contents-udeb-mips64el.gz 572ddd8f7183d851c2fcfcda55166cd4ddb95b6eba0b73c07572dff8e74f797a 760210 main/Contents-udeb-mipsel d51989963ffcccba95d5591fe78e9aa6ecefd480f7464a199288d7153ea1a637 52810 main/Contents-udeb-mipsel.gz c6e87c5351596a66921e0559dcfdfae17c52cb422c709f2e44b19cf6064e80c9 401639 main/Contents-udeb-ppc64el 3a94166a9523c86e71d08304a2bd46dd72392738f22b608a4b2b45fb77491f58 29533 main/Contents-udeb-ppc64el.gz 42b53406c44e9439e86506343040298b5e1405e6791594953bb058ca6effe8f0 258318 main/Contents-udeb-s390x ce12cd039c002aeef6d9b364d73e313712d4d39970241953919fa6e8db0ce628 20894 main/Contents-udeb-s390x.gz b42ce26db7c150a2dbac237732eb0e5dd5ef28e2ca51a5482cd9293dc64d8357 20423830 main/binary-all/Packages 33eec3157da3c566e1f078bff8b46bd6074dcf3c9f242c760b8fcb2233bc5d32 5208282 main/binary-all/Packages.gz 09728ec87e7b549eaa43b80fbb9432e36043b9874cb4b3f95428a1eb2a96582f 3918264 main/binary-all/Packages.xz 5fca0b091a4008553328742c4e5509375042ae86fd25e078e5641da80c6e35ed 114 main/binary-all/Release 35eb7de95c102ffbea4818ea91e470962ddafc97ae539384d7f95d2836d7aa2e 45534962 main/binary-amd64/Packages a445d7472b76164584ebd9aebed31517837dac1f792164bba926278dcb166255 11096605 main/binary-amd64/Packages.gz 9b3d1e096767eae5ade343b1b123e1787cc49cc78b139db247fbe96f8f3f545d 8182920 main/binary-amd64/Packages.xz ab78444b1bbaa56630b4f90edc8982f4fd965ac4db2b5530855b768c1c8fa9f9 116 main/binary-amd64/Release d908fe964d366107388f445a2afa408224ccf6a665ef087f26afd1cfd2b9ad04 44816551 main/binary-arm64/Packages 1afdf5fece156bfb26fcb25409a00defecc507b38ae69097a09b18ff6b1d2b50 10941625 main/binary-arm64/Packages.gz d2b7315d4fda95e5a5f2ce7ca6e2e44d9bf1b1d9e9d980ce416d35a4d00f1a2f 8071508 main/binary-arm64/Packages.xz fc1fcedbe9926a4b0b8eb49c4ad003eeb5d656f7a447864ebab16f026100f6f7 116 main/binary-arm64/Release 6b115f03bd7e988bade97cb51a9ada488bad7623ad3f085da265df9e4e64cfec 43343990 main/binary-armel/Packages c2564b86e9dd83293f0a43f4fb18506ab8487878bf518115dc42b4e2125ca5d2 10677432 main/binary-armel/Packages.gz a81082ad524af5c8ff7fe7674bf715daa82de2ce1bfc39dde407dfb0d6bb6ad8 7871888 main/binary-armel/Packages.xz abb6c54c329433e32610e26704ca667256c1ad24cbdef67431ded86b67b9df8d 116 main/binary-armel/Release e14f5af333a1e465450a88a9a40806b8d4b0e2dd903e9b9c698f4004eac6f0b0 43846413 main/binary-armhf/Packages 7cb2281126c6161b691eaa41e647209b5240c660a99e2b083119e6c701a0a5d3 10775534 main/binary-armhf/Packages.gz ba960fa5d4178671db25ac4be29a375496edb695aac902f99c04aa482a60a379 7944712 main/binary-armhf/Packages.xz 07c1cebfbbc800619727cfabb5bbd313a65ff1ad3df60fe04b680de8c63846cf 116 main/binary-armhf/Release 164486fd11378f87865c09143df1514fca7045166c9c1ba61f2c50cffb987ea6 45094980 main/binary-i386/Packages 216af7eb177d93f2004318058ff3f833dd6cb66bc23a3ad17b0c27edbbacc923 11013153 main/binary-i386/Packages.gz cfd786ed196f7a512764069e09f20ef97c536552f777ecd303b4a1538de5fe9c 8121972 main/binary-i386/Packages.xz 598ab0b654f7296c5dd22bf8ebc2f1452e7585bb4fee5b0318d08a7700d59f39 115 main/binary-i386/Release 2f4b83b3beff8e697aa7aba63b87a3841eda7e121dca7efeeba2fdd6c46d4708 43733274 main/binary-mips64el/Packages 5d3435e4b966e83eff68bdc0f1390639ee4cf8ca85a0912086118d18fca56895 10720185 main/binary-mips64el/Packages.gz 2f5114b8774c2ebb9e4bde58f4f61228413faf25c6f0f8cfdfef166d59194d1c 7907404 main/binary-mips64el/Packages.xz f3e83d91633067c9cc7c22a7b17331307039cb7a194534c86c45a0ae8b15e159 119 main/binary-mips64el/Release 94dfcf07165f1f9da1d465a87d0978f2cd267341b0cb100a976db872731b0861 43667386 main/binary-mipsel/Packages dc8003ba9043dc725eb21a2d51f70fd0f68a98398e0819083663de884cc73721 10726366 main/binary-mipsel/Packages.gz 886bc8567cdd318d3380636c313f736e35220acc8be711584ea919d5265e96a8 7906936 main/binary-mipsel/Packages.xz 56e88cdccc438d85773e9d9dcd4626dc93905cc85c28492cf1115e0f6d6d86c4 117 main/binary-mipsel/Release 53f4716144d0126ec83ade49820c2737e4097d058c7ec55c26a94401aff90799 44671240 main/binary-ppc64el/Packages 0d7e6d81bc985f84d71bfa9dc1568b5bacde58766499fb50c9f9615627eb64d9 10884852 main/binary-ppc64el/Packages.gz 8bd383fa40a08bde86f78b7768a3c8eb8aff0a16f380fe3ba259258db8cd89dd 8031816 main/binary-ppc64el/Packages.xz 32c55acd12e6699b68c50747b5d72a0d2252a1db5856ab75fea6771c8311ba21 118 main/binary-ppc64el/Release 1e53bd7f1a45174fdb3db7ecebeaabfbfecfa0a88aaea4a9d060039c99b0580f 43340190 main/binary-s390x/Packages 07462d6e7a7e6ef042830e993747f9d471ae8dc0ba792c3056811c64d37c0e6d 10686656 main/binary-s390x/Packages.gz be641a245bcbd2b2138762c88793df74b04bad687f2c8185137254e9cb6bb229 7877060 main/binary-s390x/Packages.xz 612cf5c4ef5247bb112bcb8af86780ecfc13514729575fce1087ec12340965d7 116 main/binary-s390x/Release 4f60d86324cc91f8ac32625dfd1f8750a7f79e866376a34a478d2d3f8033ce84 61160 main/debian-installer/binary-all/Packages 1e0c3c1d9f21267ec4183fa21ffb26808808678d6393cde03820b5f8c677977c 16449 main/debian-installer/binary-all/Packages.gz 3831da178354890a18394e5d531c28c77f70c6fcc628e369eb584fbf7ce28812 14676 main/debian-installer/binary-all/Packages.xz 5fca0b091a4008553328742c4e5509375042ae86fd25e078e5641da80c6e35ed 114 main/debian-installer/binary-all/Release 8e6eade3d4d6600d25629ef41a6e7d7f1735cb999923c20962ab96c4c60cab8b 274352 main/debian-installer/binary-amd64/Packages 127cbf365fb6430a108efe73be70b65c93a156c3e9d54a26515fb0637fecf7a0 67349 main/debian-installer/binary-amd64/Packages.gz b15c72bd10652b7c5a456b8dbce9ee1002d9ee36b4c8377d5224bf71d7c343e5 56064 main/debian-installer/binary-amd64/Packages.xz ab78444b1bbaa56630b4f90edc8982f4fd965ac4db2b5530855b768c1c8fa9f9 116 main/debian-installer/binary-amd64/Release 42d0cbedcd391dcd0ae974c2feb668676aa33b430b213d23a913e411c817f23f 257349 main/debian-installer/binary-arm64/Packages 1e7d6c63aeeb7b5923f514df4586dd7c9a23415f318e4d99c03c435fed764ded 64271 main/debian-installer/binary-arm64/Packages.gz 155a73d0f9cb8c70eb64cf86204fb88a81585d79136dec3399b54571307daf5d 53980 main/debian-installer/binary-arm64/Packages.xz fc1fcedbe9926a4b0b8eb49c4ad003eeb5d656f7a447864ebab16f026100f6f7 116 main/debian-installer/binary-arm64/Release 01175829fcfa8f2d6599c49971251106ace55e9b660a6ab2b6cb84990b615f23 248363 main/debian-installer/binary-armel/Packages 41e38adbe03f5e12ce7bb71a17a1afa385a19129f3e2c4fe064358e83c41f50f 63792 main/debian-installer/binary-armel/Packages.gz a669674d70b74c4f3928ee0824025cd032a2cd681bee9608194da11bd96140ee 53168 main/debian-installer/binary-armel/Packages.xz abb6c54c329433e32610e26704ca667256c1ad24cbdef67431ded86b67b9df8d 116 main/debian-installer/binary-armel/Release 7805822347f4d4a5c174408573f6d212e6f639a8d2587c1358dd1273c1e4bfd1 251788 main/debian-installer/binary-armhf/Packages e39dc55b91aecd52890df43e9661536022c68301e6d2d46140f0d883ea0d4097 64864 main/debian-installer/binary-armhf/Packages.gz 508561858e1d7d9533704014303d875ddecb6c8a9be3a5692e4db28b8673bd0f 53852 main/debian-installer/binary-armhf/Packages.xz 07c1cebfbbc800619727cfabb5bbd313a65ff1ad3df60fe04b680de8c63846cf 116 main/debian-installer/binary-armhf/Release 545fe891b7ccfa9058a34a9ca644eec47d4d1e32b8d19731577719914d57b1cf 349445 main/debian-installer/binary-i386/Packages b3dcfa8a62aa51c55cb0cd999fe2930828eec945d947c737a4e0251299d031a5 77230 main/debian-installer/binary-i386/Packages.gz bb6f1ba125b73e6031b0db1aff6666d674614b2900f829edc00f5422b71a9ba6 64124 main/debian-installer/binary-i386/Packages.xz 598ab0b654f7296c5dd22bf8ebc2f1452e7585bb4fee5b0318d08a7700d59f39 115 main/debian-installer/binary-i386/Release e99d10f54387b1515192c78420b8320f19226950e45628b464419a16cbbe0851 364716 main/debian-installer/binary-mips64el/Packages c16ea980c78ef318d090f661bb8a32b013b9aba1e4e03cfc7a1fcdc710b315bb 79498 main/debian-installer/binary-mips64el/Packages.gz 0fe50a043e08a0c0f92cb774acbaefc95f78d7123efa606770dd02f9fdeff404 66396 main/debian-installer/binary-mips64el/Packages.xz f3e83d91633067c9cc7c22a7b17331307039cb7a194534c86c45a0ae8b15e159 119 main/debian-installer/binary-mips64el/Release e9b79bdf2204d27512128a1f1d85e8455d94c402be68b815c24f66be4f496e8b 364202 main/debian-installer/binary-mipsel/Packages 94265e6e880e2c55618fcde79440b3060922932eb14eac1beaa3c7b1c6865d17 79784 main/debian-installer/binary-mipsel/Packages.gz 803db2a15312c03059f31f2a20cde06935f7a3ca6c3f35e043b3d1881eaed353 66500 main/debian-installer/binary-mipsel/Packages.xz 56e88cdccc438d85773e9d9dcd4626dc93905cc85c28492cf1115e0f6d6d86c4 117 main/debian-installer/binary-mipsel/Release d779769699bad795292351e1d2bf4c294d0df53f43a8e812e607d2ef5d979fc6 256933 main/debian-installer/binary-ppc64el/Packages 6d2b2b5ac8b21d5dcec79146959b1bc617b65c5fb69a72bde8fe9b494bf03e30 64920 main/debian-installer/binary-ppc64el/Packages.gz adf0f93f39ffbdf3efc60e423653d16ca020f9d40d76c51b153462d4c556fac0 53960 main/debian-installer/binary-ppc64el/Packages.xz 32c55acd12e6699b68c50747b5d72a0d2252a1db5856ab75fea6771c8311ba21 118 main/debian-installer/binary-ppc64el/Release 08fac5f6592875d7466899b2bab7a44d8eea409b2b05dd8a334f0bd4e7bac807 226275 main/debian-installer/binary-s390x/Packages dad6130f7794acf153f2654ef56ce0f51ad202a6652862332025ef08d299b092 60464 main/debian-installer/binary-s390x/Packages.gz 255a06d1829ff337a371c2e3565ad96ea789703016ce91735b36a9dd6fab1647 50116 main/debian-installer/binary-s390x/Packages.xz 612cf5c4ef5247bb112bcb8af86780ecfc13514729575fce1087ec12340965d7 116 main/debian-installer/binary-s390x/Release 99d8d572b0219a7b37addc91ff4e4ff238a33b3452580d4bd2469588a2225cad 18520413 main/dep11/Components-amd64.yml 9c5522d811abead85a73407f6b56b171207105bb3641e22d76f2146482d4750b 6213469 main/dep11/Components-amd64.yml.gz 0b517038e27fe4864c35de9459537d91f5d274800a172be69f91e90bb3631589 4048504 main/dep11/Components-amd64.yml.xz ed767617ad156481cc8948fb72c2d699d6292bfd2d83fb2f24b2b155612dc539 18436837 main/dep11/Components-arm64.yml 1732a30dff783f891da2245f955becf3a43be40f0400b722087ba626316e980a 6191092 main/dep11/Components-arm64.yml.gz a02d6259b836d37804838b6de8f40568332a9a78cb4bc7668b32208f6062e782 4033216 main/dep11/Components-arm64.yml.xz aa3eea13a49b29dba27956d6fb6093817775361e29fef3f751e8e70b7065e54d 17658848 main/dep11/Components-armel.yml ca3d41da75c25408834b265c9c95f700a1241189f6bf62270e14b85920f5cdc2 5952269 main/dep11/Components-armel.yml.gz 5c90b5a79fb5cf11b4e822396183bd3b4d3712e5f8e9363c5fce4a3a6c42a58b 3879744 main/dep11/Components-armel.yml.xz 9d95db48c33d5671c96a2931458a92b6290e9c3f880c7ec7d7aef2b23a681eb3 18205252 main/dep11/Components-armhf.yml 55c47f2e4607828ad1d875c1ade2aea6565916e9dce3e043f6de2e85b6cd74c4 6110587 main/dep11/Components-armhf.yml.gz 20797715d417813ddd77d1bf746b8ea9f6353ad0e8be2e67f1700813d992268d 3983180 main/dep11/Components-armhf.yml.xz 5579083d9a290f05eeb86967fd664c46464b3bafc00c073887560523a1793a64 18485654 main/dep11/Components-i386.yml ac8dd6c8b9e575785646a7d41adc7783956e22bcc757a60c80f225328c769f08 6201776 main/dep11/Components-i386.yml.gz 589f93188296c83e394c89ccdaae1565436dc203161958e96f3a5cf2797684ca 4041608 main/dep11/Components-i386.yml.xz 2b028df6a795c2a4b058b0f239745da363ea0f8b9fb8ce1a7955bedf579cc8cc 17819116 main/dep11/Components-mips64el.yml 0865e497ec87d5d45f84106166bb035610443e87528aacc1a43f13000542a3f5 5977494 main/dep11/Components-mips64el.yml.gz 46745049532f14f438f41704b442c157ee0f2990baed5d06da8fda3b41501547 3896708 main/dep11/Components-mips64el.yml.xz c0e1c64172edc19edcc287b0e617adff28b31354028de4c755cdf1fd077de913 17947079 main/dep11/Components-ppc64el.yml ba4eb9c1ab3f03a7fd184e5fc47dce250c083a617d9e2ba49a70c920fd957b29 6023058 main/dep11/Components-ppc64el.yml.gz aa34918432eeb8a82d912d86f69d82e84a4bc0eb48056ebe321b83d2757d1052 3925796 main/dep11/Components-ppc64el.yml.xz dc222c504c71bbc9ff6b698bf5ef7942e098efff1031861e5eb8670afdd18452 17735785 main/dep11/Components-s390x.yml 29584e8fd8bc91d9d9099893ae4951601430b1df4f55659e089d34e4525540e5 5976062 main/dep11/Components-s390x.yml.gz 1f9ca828b916aabab9b41f75950df49f71dc5e8a42f674ff4cb2138f85274314 3894008 main/dep11/Components-s390x.yml.xz 057f28adb7c2452ab2c810fdfbfce0305ba8143ffe2e24969b2ece077aba7e9f 13048320 main/dep11/icons-128x128.tar 4f46415e13538a05743752a630c9b8795a9772d0ab4ebe83c9d7e19f0e4bf179 11409337 main/dep11/icons-128x128.tar.gz e0c306e3293ecdcb8392faa372b00f1fb979c327c3e4370452acf7713ab885a4 4878336 main/dep11/icons-48x48.tar 93c4366d8b6ef489bb935434d9a2c56d842978922e941dd4ee716ede2a805494 3477622 main/dep11/icons-48x48.tar.gz 910ec31c85f12f0edefbb43fa2514b9896d105ce7316272a4c55263af864c238 9378816 main/dep11/icons-64x64.tar a94629c3e4fbe9607fb2921e1c906f88343a7cadc484a1087983181ae6df66a3 7315395 main/dep11/icons-64x64.tar.gz e061ee16e4478c39875bc3d977fdd5f880a71a3ea97c9f5119ac127a4305579a 6191 main/i18n/Translation-ca ed06627194c667d774188bcf0d9b859625ec60d2098238ee3c1cd5e1c147c4f7 2673 main/i18n/Translation-ca.bz2 857bef6538df7a4e2ae01a6ef40f8a5c9e0512797a769d8813caaa57ca867f29 1205166 main/i18n/Translation-cs bdd79636af5f08f4c40bb5266a41e4707b7bdc84d5458451df0255b787c380a6 323247 main/i18n/Translation-cs.bz2 2c7c6d7013e3d04a62c457525567fac4ac2747ef59f1b2a93cad8c0904c960b9 20240560 main/i18n/Translation-da 8935ec6ddfeaeb542fe444013ad9fefd6ffd2da2afe818efeb417fb50568b52e 4411163 main/i18n/Translation-da.bz2 55e94848df1df7d0963f3cb02cfb4171031350c549e4ae64f6aed517ed08ca6d 7801238 main/i18n/Translation-de b68fe8718325ebd1e2a8dd30f52b17c003e315f3468f9b7890fe5b1b91c709cd 1717951 main/i18n/Translation-de.bz2 284169348b8bd4e0de4cc5641eeb05577e80d2bd736452e454976c052cf3cbe2 1347 main/i18n/Translation-de_DE 481a435ad350105b74c4972859c44f447b7a8b5edea0d42f6dd635792e00a461 830 main/i18n/Translation-de_DE.bz2 9f3b3bc0da0653f0ac8484024a7f77aeda681474907f3a94b8a0a0933775d14d 6257 main/i18n/Translation-el 807de361285151534654b83681415016d443e4abd1a7ba36e1e78b4ac337b973 1835 main/i18n/Translation-el.bz2 87a5cc96d599e93f7cd76ea6f32b27e9742abd8027c9c76c40ad1a091e0d8950 30246698 main/i18n/Translation-en 4d7cf2aa527bdd9129bd6e5974c41f574de06f1963d9062af0787972b4a76b7c 6240167 main/i18n/Translation-en.bz2 abccaeb24d409c21b94883b74785053d0f8fad3e94449078ebe92af38861bc5a 2261 main/i18n/Translation-eo 747ab457a83de3b107e25b9cc5536aea2f19e0fe1f08d5357475acea0d788fae 1196 main/i18n/Translation-eo.bz2 38345d246390b3845920937338647a70b1a6a93f354615da725fbf426ac3e332 1325929 main/i18n/Translation-es d6bd3bb26fb52e553bdaa40a041aa167f8a0c207149ebf626bea65c90ff7e99f 317946 main/i18n/Translation-es.bz2 80c3ff00f3b37b64e73c85b11eab47fe88901b6f8d9f189de0e95a387e02ebed 10093 main/i18n/Translation-eu 7ce6c68ef8a577bd215da5f7a12153bee27268b0b6b9503aaf88244b225f20a1 3914 main/i18n/Translation-eu.bz2 54c5db1926c3309513d37990460a51c586ae6f01bcaaf2732e537ae400b6f5f5 269212 main/i18n/Translation-fi a0c315c9c517ac029e5981f14a3c15fa022c7c0e1e86edf123e05027343974d7 75849 main/i18n/Translation-fi.bz2 bd258bc1f5bbc6694e24f58fe4dfb5f5636afc86a431795b931225e9e336feb3 11857302 main/i18n/Translation-fr ef77125783dc8b1125ea85050ba00bfe042e6f38fa1f73613387fe30cae47c5c 2433064 main/i18n/Translation-fr.bz2 ce1a70b1000909a09166e30d574c717f3d60ba173bb65ad65e768374dc73232d 1427 main/i18n/Translation-gl fa1eb924fc1473b81f7790ccd909de1dc274f4f266df8af544261f03e1d21079 824 main/i18n/Translation-gl.bz2 22e19c218655a9a4d09e9930a66715aeb5d0b02bdc4d147e5816067873e71861 21069 main/i18n/Translation-hr 04e538e90503a9238d071bba89039e563d4c03ee038c217708a4f8c8672c28d6 4695 main/i18n/Translation-hr.bz2 a275d9da1b509fc6c1d8307ff33daea14669cec8b8f89bb4c4fdf4d50ff48135 65236 main/i18n/Translation-hu 94827a9f6e251237fb3b093360f88ba469d2be8d4a7c2c02c84298c94faceaa5 22243 main/i18n/Translation-hu.bz2 0f4bfaba954ffa37332a34df69c8844b7334cc0b61515e9510513e2c43e140b1 3983 main/i18n/Translation-id 11aebe26133b1249ebc06ec6d1a8b76f5975b9a3630daf71ecb7e2f6521a2fd2 1780 main/i18n/Translation-id.bz2 d965461960f14ff1f614bcd0ba757874e098cd460b8ae0e018fb4aba254ce641 24489940 main/i18n/Translation-it 451a92cd21dc98889f43a39223dc8863284bd1a8e515bc58633bdb7bf96dd37c 4844227 main/i18n/Translation-it.bz2 1cb8cbfe8b502cc64639b02150e6f805bdeebedae3eb69273146c03ca6c9287c 4511401 main/i18n/Translation-ja 0c00e0a8cff6fb13bdc4ed3387e3faf4f9db94f3ed4ca8e72d324c0a03d8f018 803966 main/i18n/Translation-ja.bz2 7238152be74233d91630f7100ef7ff2bb8a95598b5fbc11c21c7afeecfc0fecd 11879 main/i18n/Translation-km 01577e06c8e41b3a914ae539147af0fcdc7a0f883f50d82b57b263cf62fe1bf8 2371 main/i18n/Translation-km.bz2 232cb289feae187cf94ad451662d7ce36be8014c40b69e645d19b9534dd586df 2606190 main/i18n/Translation-ko 894aba3a34a47f3d59deca3bda07f8aa288e9f4ed6ae92422eab3fd9dd370ad5 584643 main/i18n/Translation-ko.bz2 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/i18n/Translation-ml d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 main/i18n/Translation-ml.bz2 16be336bba03786450a43321709eca2fce7fa7b50a135a97da71e16eb5e7d60b 1193 main/i18n/Translation-nb fdec5fc00fe2d0e3c7730462f95273492d278eb8a6957c1b437969833366c217 738 main/i18n/Translation-nb.bz2 ce65092fbb0a09286644912bfaf3a9535921705519e16d07617ad85ec44ccf3a 174332 main/i18n/Translation-nl e12b923a6f3f83636a31e6e1b2503d8a213e1e4112586a27700fc17bb48ce564 47973 main/i18n/Translation-nl.bz2 8999184566c11a42f9a31c810d9252316dc4f52ba738db43e0be2cd760c823a1 2051811 main/i18n/Translation-pl 17fe48deb79b044bdf5894d0d129823b1d86653b9759f848667a74b563625379 491993 main/i18n/Translation-pl.bz2 2dbf3c4316bba32571abc589b177be93c8e72885131940c9993d3fb6b8d58cb4 1074959 main/i18n/Translation-pt 991a66952f6395d7588f38e68e1032f4dcc72da61322a59460c34a24d7713400 272186 main/i18n/Translation-pt.bz2 5d7ec6fe173a67789c445369b7ebf8709cbc9ce4f3e06a75cf36c562a16580a1 3306707 main/i18n/Translation-pt_BR 1583cdd6a71e29b6eaea0d29dee9ce903fc8ced1f9f57e5ad4de154938799bd0 802734 main/i18n/Translation-pt_BR.bz2 c90708ca8975ced4acf4be98a4ac1f5c8092fd826b4d928e35c3650e705553d4 1717 main/i18n/Translation-ro 35f2449dba7bd93e0aece908f4c4de53cc864a48c8f7aeaa5a64f67384e1bcda 982 main/i18n/Translation-ro.bz2 f8b907289a1970413a47a3450c59b04e166c08cb387ee3ae4f6c0d2e4774c379 3058931 main/i18n/Translation-ru 8685feba7a33fef7ad8d7fe5db5f59e837eba69134deb87610742cf564e47258 494782 main/i18n/Translation-ru.bz2 ee2a1713ba3ccf4aa7ef3ee1b5786874c38ecc15db012bc15c3efbf5ad8facd2 5984088 main/i18n/Translation-sk 0dfec1c42d581b3fe8f95bbe26f649f45234d419c7e709dc881f1994bfb20974 1304539 main/i18n/Translation-sk.bz2 5ff9c60997a547f07d212476a8f50b4942f012d7952765c6c1925c52495711d1 323953 main/i18n/Translation-sr b4608fc3c0c7f6aefe0f6e5e19d0fbe0d5035333e74044e29358b3e3efa99536 58385 main/i18n/Translation-sr.bz2 5656d4e913760691e99cd4805e76c8f18c4441fe707a02e621a2a172da756d5b 85612 main/i18n/Translation-sv fbad8c083b9985e53a2a82d7e32f26f683bd5b8e2f1bf09a3e0fc3f8f7abf6da 27320 main/i18n/Translation-sv.bz2 2e50dd5fdf1dd6157c0db51afb4457fcfbd427ebb6d1268aeeea1daf50da78f0 14670 main/i18n/Translation-tr 401a0f8d754d92c562bafe54aa0cb2dd7686ca015425513b666b50b8c9dc36a7 5362 main/i18n/Translation-tr.bz2 6c66f49d6c9df7ef28f92aaab2620a2151fa16f74bf96deb3b74987183e43b86 3740343 main/i18n/Translation-uk bd760427bda1a65895dd7b3bd6a3e2b2a0ee6b4060ce726ec4b7c02b89a72204 576766 main/i18n/Translation-uk.bz2 c2207dfa8d62c7e2a31851842dd928739bc147515f69fb7a28db93196dd1a601 21882 main/i18n/Translation-vi e3eab47e1acdc01ee2d774dba5b0f9d29c98ff48b25a57d469eeecf60d3035ca 6510 main/i18n/Translation-vi.bz2 7133134d1b1b6c869b4b700fed9778e93a0b774391402ad3399e9ff46984efff 2007 main/i18n/Translation-zh 8cbeadbbcec613b8476f8e2aa40b15772909109e10a83317c111fcf7c28d0219 1215 main/i18n/Translation-zh.bz2 d88628c7a7a16a042234daf91a709daa6d5f9de15406ec78530891354fa25c75 425199 main/i18n/Translation-zh_CN 1ef87b145198090deb2d037bc16b5b940c0e757a2511f4ff84a7c750720b2723 113621 main/i18n/Translation-zh_CN.bz2 564fdb3059cffbe78dde61697e77edd7bc94005a358cc4b5dffb436776d1b2b0 39965 main/i18n/Translation-zh_TW 0a4d5ecccec7069a32b30de129018034b2f6f2b318f1530e1edc239182442cf8 14859 main/i18n/Translation-zh_TW.bz2 343fe56ad4f39f517c6b504106ce828f6ab57b71fd8fe11ded31b5d217950b9a 58277 main/installer-amd64/20210731+deb11u7+b1/images/MD5SUMS 3dddfa19f9ca9bd20c0f0249d68427e5a70cabb845c8dc9736f3949c96ec1188 78097 main/installer-amd64/20210731+deb11u7+b1/images/SHA256SUMS 91e63d03c43f9feaed6c255a510c30c35c547c517f395c2574900b0119fad790 57705 main/installer-amd64/20210731/images/MD5SUMS a3a16cc4af2d688613ce8df4d224974629ad3383a1969350c24ea68bfdd5f1e5 77333 main/installer-amd64/20210731/images/SHA256SUMS 343fe56ad4f39f517c6b504106ce828f6ab57b71fd8fe11ded31b5d217950b9a 58277 main/installer-amd64/current/images/MD5SUMS 3dddfa19f9ca9bd20c0f0249d68427e5a70cabb845c8dc9736f3949c96ec1188 78097 main/installer-amd64/current/images/SHA256SUMS 1df7955a3c09498e279431cb6304f4e616cb7ea5a8ee5d4b9db85ba9d2a05bed 69049 main/installer-arm64/20210731+deb11u7+b1/images/MD5SUMS fd710c158d06fae3de80d23198806c9101e7e6cc640fad6b366d3f06eed9e91f 94149 main/installer-arm64/20210731+deb11u7+b1/images/SHA256SUMS 291e81049aa85b147063ec1aa5bec87da60d3196c06c3098de5210c3346837eb 68403 main/installer-arm64/20210731/images/MD5SUMS 5dfc89487fc8717ab9a9b75cdaaf01a295ab3021cc3310d3fe9dd3e78fc1f666 93279 main/installer-arm64/20210731/images/SHA256SUMS 1df7955a3c09498e279431cb6304f4e616cb7ea5a8ee5d4b9db85ba9d2a05bed 69049 main/installer-arm64/current/images/MD5SUMS fd710c158d06fae3de80d23198806c9101e7e6cc640fad6b366d3f06eed9e91f 94149 main/installer-arm64/current/images/SHA256SUMS 54528ee7dfb52dc1ce6680b4a8b898d9454936c892012a677747465fa8f506d9 20678 main/installer-armel/20210731+deb11u7+b1/images/MD5SUMS 86396ff61efdee365e4ab688b91f773409a12d6950f61a7e8671a9b64777458c 28882 main/installer-armel/20210731+deb11u7+b1/images/SHA256SUMS ee9f639b7a0304207f23c84f5396284720a6fc6c638ee7be6873944a0f224c95 20182 main/installer-armel/20210731/images/MD5SUMS 07353d4c378ea579803ed8c1aca3fe6df2cbc89788736c7d01102a7b3ebad859 28194 main/installer-armel/20210731/images/SHA256SUMS 54528ee7dfb52dc1ce6680b4a8b898d9454936c892012a677747465fa8f506d9 20678 main/installer-armel/current/images/MD5SUMS 86396ff61efdee365e4ab688b91f773409a12d6950f61a7e8671a9b64777458c 28882 main/installer-armel/current/images/SHA256SUMS f899f04724b1fbce7e9a9060e82e1dcb942919914bdc808d120b7e52fb7b38b2 64380 main/installer-armhf/20210731+deb11u7+b1/images/MD5SUMS cf5b025aef61b2ea4e0c5f94d36e22e5ed26b01da945f498f9b6cb5156171b1f 92680 main/installer-armhf/20210731+deb11u7+b1/images/SHA256SUMS 8c1f810a60fc7daf099e608b763cec563f59c82203a07bbf4469a6213a8946eb 64240 main/installer-armhf/20210731/images/MD5SUMS 67c5b636e3fc02747ca9593e6fc7e906a3ec95d4947740fec81b1e942f0643ae 92476 main/installer-armhf/20210731/images/SHA256SUMS f899f04724b1fbce7e9a9060e82e1dcb942919914bdc808d120b7e52fb7b38b2 64380 main/installer-armhf/current/images/MD5SUMS cf5b025aef61b2ea4e0c5f94d36e22e5ed26b01da945f498f9b6cb5156171b1f 92680 main/installer-armhf/current/images/SHA256SUMS 393b9f170f9732a04cee8abf0dc9d0a52272bd577c47d30310dd88c2552db5b7 56840 main/installer-i386/20210731+deb11u7+b1/images/MD5SUMS fb5c92b43fcaaa6850fe79473a5fac3c6a27e31b72a52d81297eb283fdbc46d1 76724 main/installer-i386/20210731+deb11u7+b1/images/SHA256SUMS 96e8acb8eb827ce7032587400fbe848b6f53921c661d52e1b16fd243cb8e57aa 56286 main/installer-i386/20210731/images/MD5SUMS bced74c95a3688a9a2a28abb8190cb7efd7e1f6372dc8989e260771752ef571b 75978 main/installer-i386/20210731/images/SHA256SUMS 393b9f170f9732a04cee8abf0dc9d0a52272bd577c47d30310dd88c2552db5b7 56840 main/installer-i386/current/images/MD5SUMS fb5c92b43fcaaa6850fe79473a5fac3c6a27e31b72a52d81297eb283fdbc46d1 76724 main/installer-i386/current/images/SHA256SUMS d1eb4b5cef71f7c78971aa99bf86ed4980ebcb8bab8d0e45835731d0ce173969 630 main/installer-mips64el/20210731+deb11u7+b1/images/MD5SUMS 275fc83d164449c94cfc9c4039f38eb08e123bb11d6f6acc2724441f752a3727 1026 main/installer-mips64el/20210731+deb11u7+b1/images/SHA256SUMS af3b55dea76e91f1565bd54bc1af76a6a0bb4991eef9abe281a22d9fd8d54a7b 627 main/installer-mips64el/20210731/images/MD5SUMS 995cda8278b101eb25849d56f3ef33290fb57a940fa1c6837f19df00ceafaaff 1023 main/installer-mips64el/20210731/images/SHA256SUMS d1eb4b5cef71f7c78971aa99bf86ed4980ebcb8bab8d0e45835731d0ce173969 630 main/installer-mips64el/current/images/MD5SUMS 275fc83d164449c94cfc9c4039f38eb08e123bb11d6f6acc2724441f752a3727 1026 main/installer-mips64el/current/images/SHA256SUMS 74028a1b5cf4c8a3e8b30fadaa3c4a2237b9032b93a3abfb3d3edb64667cbe61 630 main/installer-mipsel/20210731+deb11u7+b1/images/MD5SUMS 1dd26a64b20327c1718dec6cf314168dbf68a225b1e68cedb2c8d4f4ee218087 1026 main/installer-mipsel/20210731+deb11u7+b1/images/SHA256SUMS ca77bbc823d1bf6999e141cd42c1bb4c18179cbe4a3fbb6da3e40e1055848ed7 627 main/installer-mipsel/20210731/images/MD5SUMS 28589449e1b3ac9a73bdf6f266edc83e70ebbbca587a228b15b0dbe5e1a634fa 1023 main/installer-mipsel/20210731/images/SHA256SUMS 74028a1b5cf4c8a3e8b30fadaa3c4a2237b9032b93a3abfb3d3edb64667cbe61 630 main/installer-mipsel/current/images/MD5SUMS 1dd26a64b20327c1718dec6cf314168dbf68a225b1e68cedb2c8d4f4ee218087 1026 main/installer-mipsel/current/images/SHA256SUMS 1703a54e2b260ec691ffecd444e7507f03bbefce7cb8341b73ad78ed16ca750c 576 main/installer-ppc64el/20210731+deb11u7+b1/images/MD5SUMS c234d16ddedfbb72bffb5cb22b32b981e03b3461f6720c10c7d5b8dc726e912c 972 main/installer-ppc64el/20210731+deb11u7+b1/images/SHA256SUMS d162b2da6777c1ea0643921cc1a3dde78ae48cf022711eb98c7e9dd030b89a44 576 main/installer-ppc64el/20210731/images/MD5SUMS 73e281bce56df3c7512ffa1a1cb13886064759a461621db4acf9b1f71965c676 972 main/installer-ppc64el/20210731/images/SHA256SUMS 1703a54e2b260ec691ffecd444e7507f03bbefce7cb8341b73ad78ed16ca750c 576 main/installer-ppc64el/current/images/MD5SUMS c234d16ddedfbb72bffb5cb22b32b981e03b3461f6720c10c7d5b8dc726e912c 972 main/installer-ppc64el/current/images/SHA256SUMS 20b3ae961820dbc6df8275c2efa95d4ed34775cd22f9d5dc0d656bd699c9f99d 374 main/installer-s390x/20210731+deb11u7+b1/images/MD5SUMS 1082cf1f5b94b3c234dea741a0ed81e03cf3f78b0a55affcf58d517bf37fee2d 674 main/installer-s390x/20210731+deb11u7+b1/images/SHA256SUMS b2c58a9c5b97a59742a8056e3e9d7f4f22d4d11e51c71d7a0051dc4649a717b9 374 main/installer-s390x/20210731/images/MD5SUMS 61447263ea7318c444fde199afc718a8498fe67bc0e7116f2e1103cc65ef672b 674 main/installer-s390x/20210731/images/SHA256SUMS 20b3ae961820dbc6df8275c2efa95d4ed34775cd22f9d5dc0d656bd699c9f99d 374 main/installer-s390x/current/images/MD5SUMS 1082cf1f5b94b3c234dea741a0ed81e03cf3f78b0a55affcf58d517bf37fee2d 674 main/installer-s390x/current/images/SHA256SUMS de9a48c211839c666254f2eba37417143bf6d0db56abfe1d07e4c35609d3f04f 117 main/source/Release dced89e82fac92fdc1cb92f99321787f26c8c9b0d72da39ec091dd96234ae3d1 44655922 main/source/Sources 006a5628b8afa45bf77cc449afa6f98647573b0e98b119a5944e65741094bdeb 11429086 main/source/Sources.gz a7e9e21d852dc2b685e9c28e0b06a9a4043220367cec57bd0e7043bd58c1a069 8633788 main/source/Sources.xz 29cac69ab0fd86e224587eea8e2ed2fb9b1b2e3c936fb1dc7165b8ed8d00528a 17347341 non-free/Contents-all 3b87590d0360ae141f3688fbafb5fdad35d4dd4b1a239888c911743c4357862d 888157 non-free/Contents-all.gz 1335601f3e9b7f67c279a4c1619203dd6461fab7c16c29e1d71970a9bd023052 1097448 non-free/Contents-amd64 df4bb7a18156a7f33c70f36d1709ae7ba48716d96ec1b940bd3bbb47ba432de7 79655 non-free/Contents-amd64.gz 6f4902fb02e2f1092d88d8101024129a4af0fd245e75803b0b93b0475feef42e 499970 non-free/Contents-arm64 c2715365833d3d97cb90e1fbf44df3c6835b323ef1e5dfd660b1cce148cf62e9 37376 non-free/Contents-arm64.gz 386c53a056d4aedb9d48a332056c51a302e1b043480cc24fc9ea9053ff8fe002 95417 non-free/Contents-armel 5fc23867def6ff06cf0c72080f1862ea142b20d25ca0a1e8e8b9c83ca3b82519 9298 non-free/Contents-armel.gz e2fe020c8c47e80e483acfe05462706e063c6932f9bb857e54d59383d415a44f 146124 non-free/Contents-armhf ac08720d4fc801273e1a8b2e0d7d7f80d07220f09089011a577ba47f12172ebb 13502 non-free/Contents-armhf.gz 6468671814b9daa924278df786f198b0b34d8f525b7a9c0ff8cdd6db3dbc661a 343198 non-free/Contents-i386 d85698eb7c99ba6fb568afcb497365ebbc59421c89dea8b6186b661e8c19fd12 29072 non-free/Contents-i386.gz 6bdcba453cc1369f93e7157d5d7f9c67198edc62e4e194b079b0572186a95b34 91215 non-free/Contents-mips64el 0986d6fc85dcf209edbf39b1ee2c84b370ea02dfe810ac33cd9cc89a2f3a2a18 8686 non-free/Contents-mips64el.gz 5102cb8d1b74daa60d4d6444e563dbdaf73ffaa2b7ce71a304987ff575da7f4e 92244 non-free/Contents-mipsel 53bd140b538ffea9c0bd8b6b073b3ef613ec1d452bb1bad5a5f86a029f11e3dc 9026 non-free/Contents-mipsel.gz 03756e78d0f8004d0cdd2e4fe2238a6c851f94c42b0ca7064629b55a4ca494d6 716110 non-free/Contents-ppc64el e3321e93f91e779a59e4ca94c61d1eedd13d02a847824c459419c29203ca6959 49881 non-free/Contents-ppc64el.gz 6d2b11e017bf520a64870b3ceecfac7944f991928095bd2715429987a342c37e 74537 non-free/Contents-s390x 228df45a42a42dd62cc747f2abe99dccd25c384aa423c17896a6196955cd9c12 7407 non-free/Contents-s390x.gz 1d53da6b88f2d7252351b65dafa6ec6453ef19326ce8490ea48d865557f30c52 10803369 non-free/Contents-source de64ec721f3e9589c6f7efc4f23c2713a40afcce15e033eddbfa0674dc81ae4c 1063443 non-free/Contents-source.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-all f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-all.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-amd64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-amd64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-arm64 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-arm64.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-armel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-armel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-armhf f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-armhf.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-i386 f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-i386.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-mips64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-mips64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-mipsel f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-mipsel.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-ppc64el f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-ppc64el.gz e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/Contents-udeb-s390x f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/Contents-udeb-s390x.gz 68ddf090986f56743010180da8d3e05a41bd5185e0047a98c97adb038cc5fc4b 189021 non-free/binary-all/Packages 569cc71a40dffea02aa6cf8b516370e08587ec71d34558cf6f1fe688c9629468 50928 non-free/binary-all/Packages.gz b9d8d7fb507a77a6222770fbe09815bc0cae22af92d0c16538d53b4576af6784 42996 non-free/binary-all/Packages.xz 3f87c1d57bbb196bc7d6a2bec129e82e4f4296b3743a105f53104fa82e3d6f07 118 non-free/binary-all/Release 41eae996375149a4854537915bf8162c5a22c77f3fa88c6466ce16d5f1b7d1d3 545576 non-free/binary-amd64/Packages 6bebe66d1f22f6dc11b186fbd34d029402a0848057dfa5a8afa193cad65bc205 122225 non-free/binary-amd64/Packages.gz a108aa5d825e98f766b4e20d261c21c1fafd9340547006244aa6fbb51b77d837 97772 non-free/binary-amd64/Packages.xz 9a0edbc466a3e91231c1ba756996d5fb598d3b14166a2a2b72899d4672f53a82 120 non-free/binary-amd64/Release 514482332f1c35020f2ba2ac2cff8e956dc5ba0a9a5533251321cf3e2e50ff89 381335 non-free/binary-arm64/Packages c2b9e19b24c3c9f859da6a28fd8cf27bc1b698111d4bd48728a8b8cb093085b1 88201 non-free/binary-arm64/Packages.gz 2ab2f8d500ce30e6b4e70fa5ef5678a3eef0743deaec93a24011949bc5911f75 72980 non-free/binary-arm64/Packages.xz 76a1c234c80cbabd279f721e53350404c3cffb523962e44161ded825f87c673c 120 non-free/binary-arm64/Release f5738f5a5d9f4391ba0719b7bb175892d93561b688137917a4cdc75537ca70e5 227933 non-free/binary-armel/Packages 89cb801437910d9b6076d9caf85f2144b224cb1eff7dfbd014219242df514b82 61822 non-free/binary-armel/Packages.gz bf2bfec078bdf2dcd2d0d411109257f3ec2d652087399062023d2fcce2e43710 51800 non-free/binary-armel/Packages.xz 7148bdadd1b6755cc63ffebb30bb3f228e3d6d2565e18ae6641eb62cbc802fa1 120 non-free/binary-armel/Release 4a9f94f9f510ff6c829677b8dd08ed0c5ff7b33f2118f152d2a4e6b410f8425a 259156 non-free/binary-armhf/Packages d7ae0acddc9f6a9acff311a662f78729a610fec44101cd8275fdbddebce7b5d4 67317 non-free/binary-armhf/Packages.gz 21f37dc3d988493e921f40cd37cc6ef2391b2d7cccf5c83fbf1b037602c0e521 56272 non-free/binary-armhf/Packages.xz 404c43c7b78d9a5b45b1d0c1851c58ac77a4b4ffe83c81d5c184b114c7c65804 120 non-free/binary-armhf/Release 54c7fe6dbb5eba9498c1726c1e2119d86697ef32300d3bab99048f1b4141c482 422388 non-free/binary-i386/Packages 54d73d03945551ef08f0c0b74828b3d78d2747a5f26c3a5d7d7fc446a79f383b 96319 non-free/binary-i386/Packages.gz 3f0a14b592ba6bf04c31da2ccbbe82bf058d62e341c1777c02f3fd5c00aab76f 79344 non-free/binary-i386/Packages.xz fda2cc9eaf856a91a54c1c893a273d148234734ffea5e1ae811d3404c07700b8 119 non-free/binary-i386/Release f7e9a5d9f19cc5b819efa1aac30c9d833ed9e41dfdce9abf2bc48d0467abae1a 225506 non-free/binary-mips64el/Packages 2d01bd458989434fd6555cdc4d4f9dc554881de09ced2db213fc26395f4108c8 61024 non-free/binary-mips64el/Packages.gz ed53056d18b6b8589fbbebffd26f8fbda708f71870e1bbffd4a4cfc7249283b2 51124 non-free/binary-mips64el/Packages.xz 19a2da1050283b31ebd2f6664572c326fe39fa70de30821b9a5410e5e5ae0daa 123 non-free/binary-mips64el/Release c690e75e4633fad47565d5afcef96622ec6e02b2fa824e5c0508f1119044c906 226162 non-free/binary-mipsel/Packages fd05e8f63760b2163ba4b40cdf200a9b113edfbf81d5a2a318a2b5605812891d 61277 non-free/binary-mipsel/Packages.gz 87cb9361adbac3f2604906109b21c6b685fda9caf3525395dd4ee057d7c4e43d 51364 non-free/binary-mipsel/Packages.xz 7d90fbb38122b89666a80ad2665d91fc0eac09bab9f4f7603cc4547504abae06 121 non-free/binary-mipsel/Release 74efb451a4beb4d707ceac0597842d515b78b7d9effb56a06663fb7428ef129e 381597 non-free/binary-ppc64el/Packages c4b451037905b8277fe0a2c0699c3e4ab0de2eb69559c19ac89361440f0439d5 86900 non-free/binary-ppc64el/Packages.gz 7bc21cd6ac30fce563e47909e7ec989071941134e89b2d895100059749cf3a47 71812 non-free/binary-ppc64el/Packages.xz c83ec7a841e5fc039ecef935b1b67f91cebad518a361463db2f804fcb32aaf91 122 non-free/binary-ppc64el/Release 79ebd2f1278b5db689359d517f88af2ae9acd8d493bf791e5cb5f73b9c81479d 220570 non-free/binary-s390x/Packages f7240f44940160f2d9b7cb553f6f47713186ebba6646c18a093e61bc4088e720 59856 non-free/binary-s390x/Packages.gz 4a1d593c1cd1adb67b9ab6bd5c2558536c284486eb714f89b9ce09229bbb1eef 50216 non-free/binary-s390x/Packages.xz e51de0ad0c2a44d2a9054242a462481f42bf24e4da5f58fd0ef35993dd35693c 120 non-free/binary-s390x/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-all/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-all/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-all/Packages.xz 3f87c1d57bbb196bc7d6a2bec129e82e4f4296b3743a105f53104fa82e3d6f07 118 non-free/debian-installer/binary-all/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-amd64/Packages.xz 9a0edbc466a3e91231c1ba756996d5fb598d3b14166a2a2b72899d4672f53a82 120 non-free/debian-installer/binary-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-arm64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-arm64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-arm64/Packages.xz 76a1c234c80cbabd279f721e53350404c3cffb523962e44161ded825f87c673c 120 non-free/debian-installer/binary-arm64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-armel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-armel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-armel/Packages.xz 7148bdadd1b6755cc63ffebb30bb3f228e3d6d2565e18ae6641eb62cbc802fa1 120 non-free/debian-installer/binary-armel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-armhf/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-armhf/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-armhf/Packages.xz 404c43c7b78d9a5b45b1d0c1851c58ac77a4b4ffe83c81d5c184b114c7c65804 120 non-free/debian-installer/binary-armhf/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-i386/Packages.xz fda2cc9eaf856a91a54c1c893a273d148234734ffea5e1ae811d3404c07700b8 119 non-free/debian-installer/binary-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mips64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mips64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mips64el/Packages.xz 19a2da1050283b31ebd2f6664572c326fe39fa70de30821b9a5410e5e5ae0daa 123 non-free/debian-installer/binary-mips64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mipsel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mipsel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mipsel/Packages.xz 7d90fbb38122b89666a80ad2665d91fc0eac09bab9f4f7603cc4547504abae06 121 non-free/debian-installer/binary-mipsel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-ppc64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-ppc64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-ppc64el/Packages.xz c83ec7a841e5fc039ecef935b1b67f91cebad518a361463db2f804fcb32aaf91 122 non-free/debian-installer/binary-ppc64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-s390x/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-s390x/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-s390x/Packages.xz e51de0ad0c2a44d2a9054242a462481f42bf24e4da5f58fd0ef35993dd35693c 120 non-free/debian-installer/binary-s390x/Release e13d055f233a81a77666f0ff8dd9d748917b2829740756e1dc2b8a350309bcb0 278293 non-free/dep11/Components-amd64.yml f51b1a07cd72a36b2a9f36742ab26819a7808aa7765cbf3e2ff4abe6be66b50c 29634 non-free/dep11/Components-amd64.yml.gz e113163e116c137577fc9d3a4f7c95e0934ddbae7bdae5e083aaa1ce095435b6 17904 non-free/dep11/Components-amd64.yml.xz 6177cb908c067306c11bd8728a5b65a205d999be63930c079e3ff4250a24ce8e 271451 non-free/dep11/Components-arm64.yml 1b6107a1fa771a8fff50e0b182362fd679dc01f58f7a1f3fe9fe0183daf3be0d 27686 non-free/dep11/Components-arm64.yml.gz 7ff5eda9a37e07b9bcfa479c89863d7b2b1aafbedbe4b37ea6c32a16f2eaa241 16392 non-free/dep11/Components-arm64.yml.xz f54eccd2dbf23fa45cab9e9e7abfafeb667397ea70b6197a3653e8499ffea8bf 271451 non-free/dep11/Components-armel.yml 5581d7f4c159a5cbd33927294f7fc9918e7deaf04b313001965c83412b6a81f7 27606 non-free/dep11/Components-armel.yml.gz 0830d150400c82255a52a74f6af9f1a11007bf4b92fc814513f9e13cfac0b22c 16448 non-free/dep11/Components-armel.yml.xz 15d1524c660c8fb1ee911775a9b59cebbc66843eb97cc0a15a361009f153e6ff 271451 non-free/dep11/Components-armhf.yml 3fa04d7715c8955987742dc376d10327a975f9583cf656da055d13895e460a67 27691 non-free/dep11/Components-armhf.yml.gz bbf5a05de96a53c0e10af6019cb7b053b83b0f5def488cde4d8359475adb08da 16364 non-free/dep11/Components-armhf.yml.xz 716cec6e00d8303375812c8c9be7cbfa5fc858fdb3d9af3f0c72a696d8f7cb2d 280613 non-free/dep11/Components-i386.yml 40f189b3b3a74bc85652829d0c67b21aad7e60ce389f26fe1959db1e1e8ec48c 31098 non-free/dep11/Components-i386.yml.gz 18507e0a03c74ed39b9bec853eb9216b458f2fe2b7535c2622c126b9cd35301e 19156 non-free/dep11/Components-i386.yml.xz d82d6fadb06b6a1f0d36c155b70a02eb2281838aee3ce1b9bf51b7ae06136721 271451 non-free/dep11/Components-mips64el.yml 25d788e157070218396bafba65ff087551830ba0d0ba3e3cec5342bb150aec57 27765 non-free/dep11/Components-mips64el.yml.gz 2d0aa3979fd6093dc6de8ba902166a985235c8c4926e07cab7aa2a9b4ad0c11d 16380 non-free/dep11/Components-mips64el.yml.xz c55445f6f87fd566212bb018f9fae1a4eb43c1a66fe1b0e198b1c7d7e500b009 271451 non-free/dep11/Components-ppc64el.yml f525af23f1a1eb26ee786c36e2afd4aa5e4102b646f33f8c6788aee395b752bf 27592 non-free/dep11/Components-ppc64el.yml.gz 0ee03164cca5098ec7c6f98a469818b40b61da7846451cc223d0b9e01585c57c 16576 non-free/dep11/Components-ppc64el.yml.xz 359af9af71c00d90265395225b75313966435729cf1f6cfb1085fe1721b01e72 271451 non-free/dep11/Components-s390x.yml 47ef508dff3dfdf17ceeed229d98a2e3992c1a26f28eb328a2d1958d2ddfe070 27558 non-free/dep11/Components-s390x.yml.gz 181db8b5130910114256e8809ff9a1637efac55b1f33d1f516983521b8d51e7b 16356 non-free/dep11/Components-s390x.yml.xz 601045de5331d63b7ef2a24f8f74a7452d7be785f94ae6c46002c5dc2608188f 8192 non-free/dep11/icons-128x128.tar 4fb59feb5d5afe99980ea36c3d7c14577a4b5f11705e7d16524767708666ed54 2394 non-free/dep11/icons-128x128.tar.gz 977a5470a45ec30f5e230361a446f4692f9cf9bc2abccf6eabac2df0291f1ee4 4096 non-free/dep11/icons-48x48.tar 07a401f7b03554c2d8ab32dea5885c43b7da7badeea0569b9ce5c9dbbb7cf66f 741 non-free/dep11/icons-48x48.tar.gz 159551b3012db94a70261cb8f88619a6bb148318da051479ade6df7211c41a34 36864 non-free/dep11/icons-64x64.tar 872b7437de6fb938db8b26d9de9a3113bc722cd6ed682973151722e2b7a190be 27667 non-free/dep11/icons-64x64.tar.gz db924f2bd81a5875019d05bea92accc667c5a99099512ee11862db412c21d7fb 572893 non-free/i18n/Translation-en 91ff4a231eff217916da9113aa017d4090fe442fa54f1edf21af3811e0bb255a 92419 non-free/i18n/Translation-en.bz2 6372d37a918ae4dc1be5a748e9e02e57573e765e14a3c8aa0f37208b223555cc 121 non-free/source/Release 2bd47d8b576397abf753f06eb5bec85b2036e84b80b8d8646a0e784380d0d53e 360307 non-free/source/Sources c9d5108699279e6cb2946d907c13655ebe8b6fce12986a4ba8b0ece0257977c1 98323 non-free/source/Sources.gz 3f3f09477a76bf44bbd93e7efc74f55783f0841c6692d6188b91e8f58a0c7999 81280 non-free/source/Sources.xz "; let canonical = signed.canonicalize(Some(&keyring))?; assert_eq!(canonical.len(), 2); assert_eq!( canonical, &[ ( "A7236886F3CCCAAD148A27F80E98404D386FA1D9".parse().ok(), Signed { content: BString::from(content.to_vec()), signature: vec![ 194, 193, 115, 4, 1, 1, 8, 0, 29, 22, 33, 4, 167, 35, 104, 134, 243, 204, 202, 173, 20, 138, 39, 248, 14, 152, 64, 77, 56, 111, 161, 217, 5, 2, 99, 157, 150, 185, 0, 10, 9, 16, 14, 152, 64, 77, 56, 111, 161, 217, 22, 120, 16, 0, 152, 109, 183, 65, 171, 109, 248, 107, 68, 49, 17, 233, 28, 138, 224, 159, 187, 176, 114, 109, 202, 60, 217, 208, 70, 213, 217, 80, 65, 216, 222, 122, 147, 134, 45, 212, 199, 78, 128, 115, 116, 166, 145, 215, 212, 54, 52, 92, 121, 28, 51, 35, 237, 65, 53, 64, 109, 167, 2, 26, 42, 168, 2, 221, 189, 245, 71, 165, 30, 229, 99, 250, 157, 246, 80, 159, 137, 4, 45, 225, 161, 247, 62, 215, 137, 184, 138, 198, 236, 139, 205, 89, 33, 215, 3, 196, 232, 235, 234, 16, 134, 173, 205, 254, 162, 85, 137, 230, 124, 85, 162, 151, 241, 109, 78, 101, 47, 8, 120, 234, 2, 191, 214, 63, 141, 76, 137, 109, 85, 24, 130, 119, 93, 232, 186, 96, 246, 39, 156, 148, 52, 92, 232, 98, 59, 117, 84, 125, 101, 4, 208, 34, 42, 191, 88, 199, 213, 61, 160, 55, 166, 124, 223, 255, 63, 105, 246, 150, 92, 108, 31, 248, 127, 40, 173, 144, 34, 79, 81, 103, 33, 164, 206, 139, 84, 229, 19, 103, 223, 38, 253, 40, 201, 194, 213, 249, 3, 139, 39, 40, 168, 62, 191, 36, 50, 247, 154, 238, 229, 122, 20, 175, 158, 65, 209, 22, 94, 63, 50, 46, 253, 22, 27, 95, 77, 18, 162, 234, 179, 201, 127, 34, 233, 185, 150, 10, 5, 159, 124, 117, 67, 159, 4, 187, 121, 234, 43, 166, 63, 22, 195, 183, 211, 213, 232, 207, 129, 11, 52, 174, 113, 70, 11, 247, 48, 210, 113, 238, 7, 75, 10, 75, 191, 40, 223, 221, 162, 52, 95, 185, 42, 235, 218, 178, 66, 89, 48, 21, 143, 66, 170, 35, 124, 238, 178, 105, 169, 136, 80, 235, 136, 214, 48, 137, 117, 61, 74, 157, 139, 115, 204, 5, 142, 17, 61, 28, 119, 151, 212, 204, 125, 244, 51, 108, 24, 249, 31, 52, 119, 66, 32, 48, 188, 179, 50, 37, 140, 145, 67, 240, 39, 231, 110, 7, 78, 106, 26, 100, 138, 10, 211, 132, 101, 249, 132, 63, 71, 1, 13, 93, 136, 109, 80, 187, 227, 110, 196, 26, 23, 191, 111, 145, 48, 15, 204, 80, 12, 226, 10, 203, 5, 193, 76, 105, 252, 76, 64, 67, 105, 133, 9, 136, 164, 42, 122, 151, 111, 2, 79, 97, 27, 16, 38, 102, 16, 83, 11, 183, 162, 191, 71, 151, 205, 216, 135, 199, 250, 68, 39, 109, 145, 53, 81, 210, 199, 87, 103, 17, 246, 236, 33, 202, 13, 148, 100, 158, 16, 130, 32, 157, 224, 89, 242, 97, 144, 64, 170, 149, 242, 183, 93, 142, 222, 141, 54, 187, 151, 244, 68, 80, 69, 215, 129, 154, 170, 232, 183, 210, 57, 203, 48, 78, 87, 34, 231, 199, 150, 47, 72, 164, 71, 165, 88, 232, 128, 214, 140, 78, 71, 244, 73, 64, 59, 154, 15, 101, 12, 243, 144, 48, 45, 145, 182, 208, 204, 203, 81, 7, 197, 16, 90, 145 ], } ), ( "A4285295FC7B1A81600062A9605C66F00D6C9793".parse().ok(), Signed { content: BString::from(content.to_vec()), signature: vec![ 194, 193, 148, 4, 1, 1, 8, 0, 62, 22, 33, 4, 164, 40, 82, 149, 252, 123, 26, 129, 96, 0, 98, 169, 96, 92, 102, 240, 13, 108, 151, 147, 5, 2, 99, 157, 151, 212, 32, 28, 100, 101, 98, 105, 97, 110, 45, 114, 101, 108, 101, 97, 115, 101, 64, 108, 105, 115, 116, 115, 46, 100, 101, 98, 105, 97, 110, 46, 111, 114, 103, 0, 10, 9, 16, 96, 92, 102, 240, 13, 108, 151, 147, 195, 169, 15, 254, 46, 140, 202, 93, 155, 234, 96, 138, 35, 33, 103, 131, 69, 42, 252, 36, 117, 116, 27, 242, 103, 77, 57, 217, 111, 218, 56, 236, 91, 19, 90, 109, 192, 3, 222, 139, 48, 139, 34, 74, 27, 164, 171, 41, 60, 204, 141, 188, 231, 27, 40, 154, 131, 117, 38, 40, 58, 122, 152, 57, 173, 172, 130, 221, 165, 91, 138, 23, 120, 128, 135, 11, 116, 175, 78, 40, 117, 71, 142, 52, 102, 128, 215, 157, 225, 218, 110, 101, 188, 188, 227, 73, 116, 123, 38, 230, 2, 117, 227, 58, 26, 160, 174, 137, 16, 110, 37, 95, 37, 139, 57, 205, 14, 177, 183, 135, 95, 157, 124, 208, 19, 8, 245, 255, 255, 113, 89, 220, 95, 160, 117, 135, 127, 82, 126, 239, 83, 113, 80, 221, 65, 213, 154, 95, 207, 138, 216, 253, 255, 152, 208, 127, 42, 152, 123, 114, 186, 238, 189, 131, 58, 97, 34, 78, 88, 186, 90, 28, 80, 152, 155, 193, 248, 30, 86, 180, 88, 40, 22, 216, 15, 91, 120, 101, 123, 197, 3, 241, 118, 227, 155, 121, 121, 207, 167, 220, 116, 207, 201, 2, 4, 43, 41, 132, 155, 3, 133, 136, 74, 42, 200, 90, 81, 226, 116, 234, 237, 202, 111, 80, 188, 241, 231, 124, 171, 30, 152, 156, 239, 215, 54, 58, 120, 114, 244, 16, 184, 166, 204, 13, 121, 37, 218, 228, 253, 173, 254, 152, 239, 214, 117, 94, 113, 141, 158, 96, 192, 213, 120, 1, 185, 15, 240, 5, 104, 149, 254, 44, 46, 202, 150, 47, 92, 47, 51, 150, 241, 126, 179, 228, 167, 32, 70, 38, 117, 156, 139, 98, 121, 34, 179, 158, 240, 0, 156, 128, 166, 36, 111, 126, 115, 65, 235, 75, 126, 248, 16, 43, 150, 173, 162, 177, 86, 97, 169, 244, 188, 35, 2, 5, 45, 221, 47, 243, 182, 212, 220, 179, 146, 73, 172, 146, 146, 112, 167, 242, 48, 155, 244, 109, 62, 162, 17, 206, 105, 205, 93, 81, 70, 235, 79, 160, 191, 51, 124, 30, 168, 60, 92, 9, 245, 57, 232, 112, 27, 177, 124, 16, 42, 204, 51, 21, 207, 95, 86, 5, 74, 70, 15, 85, 204, 186, 78, 43, 214, 184, 52, 61, 142, 38, 6, 235, 194, 254, 120, 168, 12, 250, 115, 173, 19, 79, 197, 93, 85, 138, 176, 79, 166, 18, 194, 221, 232, 235, 218, 127, 198, 198, 148, 182, 208, 29, 151, 0, 221, 121, 192, 44, 147, 119, 74, 27, 68, 234, 142, 148, 216, 64, 75, 131, 208, 233, 250, 129, 179, 116, 70, 65, 130, 145, 85, 89, 53, 102, 224, 123, 145, 194, 190, 158, 85, 174, 151, 66, 229, 145, 34, 9, 213, 192, 12, 88, 34, 82, 15, 175, 129, 184, 245, 203, 85, 90, 148, 245, 63, 81, 68, 8, 87, 11, 23, 185, 94, 96, 138, 222, 24, 111, 222, 163, 169, 28, 69, 137, 117, 8, 32, 96, 22, 17, 124, 163 ], } ) ] ); Ok(()) } #[test] fn test_dash_escape_and_binary_safety() -> Result<()> { let mut buf = vec![]; for x in 0..=255 { buf.push(x); buf.push(b'\n'); } let signed = Signed { content: buf.into(), signature: vec![1], }; let txt = signed.to_clear_signed()?; assert_eq!( txt, b"-----BEGIN PGP SIGNED MESSAGE----- \x00\n\x01\n\x02\n\x03\n\x04\n\x05\n\x06\n\x07\n\x08\n\x09\n\x0a\n\x0b\n\x0c\n\x0d\n\x0e\n\x0f \x10\n\x11\n\x12\n\x13\n\x14\n\x15\n\x16\n\x17\n\x18\n\x19\n\x1a\n\x1b\n\x1c\n\x1d\n\x1e\n\x1f \x20\n\x21\n\x22\n\x23\n\x24\n\x25\n\x26\n\x27\n\x28\n\x29\n\x2a\n\x2b\n\x2c\n\x2d \x2d\n\x2e\n\x2f \x30\n\x31\n\x32\n\x33\n\x34\n\x35\n\x36\n\x37\n\x38\n\x39\n\x3a\n\x3b\n\x3c\n\x3d\n\x3e\n\x3f \x40\n\x41\n\x42\n\x43\n\x44\n\x45\n\x46\n\x47\n\x48\n\x49\n\x4a\n\x4b\n\x4c\n\x4d\n\x4e\n\x4f \x50\n\x51\n\x52\n\x53\n\x54\n\x55\n\x56\n\x57\n\x58\n\x59\n\x5a\n\x5b\n\x5c\n\x5d\n\x5e\n\x5f \x60\n\x61\n\x62\n\x63\n\x64\n\x65\n\x66\n\x67\n\x68\n\x69\n\x6a\n\x6b\n\x6c\n\x6d\n\x6e\n\x6f \x70\n\x71\n\x72\n\x73\n\x74\n\x75\n\x76\n\x77\n\x78\n\x79\n\x7a\n\x7b\n\x7c\n\x7d\n\x7e\n\x7f \x80\n\x81\n\x82\n\x83\n\x84\n\x85\n\x86\n\x87\n\x88\n\x89\n\x8a\n\x8b\n\x8c\n\x8d\n\x8e\n\x8f \x90\n\x91\n\x92\n\x93\n\x94\n\x95\n\x96\n\x97\n\x98\n\x99\n\x9a\n\x9b\n\x9c\n\x9d\n\x9e\n\x9f \xa0\n\xa1\n\xa2\n\xa3\n\xa4\n\xa5\n\xa6\n\xa7\n\xa8\n\xa9\n\xaa\n\xab\n\xac\n\xad\n\xae\n\xaf \xb0\n\xb1\n\xb2\n\xb3\n\xb4\n\xb5\n\xb6\n\xb7\n\xb8\n\xb9\n\xba\n\xbb\n\xbc\n\xbd\n\xbe\n\xbf \xc0\n\xc1\n\xc2\n\xc3\n\xc4\n\xc5\n\xc6\n\xc7\n\xc8\n\xc9\n\xca\n\xcb\n\xcc\n\xcd\n\xce\n\xcf \xd0\n\xd1\n\xd2\n\xd3\n\xd4\n\xd5\n\xd6\n\xd7\n\xd8\n\xd9\n\xda\n\xdb\n\xdc\n\xdd\n\xde\n\xdf \xe0\n\xe1\n\xe2\n\xe3\n\xe4\n\xe5\n\xe6\n\xe7\n\xe8\n\xe9\n\xea\n\xeb\n\xec\n\xed\n\xee\n\xef \xf0\n\xf1\n\xf2\n\xf3\n\xf4\n\xf5\n\xf6\n\xf7\n\xf8\n\xf9\n\xfa\n\xfb\n\xfc\n\xfd\n\xfe\n\xff -----BEGIN PGP SIGNATURE----- AQ== =5yUo -----END PGP SIGNATURE----- " ); let (signed2, _) = Signed::from_bytes(&txt)?; assert_eq!(signed, signed2); Ok(()) } #[test] fn test_release_no_final_newline() -> Result<()> { let content = b"-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Wed, 03 Jul 2024 04:25:50 +0000 Architectures: amd64 Components: main Description: Generated by update-apt script MD5Sum: 367c2064db4d7381ad9c3ebaba5f0900 309659 main/binary-amd64/Packages 2555166c9f8c3fcf263bed1780d3214c 64652 main/binary-amd64/Packages.gz fc7c26c533cff1978147c24aa468000c 57201 main/binary-amd64/Packages.bz2 b342b94b4c37c2c3d7e8ef1d39dac67a 58444 main/binary-amd64/Packages.xz db8aee13877134f794b225cfb7693351 25076 main/Contents-amd64 3b5112b5a0da0fc3e178be1b393ad7b0 2039 main/Contents-amd64.gz 465d036058c655a15adaef094f9286bb 1749 main/Contents-amd64.bz2 7946f3339f79d17faddcaa0203b0f97e 1904 main/Contents-amd64.xz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release 2e9782caa73a260c91ba9bb28a7fb716 84 main/binary-amd64/Release.gz 564810f1411d179c193cc9f28f78c939 101 main/binary-amd64/Release.bz2 c7ddb24e1d0b64ca584392d71403b3cb 128 main/binary-amd64/Release.xz SHA1: 61c7f4e2f521983011f7bfbf487710c2437df3a0 309659 main/binary-amd64/Packages 182b735c97dc4d73a98c736f5a87010a19b69b21 64652 main/binary-amd64/Packages.gz 2b315a75313e08a7147443ecaec2319c58a6e08e 57201 main/binary-amd64/Packages.bz2 fc796ff95f712a82fce57fcacf7906d6f215d075 58444 main/binary-amd64/Packages.xz e19b50fedca995916d7643083134cc7b66ea72c0 25076 main/Contents-amd64 e6f19033bae7266e50dfcb3725de8ed347e88b49 2039 main/Contents-amd64.gz b6de2e9e9445e26ce72f79ce00d86f94b16b07be 1749 main/Contents-amd64.bz2 b58c520d24b6af04a95fc12f560cd05c6864c17c 1904 main/Contents-amd64.xz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release 32230bb251530e6563c378abd4bbf187af5aa904 84 main/binary-amd64/Release.gz 9a096aed53faad9054f79670507cd3da197801a7 101 main/binary-amd64/Release.bz2 ba7c389834035e903744b153a1c54e2dc5966b01 128 main/binary-amd64/Release.xz SHA256: 88730d9436f17ed233d1b92d5f5d9f53b4144ffac2e83bb91f8864c0b55650c0 309659 main/binary-amd64/Packages d8704f58be01ed834143c678d43f1be22b5b768acb747d7aed8f17c9e5eb859e 64652 main/binary-amd64/Packages.gz 907e3769de05e2dd69fb911b45aba8b5404b5b6c10ac1a2a1c845880322f7f1e 57201 main/binary-amd64/Packages.bz2 3be11ada16114f21aef8684b11bf4cdc879ca4602b68056fcba359f8dcb223e6 58444 main/binary-amd64/Packages.xz 94abd755acbd600ae822b26f9ebab2aa0bf23715ab2063a08f8733c51c642957 25076 main/Contents-amd64 1ccf7551453fd411bd815e9cb91292512c46968d880d622297c33d07da2d7ca5 2039 main/Contents-amd64.gz b030dd088aab2ed17e9d8cd545dddb4ae79e5bfa50c2a40e3c2685ee2e8e76d2 1749 main/Contents-amd64.bz2 7d071594d1b3d3df39d2ccd0dd40070102395fbced8d971c51af776e5914a87d 1904 main/Contents-amd64.xz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release 3e263cd1d7393e90f5db0cf5f2f4c82bdea525e3acb119c7aae5d64aac402594 84 main/binary-amd64/Release.gz 2559188d2ba8299dbc8942023ba941d40e71759f678090e944603343fb818ef6 101 main/binary-amd64/Release.bz2 78da08aaa862fcdd4946b033fe22adddd1e57bf0f0a59040cf5381914c7a1cbf 128 main/binary-amd64/Release.xz SHA512: 19e5830781cfdb3a3b606159b94312cbdfed829a5d33990140001f1e0ac5b429b6dae2941be6cc8ee991cd04da993cf3f0d0c729a2e2842c4541bc2a1b51e746 309659 main/binary-amd64/Packages 5e3dac7df6e28bbf026d4ace79626b850d7a583106cbc7e52546da3ed1466df348f52e2f267ef52f8787cb5f99be6b3b54e45490c401482fa8c437806ce52d6c 64652 main/binary-amd64/Packages.gz 7136b4d6986ba6e2e2bcc0a36be6f20d8cd8835e400b9f381c6db34e67f0f7209ab00cfda7d8fa0dc6ac9863b295e6a2eae233aba9b3c5ac0de81cb3284ea707 57201 main/binary-amd64/Packages.bz2 27d8dd4ed7b470cdcb46517954b77aca1e1a8713783d1fa1a1a7f14379ef4509b1b9604e186d16a93e1313d0ed02e5a88f073749f6ef7cc9413f999622c84707 58444 main/binary-amd64/Packages.xz 95f2bdbfac6769737aa51546f83ab4b14c8cf289657e509c004de6c781fc04c7c38f5270c6ac478531a5cd3d8c1b1a834c7dc9dc53ef309f882414b4878853db 25076 main/Contents-amd64 1636d5437c35c1a78d71ab9b38d35c90399110b43d5920ef065a2b433d8013476c184abd3aca87e422b4be12c4db8d877badad581e4ad34c89fdacf7595b1c2e 2039 main/Contents-amd64.gz c2e4c9db2f98bc65ab4d22f6da023c7b2f4c10b013f8e1efbac1d519035c299117a6e1d8a8a37cc8b2f50ef6588b03ccd3f1f587d280fa85696e78b9f62ed65f 1749 main/Contents-amd64.bz2 16134ecd6a8ed69bc74f21a76e029feca04dd57a9eb90b0529d7984073e42db4c9806af5c78bf7746505b1c6d26201a7e8792b2988b9e949c35ee24ec23a2d06 1904 main/Contents-amd64.xz 3bdd91456dd4be348fc772ee4b2bef3b77467c1405b63332e2e531a98c6f44de88b2f3a8b42f28ff0b24f133a8e50e756de1200ba51c7ba74331e3eab136b489 85 main/binary-amd64/Release b4f4204a7587db0a61e4bd6b420091c37b3863a5d5c6ddc5deb699c20036496705cd28f7e6358510ac79c91dab7cec6f39342f0af8e81a7c61559e797edb6971 84 main/binary-amd64/Release.gz 79b5d47081f0425501f3b98536f5174c8e1730f3ac3d466a9773563aab8fc708a613a29f4c028edce95bb45bb73c6176f7b7f669c0bb2cb102baeb87b9badb21 101 main/binary-amd64/Release.bz2 43d6fae55651c3e884a86cc9361e4a930dc001183847a28f436ea420a4385cadebb18c69286e2cd22129260a64f223660852d3eb825c8a3cfe4b9197329617e0 128 main/binary-amd64/Release.xz -----BEGIN PGP SIGNATURE----- wsFzBAEBCAAnBQJmhNLTCRDZgKF0V/b7BhYhBNuja1GB0MgW9jDoidmAoXRX9vsG AAAMPg/+P/QDpcKnVNJ6qTAewL2c6852c8yloZes83wr1hD/cMdOWs7wKUpgZKCm WNG+0GtrE/HeHEWtqxz4yoAbO5ZImoV90a0XviIa76csHOlKULnp+qioi4X90kIX crhKZL7PGXVj4oOXlhO/Qk+25P5x/uKpUGkH9tFVdSORJ2iVHiLUQk5kfBG7VMWv tmiFLCy8a+AXG3S/smMzasZq1ihdqc0pkg8uUr1yxEQR42+0e/BJdjkdZfCFdrb7 LYvmSFLvFI3Aq8bo0Z2kEFe370oa+a3VOdTfEMoTJVnmAJONngpwc/CrRvrEWBVm q58qPcEWrygFqa6Uxo6QqygoFjrhvUvaPpxsRCfbUkeEfDIOmhpq+yY7Xo5niIUZ d71jg+nfd/qh3amvzjTZRQ80F6667y0JoLN9RpjxXZbfeg5rPWWdrU2FaC/cXdaj emLBsCFonme9IzBNXi9VoHkW5RQ8xY0cS0IwfGNoVVWi2FXjoGzdzWHS2qQem7Zo mES/hOg4z5+tyyOkj9hn1xqE2F0zIDrltqK6xY2tnUZiJo9GbSsTQuj826K2FASn n6XHHgZs+FZmCNUSAxzSfM3Y8l55scuKbr7PwhOwLmx2WNVd/RQ8K0VoJAmAnoN5 TQb+9OlSI0ZCZxiegW3IMDL6Qy6u/4nySGfFk21y7t3sc8W0+68= =JjIx -----END PGP SIGNATURE-----"; let (signed, remaining) = Signed::from_bytes(content)?; assert_eq!(remaining, b""); assert_eq!( signed, Signed { content: BString::from(b"Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Wed, 03 Jul 2024 04:25:50 +0000 Architectures: amd64 Components: main Description: Generated by update-apt script MD5Sum: 367c2064db4d7381ad9c3ebaba5f0900 309659 main/binary-amd64/Packages 2555166c9f8c3fcf263bed1780d3214c 64652 main/binary-amd64/Packages.gz fc7c26c533cff1978147c24aa468000c 57201 main/binary-amd64/Packages.bz2 b342b94b4c37c2c3d7e8ef1d39dac67a 58444 main/binary-amd64/Packages.xz db8aee13877134f794b225cfb7693351 25076 main/Contents-amd64 3b5112b5a0da0fc3e178be1b393ad7b0 2039 main/Contents-amd64.gz 465d036058c655a15adaef094f9286bb 1749 main/Contents-amd64.bz2 7946f3339f79d17faddcaa0203b0f97e 1904 main/Contents-amd64.xz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release 2e9782caa73a260c91ba9bb28a7fb716 84 main/binary-amd64/Release.gz 564810f1411d179c193cc9f28f78c939 101 main/binary-amd64/Release.bz2 c7ddb24e1d0b64ca584392d71403b3cb 128 main/binary-amd64/Release.xz SHA1: 61c7f4e2f521983011f7bfbf487710c2437df3a0 309659 main/binary-amd64/Packages 182b735c97dc4d73a98c736f5a87010a19b69b21 64652 main/binary-amd64/Packages.gz 2b315a75313e08a7147443ecaec2319c58a6e08e 57201 main/binary-amd64/Packages.bz2 fc796ff95f712a82fce57fcacf7906d6f215d075 58444 main/binary-amd64/Packages.xz e19b50fedca995916d7643083134cc7b66ea72c0 25076 main/Contents-amd64 e6f19033bae7266e50dfcb3725de8ed347e88b49 2039 main/Contents-amd64.gz b6de2e9e9445e26ce72f79ce00d86f94b16b07be 1749 main/Contents-amd64.bz2 b58c520d24b6af04a95fc12f560cd05c6864c17c 1904 main/Contents-amd64.xz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release 32230bb251530e6563c378abd4bbf187af5aa904 84 main/binary-amd64/Release.gz 9a096aed53faad9054f79670507cd3da197801a7 101 main/binary-amd64/Release.bz2 ba7c389834035e903744b153a1c54e2dc5966b01 128 main/binary-amd64/Release.xz SHA256: 88730d9436f17ed233d1b92d5f5d9f53b4144ffac2e83bb91f8864c0b55650c0 309659 main/binary-amd64/Packages d8704f58be01ed834143c678d43f1be22b5b768acb747d7aed8f17c9e5eb859e 64652 main/binary-amd64/Packages.gz 907e3769de05e2dd69fb911b45aba8b5404b5b6c10ac1a2a1c845880322f7f1e 57201 main/binary-amd64/Packages.bz2 3be11ada16114f21aef8684b11bf4cdc879ca4602b68056fcba359f8dcb223e6 58444 main/binary-amd64/Packages.xz 94abd755acbd600ae822b26f9ebab2aa0bf23715ab2063a08f8733c51c642957 25076 main/Contents-amd64 1ccf7551453fd411bd815e9cb91292512c46968d880d622297c33d07da2d7ca5 2039 main/Contents-amd64.gz b030dd088aab2ed17e9d8cd545dddb4ae79e5bfa50c2a40e3c2685ee2e8e76d2 1749 main/Contents-amd64.bz2 7d071594d1b3d3df39d2ccd0dd40070102395fbced8d971c51af776e5914a87d 1904 main/Contents-amd64.xz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release 3e263cd1d7393e90f5db0cf5f2f4c82bdea525e3acb119c7aae5d64aac402594 84 main/binary-amd64/Release.gz 2559188d2ba8299dbc8942023ba941d40e71759f678090e944603343fb818ef6 101 main/binary-amd64/Release.bz2 78da08aaa862fcdd4946b033fe22adddd1e57bf0f0a59040cf5381914c7a1cbf 128 main/binary-amd64/Release.xz SHA512: 19e5830781cfdb3a3b606159b94312cbdfed829a5d33990140001f1e0ac5b429b6dae2941be6cc8ee991cd04da993cf3f0d0c729a2e2842c4541bc2a1b51e746 309659 main/binary-amd64/Packages 5e3dac7df6e28bbf026d4ace79626b850d7a583106cbc7e52546da3ed1466df348f52e2f267ef52f8787cb5f99be6b3b54e45490c401482fa8c437806ce52d6c 64652 main/binary-amd64/Packages.gz 7136b4d6986ba6e2e2bcc0a36be6f20d8cd8835e400b9f381c6db34e67f0f7209ab00cfda7d8fa0dc6ac9863b295e6a2eae233aba9b3c5ac0de81cb3284ea707 57201 main/binary-amd64/Packages.bz2 27d8dd4ed7b470cdcb46517954b77aca1e1a8713783d1fa1a1a7f14379ef4509b1b9604e186d16a93e1313d0ed02e5a88f073749f6ef7cc9413f999622c84707 58444 main/binary-amd64/Packages.xz 95f2bdbfac6769737aa51546f83ab4b14c8cf289657e509c004de6c781fc04c7c38f5270c6ac478531a5cd3d8c1b1a834c7dc9dc53ef309f882414b4878853db 25076 main/Contents-amd64 1636d5437c35c1a78d71ab9b38d35c90399110b43d5920ef065a2b433d8013476c184abd3aca87e422b4be12c4db8d877badad581e4ad34c89fdacf7595b1c2e 2039 main/Contents-amd64.gz c2e4c9db2f98bc65ab4d22f6da023c7b2f4c10b013f8e1efbac1d519035c299117a6e1d8a8a37cc8b2f50ef6588b03ccd3f1f587d280fa85696e78b9f62ed65f 1749 main/Contents-amd64.bz2 16134ecd6a8ed69bc74f21a76e029feca04dd57a9eb90b0529d7984073e42db4c9806af5c78bf7746505b1c6d26201a7e8792b2988b9e949c35ee24ec23a2d06 1904 main/Contents-amd64.xz 3bdd91456dd4be348fc772ee4b2bef3b77467c1405b63332e2e531a98c6f44de88b2f3a8b42f28ff0b24f133a8e50e756de1200ba51c7ba74331e3eab136b489 85 main/binary-amd64/Release b4f4204a7587db0a61e4bd6b420091c37b3863a5d5c6ddc5deb699c20036496705cd28f7e6358510ac79c91dab7cec6f39342f0af8e81a7c61559e797edb6971 84 main/binary-amd64/Release.gz 79b5d47081f0425501f3b98536f5174c8e1730f3ac3d466a9773563aab8fc708a613a29f4c028edce95bb45bb73c6176f7b7f669c0bb2cb102baeb87b9badb21 101 main/binary-amd64/Release.bz2 43d6fae55651c3e884a86cc9361e4a930dc001183847a28f436ea420a4385cadebb18c69286e2cd22129260a64f223660852d3eb825c8a3cfe4b9197329617e0 128 main/binary-amd64/Release.xz "), signature: vec![ 194, 193, 115, 4, 1, 1, 8, 0, 39, 5, 2, 102, 132, 210, 211, 9, 16, 217, 128, 161, 116, 87, 246, 251, 6, 22, 33, 4, 219, 163, 107, 81, 129, 208, 200, 22, 246, 48, 232, 137, 217, 128, 161, 116, 87, 246, 251, 6, 0, 0, 12, 62, 15, 254, 63, 244, 3, 165, 194, 167, 84, 210, 122, 169, 48, 30, 192, 189, 156, 235, 206, 118, 115, 204, 165, 161, 151, 172, 243, 124, 43, 214, 16, 255, 112, 199, 78, 90, 206, 240, 41, 74, 96, 100, 160, 166, 88, 209, 190, 208, 107, 107, 19, 241, 222, 28, 69, 173, 171, 28, 248, 202, 128, 27, 59, 150, 72, 154, 133, 125, 209, 173, 23, 190, 34, 26, 239, 167, 44, 28, 233, 74, 80, 185, 233, 250, 168, 168, 139, 133, 253, 210, 66, 23, 114, 184, 74, 100, 190, 207, 25, 117, 99, 226, 131, 151, 150, 19, 191, 66, 79, 182, 228, 254, 113, 254, 226, 169, 80, 105, 7, 246, 209, 85, 117, 35, 145, 39, 104, 149, 30, 34, 212, 66, 78, 100, 124, 17, 187, 84, 197, 175, 182, 104, 133, 44, 44, 188, 107, 224, 23, 27, 116, 191, 178, 99, 51, 106, 198, 106, 214, 40, 93, 169, 205, 41, 146, 15, 46, 82, 189, 114, 196, 68, 17, 227, 111, 180, 123, 240, 73, 118, 57, 29, 101, 240, 133, 118, 182, 251, 45, 139, 230, 72, 82, 239, 20, 141, 192, 171, 198, 232, 209, 157, 164, 16, 87, 183, 239, 74, 26, 249, 173, 213, 57, 212, 223, 16, 202, 19, 37, 89, 230, 0, 147, 141, 158, 10, 112, 115, 240, 171, 70, 250, 196, 88, 21, 102, 171, 159, 42, 61, 193, 22, 175, 40, 5, 169, 174, 148, 198, 142, 144, 171, 40, 40, 22, 58, 225, 189, 75, 218, 62, 156, 108, 68, 39, 219, 82, 71, 132, 124, 50, 14, 154, 26, 106, 251, 38, 59, 94, 142, 103, 136, 133, 25, 119, 189, 99, 131, 233, 223, 119, 250, 161, 221, 169, 175, 206, 52, 217, 69, 15, 52, 23, 174, 186, 239, 45, 9, 160, 179, 125, 70, 152, 241, 93, 150, 223, 122, 14, 107, 61, 101, 157, 173, 77, 133, 104, 47, 220, 93, 214, 163, 122, 98, 193, 176, 33, 104, 158, 103, 189, 35, 48, 77, 94, 47, 85, 160, 121, 22, 229, 20, 60, 197, 141, 28, 75, 66, 48, 124, 99, 104, 85, 85, 162, 216, 85, 227, 160, 108, 221, 205, 97, 210, 218, 164, 30, 155, 182, 104, 152, 68, 191, 132, 232, 56, 207, 159, 173, 203, 35, 164, 143, 216, 103, 215, 26, 132, 216, 93, 51, 32, 58, 229, 182, 162, 186, 197, 141, 173, 157, 70, 98, 38, 143, 70, 109, 43, 19, 66, 232, 252, 219, 162, 182, 20, 4, 167, 159, 165, 199, 30, 6, 108, 248, 86, 102, 8, 213, 18, 3, 28, 210, 124, 205, 216, 242, 94, 121, 177, 203, 138, 110, 190, 207, 194, 19, 176, 46, 108, 118, 88, 213, 93, 253, 20, 60, 43, 69, 104, 36, 9, 128, 158, 131, 121, 77, 6, 254, 244, 233, 82, 35, 70, 66, 103, 24, 158, 129, 109, 200, 48, 50, 250, 67, 46, 174, 255, 137, 242, 72, 103, 197, 147, 109, 114, 238, 221, 236, 115, 197, 180, 251, 175 ], } ); Ok(()) } #[tokio::test] async fn test_from_reader() -> Result<()> { let canonical = Signed::from_reader(&mut &IN_RELEASE[..]).await?; let canonical = canonical.to_clear_signed()?; assert_eq!(BStr::new(&canonical), BStr::new(IN_RELEASE)); Ok(()) } } apt-swarm-0.5.1/src/sync.rs000064400000000000000000001064631046102023000136650ustar 00000000000000use crate::db::{Database, DatabaseClient}; use crate::errors::*; use crate::keyring::Keyring; use crate::p2p::peerdb; use crate::signed::Signed; use bstr::BStr; use futures::StreamExt; use indexmap::{IndexMap, IndexSet}; use sequoia_openpgp::Fingerprint; use sha2::{Digest, Sha256}; use std::borrow::Cow; use std::collections::{BTreeMap, VecDeque}; use std::fmt; use std::str; use std::str::FromStr; use std::time::Duration; use tokio::io; use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use tokio::time; pub const MAX_LINE_LENGTH: u64 = 512; pub const SYNC_INDEX_TIMEOUT: Duration = Duration::from_secs(120); pub const SYNC_READ_TIMEOUT: Duration = Duration::from_secs(30); // We expect entries from 0-f pub const BATCH_INDEX_MAX_SIZE: usize = 16; /// If the number of entries is greater than zero, but <= this threshold, send a dump instead of an index pub const SPILL_THRESHOLD: usize = 1; /// Stop announcing peers we couldn't handshake with recently const PEX_MAX_SUCCESS_AGE: Duration = Duration::from_secs(3600 * 24 * 5); #[derive(Debug, Clone)] pub enum Query { Tree(TreeQuery), Pex, Unknown(String), } impl Query { pub fn from_bytes(bytes: &[u8]) -> Result { let line = bytes.strip_suffix(b"\n").unwrap_or(bytes); let line = str::from_utf8(line).context("Query contains invalid utf8")?; let query = line .parse() .with_context(|| anyhow!("Failed to parse input as query: {line:?}"))?; Ok(query) } } impl FromStr for Query { type Err = Error; fn from_str(query: &str) -> Result { if let Some(cmd) = query.strip_prefix("//") { if cmd == "pex" { Ok(Query::Pex) } else { Ok(Query::Unknown(cmd.to_string())) } } else { let query = query .parse() .context("Failed to parse input as tree-query")?; Ok(Query::Tree(query)) } } } #[derive(Debug, Clone)] pub struct TreeQuery { pub fp: Fingerprint, pub hash_algo: String, pub prefix: Option, } impl TreeQuery { pub async fn write_to(&self, mut tx: W) -> Result<()> { let mut out = format!("{:X} {}", self.fp, self.hash_algo); if let Some(prefix) = &self.prefix { out.push(' '); out.push_str(prefix); } out.push('\n'); tx.write_all(out.as_bytes()).await?; Ok(()) } /// Switch to the next shard pub fn increment(&mut self) -> bool { if let Some(prefix) = &mut self.prefix { if prefix.ends_with('f') { prefix.pop(); true } else if let Some(c) = prefix.pop() { let c = match c { '0'..='8' | 'a'..='e' => (c as u8 + 1) as char, '9' => 'a', _ => c, }; prefix.push(c); false } else { // prefix is empty, keyspace has been traversed false } } else { debug!("Peers are already in sync, nothing to do here"); self.prefix = Some(String::new()); false } } /// Traverse into the first entry in this shard pub fn enter(&mut self) { if let Some(prefix) = &mut self.prefix { prefix.push('0'); } else { self.prefix = Some("0".to_string()); } } } impl fmt::Display for TreeQuery { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { let prefix = self.prefix.as_deref().unwrap_or(""); write!(w, "{:X}/{}:{}", self.fp, self.hash_algo, prefix)?; Ok(()) } } impl FromStr for TreeQuery { type Err = Error; fn from_str(s: &str) -> Result { let mut s = s.split(' '); let fp = Fingerprint::from_str(s.next().context("Missing fingerprint")?) .context("Invalid fingerprint")?; let hash_algo = s.next().context("Missing hash algo")?; if hash_algo != "sha256" { bail!("Only sha256 is supported at the moment"); } let prefix = s.next().map(String::from); if let Some(garbage) = s.next() { bail!("Detected trailing data, rejecting as invalid: {garbage:?}"); } Ok(TreeQuery { fp, hash_algo: hash_algo.to_string(), prefix, }) } } #[derive(Debug, Default)] pub struct BatchIndex { index: IndexMap, } impl BatchIndex { pub fn new() -> Self { BatchIndex::default() } pub fn add(&mut self, index: String, prefix: String, count: usize) -> Result<()> { if self.index.len() < BATCH_INDEX_MAX_SIZE { self.index.insert(prefix, (index, count)); Ok(()) } else { bail!( "Batch index is already at max capacity: {:?}", self.index.len() ) } } pub async fn write_to(&self, mut sink: W) -> Result<()> { for (prefix, (index, count)) in &self.index { sink.write_all(format!("{index} {prefix} {count}\n").as_bytes()) .await?; } Ok(()) } pub fn parse_line(&mut self, line: &[u8]) -> Result<()> { let line = line.strip_suffix(b"\n").unwrap_or(line); let line = str::from_utf8(line).context("Response contains invalid utf8")?; let mut s = line.split(' '); let index = s.next().context("Missing index from response")?; let prefix = s.next().context("Failed to get prefix for index")?; let count = s.next().context("Failed to get number of children")?; let count = count .parse() .context("Number of children is not a number")?; self.add(index.to_string(), prefix.to_string(), count) } pub fn get(&self, key: &str) -> Option<&(String, usize)> { self.index.get(key) } pub fn keys(&self) -> indexmap::map::Keys { self.index.keys() } pub fn clear(&mut self) { self.index.clear(); } } pub async fn index_from_scan(db: &Database, query: &TreeQuery) -> Result<(String, usize)> { let prefix = query.to_string(); let mut counter = 0; let mut hasher = Sha256::new(); let stream = db.scan_keys(prefix.as_bytes()); tokio::pin!(stream); while let Some(item) = stream.next().await { let hash = item.context("Failed to read from database (index_from_scan)")?; hasher.update(&hash); hasher.update(b"\n"); counter += 1; } let result = hasher.finalize(); Ok((format!("sha256:{result:x}"), counter)) } pub async fn sync_yield< D: DatabaseClient + Sync + Send, R: AsyncRead + Unpin, W: AsyncWrite + Unpin, >( db: &mut D, peerdb: Option, rx: R, mut tx: W, timeout: Option, ) -> Result<()> { let mut rx = io::BufReader::new(rx); loop { let mut line = Vec::new(); let mut rrx = (&mut rx).take(MAX_LINE_LENGTH); let read = rrx.read_until(b'\n', &mut line); let n = if let Some(timeout) = timeout { if let Ok(n) = time::timeout(timeout, read).await { n } else { break; } } else { read.await }?; if n == 0 { break; } if !line.ends_with(b"\n") { bail!( "Client sent invalid request, exceeding size limit: {:?}", BStr::new(&line) ); } let query = Query::from_bytes(&line)?; trace!("Received query: {:?}", query); match query { Query::Tree(mut query) => { let (index, total) = db.batch_index_from_scan(&mut query).await?; if total > 0 && total <= SPILL_THRESHOLD { let prefix = query.to_string(); for (hash, data) in db.spill(prefix.as_bytes()).await? { trace!("Sending data packet to client: {:?}", BStr::new(&hash)); tx.write_all(format!(":{:x}\n", data.len()).as_bytes()) .await?; tx.write_all(&data).await?; } tx.write_all(b":0\n").await?; } else { index.write_to(&mut tx).await?; tx.write_all(b"\n").await?; } } Query::Pex => { let mut buf = String::new(); if let Some(peerdb) = &peerdb { for addr in peerdb.sample(Some(PEX_MAX_SUCCESS_AGE)).await? { buf += &format!("{addr}\n"); } } tx.write_all(format!(":{}\n", buf.len()).as_bytes()).await?; tx.write_all(buf.as_bytes()).await?; } Query::Unknown(data) => { debug!("Received unknown command from network: {data:?}"); tx.write_all(b":0\n").await?; } } } Ok(()) } #[derive(Debug, Default)] pub struct SyncQueue { queues: BTreeMap>>, } impl SyncQueue { pub fn push(&mut self, key: Option) { let len = key.as_ref().map(|s| s.len()).unwrap_or(0); let queue = self.queues.entry(len).or_default(); queue.push_back(key); } pub fn pop_next(&mut self) -> Option> { loop { let mut entry = self.queues.last_entry()?; let queue = entry.get_mut(); if let Some(item) = queue.pop_front() { return Some(item); } else { entry.remove_entry(); } } } } pub async fn sync_pull_key< D: DatabaseClient + Sync + Send, R: AsyncRead + Unpin, W: AsyncWrite + Unpin, >( db: &mut D, keyring: &Keyring, fp: &Fingerprint, dry_run: bool, mut tx: W, rx: &mut io::BufReader, ) -> Result<()> { let mut query = TreeQuery { fp: fp.clone(), hash_algo: "sha256".to_string(), prefix: None, }; let mut queue = SyncQueue::default(); queue.push(None); while let Some(item) = queue.pop_next() { query.prefix = item; info!("Requesting index for: {:?}", query.to_string()); query.write_to(&mut tx).await?; let (our_index, _our_count) = db.batch_index_from_scan(&mut query).await?; trace!("Our index: {our_index:?}"); let mut line = Vec::new(); let mut their_index = BatchIndex::new(); loop { line.clear(); let mut rrx = rx.take(MAX_LINE_LENGTH); let read = rrx.read_until(b'\n', &mut line); let n = time::timeout(SYNC_INDEX_TIMEOUT, read) .await .context("Request for index timed out")? .context("Failed to receive response from peer")?; if n == 0 { bail!("Reached unexpected eof while enumerating service"); } if !line.ends_with(b"\n") { bail!( "Server sent invalid line, exceeding size limit: {:?}", BStr::new(&line) ); } if line == b"\n" { let keys = their_index .keys() .chain(our_index.keys()) .collect::>(); for key in keys { match (their_index.get(key), our_index.get(key)) { (Some(theirs), Some(ours)) => { trace!("Comparing index shards for key={key:?}, theirs={theirs:?}, ours={ours:?}"); if theirs.1 == 0 { trace!( "No children in this shard (key={key:?}), moving to next one" ); } else if theirs == ours { trace!("These shards are already in sync (key={key:?}), moving to next one"); } else { trace!("Data to be found here (key={key:?}), trying to enumerate"); queue.push(Some(key.to_owned())); } } _ => bail!("Some index shards are omitted, this is currently unsupported"), } } their_index.clear(); break; } else if let Some(line) = line.strip_prefix(b":") { let line = line.strip_suffix(b"\n").unwrap_or(line); let line = str::from_utf8(line).context("Length tag has invalid utf8")?; trace!("Received len tag: {:?}", line); let len = usize::from_str_radix(line, 16) .with_context(|| anyhow!("Length tag is invalid number: {line:?}"))?; if len == 0 { trace!("Received all releases from shard, moving to next one"); while query.increment() { trace!("Reached last entry in shard, returning to parent"); } break; } // TODO: check this tag doesn't OOM us info!("Reading data packet from remote: {len:?} bytes"); let mut remaining = len; let mut buf = vec![0u8; len]; while remaining > 0 { let read = rx.read(&mut buf[len - remaining..]); let n = time::timeout(SYNC_READ_TIMEOUT, read) .await .context("Read from remote timed out")? .context("Failed to receive data from peer")?; if n == 0 { bail!("Unexpected end of file"); } remaining -= n; trace!("Read {}/{} bytes from remote", len - remaining, len); } trace!("Finished reading data packet: {:?}", buf.len()); let mut bytes = &buf[..]; while !bytes.is_empty() { let (signed, remaining) = Signed::from_bytes(bytes).context("Failed to parse release file")?; for (fp, variant) in signed.canonicalize(Some(keyring))? { let fp = fp.context( "Signature can't be imported because the signature is unverified", )?; if dry_run { debug!("Skipping insert due to dry-run"); } else { db.add_release(&fp, &variant).await?; } } bytes = remaining; } } else { their_index .parse_line(&line) .with_context(|| anyhow!("Failed to parse line of batch index: {line:?}"))?; } } } Ok(()) } pub async fn sync_pull< D: DatabaseClient + Sync + Send, R: AsyncRead + Unpin, W: AsyncWrite + Unpin, >( db: &mut D, keyring: &Keyring, selected_keys: &[Fingerprint], dry_run: bool, mut tx: W, rx: R, ) -> Result<()> { let selected_keys = if !selected_keys.is_empty() { Cow::Borrowed(selected_keys) } else { Cow::Owned(keyring.all_fingerprints()) }; let mut rx = io::BufReader::new(rx); for fp in selected_keys.iter() { sync_pull_key(db, keyring, fp, dry_run, &mut tx, &mut rx).await?; } Ok(()) } #[cfg(test)] mod tests { use super::*; use crate::db::AccessMode; use futures::TryStreamExt; fn init() { let _ = env_logger::builder().is_test(true).try_init(); } async fn open_temp_dbs() -> Result<(tempfile::TempDir, Database, Database)> { let dir = tempfile::tempdir()?; let db_a = Database::open_at(dir.path().join("a"), AccessMode::Exclusive).await?; let db_b = Database::open_at(dir.path().join("b"), AccessMode::Exclusive).await?; Ok((dir, db_a, db_b)) } async fn run_sync(keyring: &Keyring, db_a: &mut Database, db_b: &mut Database) -> Result<()> { let (client, server) = tokio::io::duplex(64); let (client_rx, client_tx) = tokio::io::split(client); let (server_rx, server_tx) = tokio::io::split(server); let task_yield = sync_yield(db_a, None, server_rx, server_tx, None); let task_pull = sync_pull(db_b, keyring, &[], false, client_tx, client_rx); tokio::select! { ret = task_pull => ret?, ret = task_yield => bail!("Yield task was not expected to return: {ret:?}"), } Ok(()) } #[tokio::test] async fn test_sync_both_empty() -> Result<()> { init(); let keyring = Keyring::new(include_bytes!("../contrib/signal-desktop-keyring.gpg")).unwrap(); let (_, mut db_a, mut db_b) = open_temp_dbs().await.unwrap(); run_sync(&keyring, &mut db_a, &mut db_b).await.unwrap(); Ok(()) } #[tokio::test] async fn test_sync_full() -> Result<()> { init(); let keyring = Keyring::new(include_bytes!("../contrib/signal-desktop-keyring.gpg")).unwrap(); let (_, mut db_a, mut db_b) = open_temp_dbs().await.unwrap(); let data = [ b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Thu, 23 Feb 2023 01:55:04 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: cdb20787f1556bb38ae3b6017ef51327 132984 main/binary-amd64/Packages 001fc41d6c21eb85a43a13133584cbae 21567 main/binary-amd64/Packages.gz 3fb4f1a0169c3b2fff2c43c2a2277b51 17923 main/binary-amd64/Packages.bz2 c911b1bc4adf556f6fbd17c0c9cd8315 4794 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release SHA1: 455673b692a697ad3ada91a875096365f8da1524 132984 main/binary-amd64/Packages e6a940039dcfc7f93f4a5501f15e75d1427b9464 21567 main/binary-amd64/Packages.gz b8447294816bb063c10d0ba35f48dd5d1980f795 17923 main/binary-amd64/Packages.bz2 b6fd643edc8846c0914b44f3182dfc086877d944 4794 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release SHA256: 989c22244106e44d789400d4da33d2ed64228ce94f48d1c2c37493118c992384 132984 main/binary-amd64/Packages c46198172d00d4e01388832b61186a888da47e2c119c1e9dd7378fea206b1237 21567 main/binary-amd64/Packages.gz b368e24d5c137448095f8940e3b371bff83e3e56159df6c58d4be83732a85554 17923 main/binary-amd64/Packages.bz2 bb347cbc00e02d73fef513965f1cd9f9e73100cd34097c43fdd1414668ec8ed8 4794 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release -----BEGIN PGP SIGNATURE----- wsFcBAEBCAAGBQJj9sd6AAoJENmAoXRX9vsGOQ0P/3S63ctKl7QyxmRQ4UVJl70S hTxA90FbWp236nrEWw4EO/eVWiR/VbgFPacp/dyBpSmtTFl5cpOeyf2SYj5qfg5L cemYgUbaxRl+PBFGm7A14y82Ym0MUzF9cNWVK8bDXH9BKSljKKerXr4giOwjTkgh z2LoLxnrbhGkIWnSNiT0YvQrkxkSC5BjOInRiy/4Dr7LFAX/7KBzyPVwiDPxWQca dwtmI6EoZQP+zHDTR6RwnYOB7oME8aYIruwF9Vhu/unfdC4LpbNJDGL7VwQKUp8h ICupSwnRmHPV2raNBq58K6OunGvFO0oFaYUIQqbvGzu/5859YWhrdd7gBd9Fj4zI Ff7fHC+ZigCNCk7op4LykJ/3uJF8NvFlNxiagO+1tRko3V4tNbeSrXEKDhr5RQJz p/VdL1TXI/pVIobxbF5D/Lo8dCs5LjJsJ5rFlPgzjlREFn0hwKcDwB7M+rbPhuHV 1R3lgdhW01ZghwOdTMiX1cShQwE7bvGtskn2WIHyIhEawpotGNpBFG2K5TdxfXA1 m+wu4PLxfxOSb+VoQlH1enyDcR7m7XNtt692l++6nw3rq6Wv2zNc9DHRE+HNavJg zwlfH3L9OOoGfPMfRxrKqFzcob2gnKjptlHt3XpUx5ZwS4hcKB2lETT9ORVxe1NI rK5KKL67o5aLviVqo98l =MI63 -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Wed, 15 Feb 2023 23:18:08 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: bea5a0f7c99209504f22d8faf10125fd 132287 main/binary-amd64/Packages 1aa4c130945a3a076a9f16546ca17a83 21467 main/binary-amd64/Packages.gz f18c7f0779161104fed2aec72d9a44e2 17922 main/binary-amd64/Packages.bz2 fdb168fb0b8f575585d917ca0ffd98bb 4783 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release SHA1: d01c164d99cf7c867b5f115770f58e4916d7a15f 132287 main/binary-amd64/Packages 41e78c4c558567f4936d9952eb928a32911cc56c 21467 main/binary-amd64/Packages.gz 8837bf2f3e2bad7c73712d003c1510c6171c53ee 17922 main/binary-amd64/Packages.bz2 e800a4c83e8d9ef564f5869ad838962550799c5e 4783 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release SHA256: 9f9178b66c4d1d31d7b2b741f0835c2140552cac68861beaf2ecc55f0364c620 132287 main/binary-amd64/Packages 57386742060a0913236bafd5e8eb3b3334284e0d2ab8362a7c22c78175e9d89b 21467 main/binary-amd64/Packages.gz ec097b64b5e3a39760a9b5ea6b02e91d0401994464dd0ce3de2a0a26a62230e2 17922 main/binary-amd64/Packages.bz2 e04d5fd71915c3003d55f3927e5af71a4831e30ffbb0efec6dceb36cd1b054fa 4783 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release -----BEGIN PGP SIGNATURE----- wsFcBAABCAAGBQJj7WgwAAoJENmAoXRX9vsG69AQAJmvducnhHqCXQIsqjXrDMjU QUAw56MRunn7rHTFpJY0ZPLgQ5gVBibouNZ9x78wuJ784Sl+MIHC7RWdQYBEbWQ5 haKjiI00BzDeXx4sUet1E+Ce5dhjK/UvoZIOy+ed5nv/HM7QFrvoxdADSDnYGy2o djFUVWR5kzkb5Tv7bcjJQWWf6JvY1Z12CgsG85ECYv2PE+tGgQjSwbxRDvFFzY1O Xy1EkjT+YDG6hy5CiKSZL7qPsjsLHeuRvat3oSlBWiFRnSuLOlsDozqzYMFqNx93 GPQiFNiYEmkxDxiKLOcds7+Plz2FjQdQwv2msllJ4jA9PxYRiEbfH14/ELk+/snE 66XID9dv91JbrwaI3NOoJZZmN+QYZ7WaAj3Uxl3cYnCGuIIt6z4KB2CYeyRa3f3K HbPq0mBchPPmavaQEfaNDQ+dzMuazR0VMoKfHGEp44r+XU+JH/lNzlxgQEMgVv43 0B++zb4MYgheGUhu7Xdgd6XSQdZGxt4GieXLwIAXA0nmAFlZB7EAJcyHqz0hVo6m Q/m8Ja8hBw6lmyM5uCduF61BhnQDfuDQetLgGzrvOp3m2qfTag3QGtEijwhH8L2O 3xuMqMjtJutTa557go0p+PLjAhMVQ0S7z+3aLn/368qnqlxSflDCPe4GMcaXmOCz RdMJMk9txqB8GM5F2sO3 =gtrA -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Fri, 10 Feb 2023 21:24:49 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: 1044a9316b629fb7ea4b964ecaf1ccf3 21255 main/binary-amd64/Packages.gz 6ee4dcbdb0c0e98e416b94f542f6cc1b 17584 main/binary-amd64/Packages.bz2 fdb168fb0b8f575585d917ca0ffd98bb 4783 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release b2f1f73fabd4acfaca43d05bee1debca 130864 main/binary-amd64/Packages SHA1: 1bcb7cd08c94a3519b2dce77f3f5f5e16c312067 21255 main/binary-amd64/Packages.gz 61c0f6b35c7bd3a5f59094511ccd593dcb2b8c96 17584 main/binary-amd64/Packages.bz2 e800a4c83e8d9ef564f5869ad838962550799c5e 4783 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release 4a7c86cb1c0caa36c92e1af844ebf0b7e2bf4cea 130864 main/binary-amd64/Packages SHA256: 481c1bf74f609fbf71eed01da98a05cbe884acc2efd6d0e2c1c65f9e72ddc2e6 21255 main/binary-amd64/Packages.gz d9f8cc2cc5b2aa854c509caf96d9e1457e6cb0fd55597ac49408a96afb8a727b 17584 main/binary-amd64/Packages.bz2 e04d5fd71915c3003d55f3927e5af71a4831e30ffbb0efec6dceb36cd1b054fa 4783 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release d0bec4d8f926383f3d61dc79b8d5d352f71adcf8befb59e8e02aeabe8c19eeba 130864 main/binary-amd64/Packages -----BEGIN PGP SIGNATURE----- wsFcBAEBCAAGBQJj5rYjAAoJENmAoXRX9vsG3wUP/2X7ufCo5nJkyHhzOtTEI4Pq rz6P94r2S/OA7v99mVkKNyOYZ8hKMNccYumvkWaXBF+WkLemCPeJxaBbRUrulu3c GXNPHht8dusQYIxS2VQVYbHgXfwQ+Y3+P1wVLPNT+9Ka0POkUT4YiM1G8Zx3fwTq zUeCpV1TKgkrVQ4CF5DX8i9tcVmYUq8B+BouwQAFJxElM1cuYqGybG19H/od77nH tkv3n43P0TCZ9KR48ZXWXF+6v26SRse2YkergbNOtJwRfdMHzvc8d/nb7T/Iv3jM WmqUs6Ob4EioUTWYwi2H3y+LnzAPeSVEklfCS61LzlyFGelpxHGuTjaaMtCI2Bkb f3XyNjeVwUYmnGWrBMCI38CUnY0J0oXLrVUxYZoT0O9SSO2bpql64T2Flqn10Djk W8j7V9a5gNO69PkNEHWUylwolFvF/H8Zmc6QZbnnbFSpC4pMEeRhoI1v1CqPSMn8 APOGWa1xHN9hj9g4AZfXvO56BDveo9lbNOmFs2EAmBEEj2hCiroRtuCxxDmwerq3 MLtCJIkir3JdbefexXcbIoP5+tjl573nvKU+Kb4KhCJTBDEY6+6qZKTSBDESKTvq T2L60YwfXZsj6WCS9roTz9llmze3YjURbHNZpf4BO3zONwNNeqFZw3qYWNCyzRS+ R4AjBHbzlyIGpU5BGNn3 =KMXz -----END PGP SIGNATURE----- " ]; for data in data { let (signed, _) = Signed::from_bytes(data).unwrap(); db_a.add_release( &"DBA36B5181D0C816F630E889D980A17457F6FB06".parse()?, &signed, ) .await .unwrap(); } let keys_a = db_a.scan_keys(b"").try_collect::>().await.unwrap(); let keys_b = db_b.scan_keys(b"").try_collect::>().await.unwrap(); assert_eq!(keys_a.len(), 3); assert_eq!(keys_b.len(), 0); run_sync(&keyring, &mut db_a, &mut db_b).await.unwrap(); let keys_a = db_a.scan_keys(b"").try_collect::>().await.unwrap(); let keys_b = db_b.scan_keys(b"").try_collect::>().await.unwrap(); assert_eq!(keys_a.len(), 3); assert_eq!(keys_b.len(), 3); Ok(()) } #[tokio::test] async fn test_sync_from_partial() -> Result<()> { init(); let keyring = Keyring::new(include_bytes!("../contrib/signal-desktop-keyring.gpg")).unwrap(); let (_, mut db_a, mut db_b) = open_temp_dbs().await.unwrap(); let data = [ b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Thu, 23 Feb 2023 01:55:04 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: cdb20787f1556bb38ae3b6017ef51327 132984 main/binary-amd64/Packages 001fc41d6c21eb85a43a13133584cbae 21567 main/binary-amd64/Packages.gz 3fb4f1a0169c3b2fff2c43c2a2277b51 17923 main/binary-amd64/Packages.bz2 c911b1bc4adf556f6fbd17c0c9cd8315 4794 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release SHA1: 455673b692a697ad3ada91a875096365f8da1524 132984 main/binary-amd64/Packages e6a940039dcfc7f93f4a5501f15e75d1427b9464 21567 main/binary-amd64/Packages.gz b8447294816bb063c10d0ba35f48dd5d1980f795 17923 main/binary-amd64/Packages.bz2 b6fd643edc8846c0914b44f3182dfc086877d944 4794 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release SHA256: 989c22244106e44d789400d4da33d2ed64228ce94f48d1c2c37493118c992384 132984 main/binary-amd64/Packages c46198172d00d4e01388832b61186a888da47e2c119c1e9dd7378fea206b1237 21567 main/binary-amd64/Packages.gz b368e24d5c137448095f8940e3b371bff83e3e56159df6c58d4be83732a85554 17923 main/binary-amd64/Packages.bz2 bb347cbc00e02d73fef513965f1cd9f9e73100cd34097c43fdd1414668ec8ed8 4794 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release -----BEGIN PGP SIGNATURE----- wsFcBAEBCAAGBQJj9sd6AAoJENmAoXRX9vsGOQ0P/3S63ctKl7QyxmRQ4UVJl70S hTxA90FbWp236nrEWw4EO/eVWiR/VbgFPacp/dyBpSmtTFl5cpOeyf2SYj5qfg5L cemYgUbaxRl+PBFGm7A14y82Ym0MUzF9cNWVK8bDXH9BKSljKKerXr4giOwjTkgh z2LoLxnrbhGkIWnSNiT0YvQrkxkSC5BjOInRiy/4Dr7LFAX/7KBzyPVwiDPxWQca dwtmI6EoZQP+zHDTR6RwnYOB7oME8aYIruwF9Vhu/unfdC4LpbNJDGL7VwQKUp8h ICupSwnRmHPV2raNBq58K6OunGvFO0oFaYUIQqbvGzu/5859YWhrdd7gBd9Fj4zI Ff7fHC+ZigCNCk7op4LykJ/3uJF8NvFlNxiagO+1tRko3V4tNbeSrXEKDhr5RQJz p/VdL1TXI/pVIobxbF5D/Lo8dCs5LjJsJ5rFlPgzjlREFn0hwKcDwB7M+rbPhuHV 1R3lgdhW01ZghwOdTMiX1cShQwE7bvGtskn2WIHyIhEawpotGNpBFG2K5TdxfXA1 m+wu4PLxfxOSb+VoQlH1enyDcR7m7XNtt692l++6nw3rq6Wv2zNc9DHRE+HNavJg zwlfH3L9OOoGfPMfRxrKqFzcob2gnKjptlHt3XpUx5ZwS4hcKB2lETT9ORVxe1NI rK5KKL67o5aLviVqo98l =MI63 -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Wed, 15 Feb 2023 23:18:08 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: bea5a0f7c99209504f22d8faf10125fd 132287 main/binary-amd64/Packages 1aa4c130945a3a076a9f16546ca17a83 21467 main/binary-amd64/Packages.gz f18c7f0779161104fed2aec72d9a44e2 17922 main/binary-amd64/Packages.bz2 fdb168fb0b8f575585d917ca0ffd98bb 4783 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release SHA1: d01c164d99cf7c867b5f115770f58e4916d7a15f 132287 main/binary-amd64/Packages 41e78c4c558567f4936d9952eb928a32911cc56c 21467 main/binary-amd64/Packages.gz 8837bf2f3e2bad7c73712d003c1510c6171c53ee 17922 main/binary-amd64/Packages.bz2 e800a4c83e8d9ef564f5869ad838962550799c5e 4783 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release SHA256: 9f9178b66c4d1d31d7b2b741f0835c2140552cac68861beaf2ecc55f0364c620 132287 main/binary-amd64/Packages 57386742060a0913236bafd5e8eb3b3334284e0d2ab8362a7c22c78175e9d89b 21467 main/binary-amd64/Packages.gz ec097b64b5e3a39760a9b5ea6b02e91d0401994464dd0ce3de2a0a26a62230e2 17922 main/binary-amd64/Packages.bz2 e04d5fd71915c3003d55f3927e5af71a4831e30ffbb0efec6dceb36cd1b054fa 4783 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release -----BEGIN PGP SIGNATURE----- wsFcBAABCAAGBQJj7WgwAAoJENmAoXRX9vsG69AQAJmvducnhHqCXQIsqjXrDMjU QUAw56MRunn7rHTFpJY0ZPLgQ5gVBibouNZ9x78wuJ784Sl+MIHC7RWdQYBEbWQ5 haKjiI00BzDeXx4sUet1E+Ce5dhjK/UvoZIOy+ed5nv/HM7QFrvoxdADSDnYGy2o djFUVWR5kzkb5Tv7bcjJQWWf6JvY1Z12CgsG85ECYv2PE+tGgQjSwbxRDvFFzY1O Xy1EkjT+YDG6hy5CiKSZL7qPsjsLHeuRvat3oSlBWiFRnSuLOlsDozqzYMFqNx93 GPQiFNiYEmkxDxiKLOcds7+Plz2FjQdQwv2msllJ4jA9PxYRiEbfH14/ELk+/snE 66XID9dv91JbrwaI3NOoJZZmN+QYZ7WaAj3Uxl3cYnCGuIIt6z4KB2CYeyRa3f3K HbPq0mBchPPmavaQEfaNDQ+dzMuazR0VMoKfHGEp44r+XU+JH/lNzlxgQEMgVv43 0B++zb4MYgheGUhu7Xdgd6XSQdZGxt4GieXLwIAXA0nmAFlZB7EAJcyHqz0hVo6m Q/m8Ja8hBw6lmyM5uCduF61BhnQDfuDQetLgGzrvOp3m2qfTag3QGtEijwhH8L2O 3xuMqMjtJutTa557go0p+PLjAhMVQ0S7z+3aLn/368qnqlxSflDCPe4GMcaXmOCz RdMJMk9txqB8GM5F2sO3 =gtrA -----END PGP SIGNATURE----- ", b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Fri, 10 Feb 2023 21:24:49 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: 1044a9316b629fb7ea4b964ecaf1ccf3 21255 main/binary-amd64/Packages.gz 6ee4dcbdb0c0e98e416b94f542f6cc1b 17584 main/binary-amd64/Packages.bz2 fdb168fb0b8f575585d917ca0ffd98bb 4783 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release b2f1f73fabd4acfaca43d05bee1debca 130864 main/binary-amd64/Packages SHA1: 1bcb7cd08c94a3519b2dce77f3f5f5e16c312067 21255 main/binary-amd64/Packages.gz 61c0f6b35c7bd3a5f59094511ccd593dcb2b8c96 17584 main/binary-amd64/Packages.bz2 e800a4c83e8d9ef564f5869ad838962550799c5e 4783 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release 4a7c86cb1c0caa36c92e1af844ebf0b7e2bf4cea 130864 main/binary-amd64/Packages SHA256: 481c1bf74f609fbf71eed01da98a05cbe884acc2efd6d0e2c1c65f9e72ddc2e6 21255 main/binary-amd64/Packages.gz d9f8cc2cc5b2aa854c509caf96d9e1457e6cb0fd55597ac49408a96afb8a727b 17584 main/binary-amd64/Packages.bz2 e04d5fd71915c3003d55f3927e5af71a4831e30ffbb0efec6dceb36cd1b054fa 4783 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release d0bec4d8f926383f3d61dc79b8d5d352f71adcf8befb59e8e02aeabe8c19eeba 130864 main/binary-amd64/Packages -----BEGIN PGP SIGNATURE----- wsFcBAEBCAAGBQJj5rYjAAoJENmAoXRX9vsG3wUP/2X7ufCo5nJkyHhzOtTEI4Pq rz6P94r2S/OA7v99mVkKNyOYZ8hKMNccYumvkWaXBF+WkLemCPeJxaBbRUrulu3c GXNPHht8dusQYIxS2VQVYbHgXfwQ+Y3+P1wVLPNT+9Ka0POkUT4YiM1G8Zx3fwTq zUeCpV1TKgkrVQ4CF5DX8i9tcVmYUq8B+BouwQAFJxElM1cuYqGybG19H/od77nH tkv3n43P0TCZ9KR48ZXWXF+6v26SRse2YkergbNOtJwRfdMHzvc8d/nb7T/Iv3jM WmqUs6Ob4EioUTWYwi2H3y+LnzAPeSVEklfCS61LzlyFGelpxHGuTjaaMtCI2Bkb f3XyNjeVwUYmnGWrBMCI38CUnY0J0oXLrVUxYZoT0O9SSO2bpql64T2Flqn10Djk W8j7V9a5gNO69PkNEHWUylwolFvF/H8Zmc6QZbnnbFSpC4pMEeRhoI1v1CqPSMn8 APOGWa1xHN9hj9g4AZfXvO56BDveo9lbNOmFs2EAmBEEj2hCiroRtuCxxDmwerq3 MLtCJIkir3JdbefexXcbIoP5+tjl573nvKU+Kb4KhCJTBDEY6+6qZKTSBDESKTvq T2L60YwfXZsj6WCS9roTz9llmze3YjURbHNZpf4BO3zONwNNeqFZw3qYWNCyzRS+ R4AjBHbzlyIGpU5BGNn3 =KMXz -----END PGP SIGNATURE----- " ]; for data in data { let (signed, _) = Signed::from_bytes(data).unwrap(); db_a.add_release( &"DBA36B5181D0C816F630E889D980A17457F6FB06".parse()?, &signed, ) .await .unwrap(); } let (signed, _) = Signed::from_bytes(b"-----BEGIN PGP SIGNED MESSAGE----- Origin: . xenial Label: . xenial Suite: xenial Codename: xenial Date: Wed, 15 Feb 2023 23:18:08 UTC Architectures: amd64 Components: main Description: Generated by aptly MD5Sum: bea5a0f7c99209504f22d8faf10125fd 132287 main/binary-amd64/Packages 1aa4c130945a3a076a9f16546ca17a83 21467 main/binary-amd64/Packages.gz f18c7f0779161104fed2aec72d9a44e2 17922 main/binary-amd64/Packages.bz2 fdb168fb0b8f575585d917ca0ffd98bb 4783 main/Contents-amd64.gz d8c35b55bc8e48e267b9ccdaf383976d 85 main/binary-amd64/Release SHA1: d01c164d99cf7c867b5f115770f58e4916d7a15f 132287 main/binary-amd64/Packages 41e78c4c558567f4936d9952eb928a32911cc56c 21467 main/binary-amd64/Packages.gz 8837bf2f3e2bad7c73712d003c1510c6171c53ee 17922 main/binary-amd64/Packages.bz2 e800a4c83e8d9ef564f5869ad838962550799c5e 4783 main/Contents-amd64.gz 992cb9cd8a0af2d9ad81d2b45342656d41157202 85 main/binary-amd64/Release SHA256: 9f9178b66c4d1d31d7b2b741f0835c2140552cac68861beaf2ecc55f0364c620 132287 main/binary-amd64/Packages 57386742060a0913236bafd5e8eb3b3334284e0d2ab8362a7c22c78175e9d89b 21467 main/binary-amd64/Packages.gz ec097b64b5e3a39760a9b5ea6b02e91d0401994464dd0ce3de2a0a26a62230e2 17922 main/binary-amd64/Packages.bz2 e04d5fd71915c3003d55f3927e5af71a4831e30ffbb0efec6dceb36cd1b054fa 4783 main/Contents-amd64.gz e593f5bb98e0b6dbf5d0636ebff298b905b98a00402e2b20173fdb5da85c46d9 85 main/binary-amd64/Release -----BEGIN PGP SIGNATURE----- wsFcBAABCAAGBQJj7WgwAAoJENmAoXRX9vsG69AQAJmvducnhHqCXQIsqjXrDMjU QUAw56MRunn7rHTFpJY0ZPLgQ5gVBibouNZ9x78wuJ784Sl+MIHC7RWdQYBEbWQ5 haKjiI00BzDeXx4sUet1E+Ce5dhjK/UvoZIOy+ed5nv/HM7QFrvoxdADSDnYGy2o djFUVWR5kzkb5Tv7bcjJQWWf6JvY1Z12CgsG85ECYv2PE+tGgQjSwbxRDvFFzY1O Xy1EkjT+YDG6hy5CiKSZL7qPsjsLHeuRvat3oSlBWiFRnSuLOlsDozqzYMFqNx93 GPQiFNiYEmkxDxiKLOcds7+Plz2FjQdQwv2msllJ4jA9PxYRiEbfH14/ELk+/snE 66XID9dv91JbrwaI3NOoJZZmN+QYZ7WaAj3Uxl3cYnCGuIIt6z4KB2CYeyRa3f3K HbPq0mBchPPmavaQEfaNDQ+dzMuazR0VMoKfHGEp44r+XU+JH/lNzlxgQEMgVv43 0B++zb4MYgheGUhu7Xdgd6XSQdZGxt4GieXLwIAXA0nmAFlZB7EAJcyHqz0hVo6m Q/m8Ja8hBw6lmyM5uCduF61BhnQDfuDQetLgGzrvOp3m2qfTag3QGtEijwhH8L2O 3xuMqMjtJutTa557go0p+PLjAhMVQ0S7z+3aLn/368qnqlxSflDCPe4GMcaXmOCz RdMJMk9txqB8GM5F2sO3 =gtrA -----END PGP SIGNATURE----- ").unwrap(); db_b.add_release( &"DBA36B5181D0C816F630E889D980A17457F6FB06".parse()?, &signed, ) .await .unwrap(); let keys_a = db_a.scan_keys(b"").try_collect::>().await.unwrap(); let keys_b = db_b.scan_keys(b"").try_collect::>().await.unwrap(); assert_eq!(keys_a.len(), 3); assert_eq!(keys_b.len(), 1); run_sync(&keyring, &mut db_a, &mut db_b).await.unwrap(); let keys_a = db_a.scan_keys(b"").try_collect::>().await.unwrap(); let keys_b = db_b.scan_keys(b"").try_collect::>().await.unwrap(); assert_eq!(keys_a.len(), 3); assert_eq!(keys_b.len(), 3); Ok(()) } } apt-swarm-0.5.1/src/timers.rs000064400000000000000000000037061046102023000142100ustar 00000000000000use tokio::time::{self, Duration, Instant, Interval}; pub struct EasedInterval { started: Option, delay: Duration, interval: Interval, } impl EasedInterval { pub fn new(delay: Duration, interval: Duration) -> Self { Self { started: Some(Instant::now()), delay, interval: time::interval(interval), } } pub async fn tick(&mut self) { if let Some(started) = &self.started { let elapsed = Instant::now().duration_since(*started); if let Some(remaining) = self.delay.checked_sub(elapsed) { time::sleep(remaining).await; } self.started = None; self.interval.reset(); } else { self.interval.tick().await; } } } #[cfg(test)] mod tests { use super::*; // this test is somewhat flakey, don't run it by default #[ignore] #[tokio::test] async fn test_eased_interval() { let mut interval = EasedInterval::new(Duration::from_millis(100), Duration::from_millis(50)); tokio::select! { _ = interval.tick() => panic!("interval is not expected to tick yet"), _ = time::sleep(Duration::from_millis(50)) => (), }; tokio::select! { _ = interval.tick() => (), _ = time::sleep(Duration::from_millis(75)) => panic!("interval was expected to tick"), }; tokio::select! { _ = interval.tick() => panic!("interval is not expected to tick yet"), _ = time::sleep(Duration::from_millis(35)) => (), }; tokio::select! { _ = interval.tick() => (), _ = time::sleep(Duration::from_millis(25)) => panic!("interval was expected to tick"), }; tokio::select! { _ = interval.tick() => (), _ = time::sleep(Duration::from_millis(60)) => panic!("interval was expected to tick"), }; } }