diff --git a/scapy/data.py b/scapy/data.py index a1a8e3c8316..b6bff82e9ab 100644 --- a/scapy/data.py +++ b/scapy/data.py @@ -574,6 +574,14 @@ def _process_data(fdesc): return manufdb +@scapy_data_cache("bluetoothids") +def load_bluetoothids(filename=None): + # type: (Optional[str]) -> Dict[int, str] + """Load Bluetooth IDs into the cache""" + from scapy.libs.bluetoothids import DATA + return cast(Dict[int, str], DATA) + + def select_path(directories, filename): # type: (List[str], str) -> Optional[str] """Find filename among several directories""" @@ -613,6 +621,8 @@ def select_path(directories, filename): ) ) +BLUETOOTH_CORE_COMPANY_IDENTIFIERS = load_bluetoothids() + ##################### # knowledge bases # diff --git a/scapy/layers/bluetooth.py b/scapy/layers/bluetooth.py index fb939b3e4d4..2d3ac47efe1 100644 --- a/scapy/layers/bluetooth.py +++ b/scapy/layers/bluetooth.py @@ -21,7 +21,8 @@ from scapy.data import ( DLT_BLUETOOTH_HCI_H4, DLT_BLUETOOTH_HCI_H4_WITH_PHDR, - DLT_BLUETOOTH_LINUX_MONITOR + DLT_BLUETOOTH_LINUX_MONITOR, + BLUETOOTH_CORE_COMPANY_IDENTIFIERS ) from scapy.packet import bind_layers, Packet from scapy.fields import ( @@ -266,6 +267,24 @@ class HCI_PHDR_Hdr(Packet): 'extended_features', ] +_bluetooth_core_specification_versions = { + 0x00: '1.0b', + 0x01: '1.1', + 0x02: '1.2', + 0x03: '2.0+EDR', + 0x04: '2.1+EDR', + 0x05: '3.0+HS', + 0x06: '4.0', + 0x07: '4.1', + 0x08: '4.2', + 0x09: '5.0', + 0x0a: '5.1', + 0x0b: '5.2', + 0x0c: '5.3', + 0x0d: '5.4', + 0x0e: '6.0', +} + class HCI_Hdr(Packet): name = "HCI header" @@ -1153,9 +1172,13 @@ class EIR_PeripheralConnectionIntervalRange(EIR_Element): class EIR_Manufacturer_Specific_Data(EIR_Element): name = "EIR Manufacturer Specific Data" + deprecated_fields = { + "company_id": ("company_identifier", "2.6.2"), + } fields_desc = [ # https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers - XLEShortField("company_id", None), + LEShortEnumField("company_identifier", None, + BLUETOOTH_CORE_COMPANY_IDENTIFIERS), ] registered_magic_payloads = {} @@ -2445,10 +2468,10 @@ class HCI_Cmd_Complete_Read_Local_Version_Information(Packet): """ name = 'Read Local Version Information' fields_desc = [ - ByteField('hci_version', 0), + ByteEnumField('hci_version', 0, _bluetooth_core_specification_versions), LEShortField('hci_subversion', 0), - ByteField('lmp_version', 0), - LEShortField('company_identifier', 0), + ByteEnumField('lmp_version', 0, _bluetooth_core_specification_versions), + LEShortEnumField('company_identifier', 0, BLUETOOTH_CORE_COMPANY_IDENTIFIERS), LEShortField('lmp_subversion', 0)] diff --git a/scapy/libs/bluetoothids.py b/scapy/libs/bluetoothids.py new file mode 100644 index 00000000000..6dbcdded15f --- /dev/null +++ b/scapy/libs/bluetoothids.py @@ -0,0 +1,755 @@ +# SPDX-License-Identifier: GPL-2.0-only +# This file is part of Scapy +# See https://scapy.net/ for more information + +""" +# Bluetooth Core Company Identifiers +# +# This file was generated. Its canonical location is +# https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/company_identifiers/company_identifiers.yaml +""" + +# To quote Python's get-pip: + +# Hi There! +# +# You may be wondering what this giant blob of binary data here is, you might +# even be worried that we're up to something nefarious (good for you for being +# paranoid!). This is a base85 encoding of a zip file, this zip file contains +# a copy of the Bluetooth SID listing of all company identifiers. + +# This file is automatically generated using +# scapy/tools/generate_bluetooth.py + +import gzip +import json +from base64 import b85decode + + +def _d(x: str) -> str: + return json.loads(gzip.decompress( + b85decode(x.replace("\n", "")) + ).decode()) + + +DATA = _d(""" +ABzY8d1^Rl0{@J?Yj@hn(m(oDwDybnC+i>k0SwqV?*z!8a1oJ&9cMjn1hkC?Au+l*Cg*(kQ`J>1b%UM +RYwwv%B%w=nbyfZ9`v3mt=I*BdpZ~}D&$lSetXcdlEH~X;|L2Q^XL@*MFk3lG-+ORJj{nn|&4zrkizf +q-79z^6WqGn@<(5y~;3>Nh$1>hzU-Ub6@Qj;&7-7@;L(S;6zT?Tye!P4%|1)B!^sLxMJ +W!2ajTYm{!XO7;U8;wT8kV`r`cl=$w{VAnwe;NwJ9Mm>J9k58#Mj^A_46!^6Uz?xn562^UWT^2um&@CG367IsE^fKY>hHeSgse=&*v+c +veB<7-&#&0Hf0X?-tbvT-0$5Ed~7N5RFu}>`a!+9q^~oZIkx34#?E-*_^xdQ{>)k}+@<3O-olalY9B`Rp;Dk+gk`lO+3P&7yUdM`f1B!dQT|B;$SccMQu%Zy9f_$1L9$+Q+mdEr(eytdV$)H}J +(Z3$-QPmhKN{W`!=i@aWodtf4mtGJ7MWJCWUEnzkiPgRy1jhp4P_SawD3wxlYo<<#~^mhJl1$i2T`1+ +KTSJ}twi&(nD?-bMOvQkh;~P5F&;VwXCDez|T)){=ys+t%D2`ku*ZtvfmgD>(&9Es(n$A4#_gLjTFK|Az_ElC&M2(x}?TnRc9L +n58FclBL_onrG`ciDCOTU)hqx9Ev>N{(?6)wq~nqY`dS?Kk=XTTI)t#{u3`BWKZ#MS4HW|k2vKkBuS^ +)HqIk!d{|HTu%xI5gxZN{3tJ`2;okWXSrN83UnEI8@_c(?&F{z8HEZ2|l{AD6>n?yUtGTlX19^ArFMP +%6m@kv${9eVdm5KruJdP6J(;|LJHCDg{1V% +TmV`ZRGBHxDBUPn^Y1_{SPJLHKAt8B%EIU4K#heEU_B_`zK~&8)c{hSuB}!JgOI=Ju;3@;F`>nfYOo% +Hy#!wCn?{_a-vVO7f0zxqk1m3K<4gVIFVtOw>|Ieqg=ew|A283%NbDTix9mY_o7YXXt&*H@A0^;y-b- +Sivp=`Hn2=1Kocao@fRqn=7DH5G*7hfoeyR?VyJ!qi0?ZZa42C#l0u^mt};nT +IbhPRTk6Ok9dJPEw}a~|bl+wj({r12zv*;!5s#5tb6G#_&-2|CQPqS(S-;)9Y(kHBHTe{b5$-AY0Qn_ +ZQZ;tKvuqL+149h8Q+y_EzT30xI>lfeSON|?*Z7fK?Au#V5bM%F}tw%_Sjej14Q?>K$AAkZ!G?6SUp! +5U9)7+h_A@7)s3i)aUW74}wk#+SE}+~LIW=TEgRxa~`tikA%Dzyed{I#I;z-_i2;_83IEtFD(+bPj8= +-2&+wBc`TvpX95^QN%CvY+G$gU2Wd>C25zrCSgc?kS3EZ?emkx#X3AgXdE{ZP}xF?C}EyGKtdE4u=`VwUhFWL~gA!LtuG<2SPD**D9+ScrKX)C-6_$ +kPX-L%idt^m{?A-qV?$lpG64aiL(S&N2uPf>4M +8(M$(PpQ8+cJ+|QIZ(T(k1%Fp);IVAZ)TjR^oSkdaQQUXT{}wEm3sl2D-Y?Sf?w=`rVy^>9BBqXeUVJ +S4k4T$gkBm+Auo+m!9}aNm^$ybArHnbbSZ^gHK7ydcP91NuxDLfyht--42`euOfLnB1z-ugO8@&45kZ +eoSN6VMA3Aci(dt3aythhqDjCTN!n$UMuk)j8o3xjoG7`ASuJg?DR(zBUda;ey$UXY@CA2i$;Lc0=n29@Ij&yJnhPl(8`Ui*{KkFgkkCu-klZ5YnH79ZeTTj2~?l=BHh5_ +v`s?5#yg4>)szJfjiYoUbkY#2nTvc=x-@P +r2^*dcN06Ifq)!|6CXf>>{df_s0!`8oq!~_}2YcoM9FVfYFdhiiNK#X44P^dX7;tHD +n{agUYE&A~tUb>pTG0y};gP`PE_@@K{!H_aw<7yUG!X)t2`kJhV8c(!c>b&zzn4FfRQI#Z9;{{D6Aj7x +go*6!D{Mxv&I@GHawn`Mn3OTRLRuz(0zuTrxGz3|(O_jIx&_Jz4ByYjhU^n^3O)bYb`65`2`o7adoXh +z9oyGlK(5C!gN=vw-2Qr#9r#R-wjA(D3g4#fhd#j}_j-Okvj?@L=@aU?cOJap?C~A)1dR2C=o8SX@y9 +sJwi!Gft>_G$34in$^$7?~P9oKWXrG|YT)aebG2S#&_MKbtZ|+F>=b?Dhj!Kfj4hyZ3^WYA_{s*~k^U +1#P>Vv2dRq=rHTHb{$?%u8sX-d>G*$ +`w$;s`L(C9i*6?&?+Y%e4mfp_t4~14JEZX=m^GK?ud;s6_<&&1ECVH^FJ&!M`-Fa0`5LS-J3oLGGzR; ++(NcW|JV_ZFOi4Hgu;kMBthoR)4&T1UrhP&@3-JqHs5pRls0HpB$q4|V&qF+$J`eV}^$85k-GvLgjSm +q){{a~nY41vyXLO1-*_mnCyf{IgpF8n4>IAem4s3`LbC!Q#c|t^D0Cwj%I^YKfCn-{;TUuXn0!ZJ3q5 +gJkBV^egFqtlU2olYzw_=BuEP%ERsdwI17cW9sX}KB&&XYBA?YXxYSjAJHG>Rdr2s$m|vdj>(? +z0O^p-&iTBr?!d29i1)D&Q{?Tz`EmZwNrb7~<=@Mdn`8xODv&*}hcnY5*e9qJc&o)|H4OO}3FkNg<(4OWj3~dd7oiPmk`GGKqZ{mj2#YrN2KYi +}IBls2QvJO07S12ofe@Bmz!HhQ6lql{g9B<^2~#~zM~KXdhFXN59^(S8W^c9jZ~{*c_F~}u;3Fg`qT~ +?erGEb|86E{lt98N0$P@Z2elDfYU)q+MQm1bSN9q=mT;9F=UAGATB@2;S@Yf2&sOd6QefXW|za03}May_9HsDbe;;a~JmPS49l+9Ib^wdH`yA5 +sC^H_Hy~?1{3WB5mMxb80cGM&*d-NUPY}Ol7zK9VX7e*D;tymiw8d3)qQ8|{C4e`bc||5f9x4fL^%*e8&7pTx&w!{-|J5+q +wjF6DU7h-nnR07gyzu&oKW0Uq7Ph4 +nK|wx}s;Ph+28+dQ!L(cjVj7J!KLDIrN^0fM6_$7jBlT%~U4)q$TrfwFsV?D5|T>EEN-89LL2H}k%^w +XozpX-Z21XagWU*%N$J((`Mt-MQ-B-P~H=SI)p0YQ{>N9nDAGi`*yRRmTBF?%0*MP7#!^qR3MWyMC6j +K2U%{DQbdZxMtaFrpW=qVCW^g`kB3*Y36{X(QwHiq`%BrQNHhTfbHQM_ +;FJOC%pyz!X9H8R7P-Snn-Ce-#ArN0v`-egV3k)o$u35+^raaqBJ;Gv7V5mKdOZcx}NKOazgP~z%%W&d*F_#`8wI$d&Auu=W{e^rh5X(A+d +W77ZS1Ii^&s;F$^BrEk6s*#nHO-F4hG%;O&eR;rS~O +DjQ{arW{8-f@C%75_18@W%)i+_6VYZ#f=&j5Zu|_8#plsTCcM|Q2Wjd{zmbvD@CnFN +rBb#6?gV@ +CwJNWqXZ_O~_9CZ-trY!u^k8bJ7NmWz^iq|e-uPu;&TUo2-3F +`!9Rd<+dMmiFxo{VY@8o9l3!<6wT}t(IlFiKvNbCauyf`Ehr}&^F9*fy4djh5jp>XH39^Ou+#X#dKlK +Q^c~x2L;`H=~AWe@D9T-Mqj#eupuh%oZZL=!f#2;eR9)Y^X&{+hvN$&(__G6E*U6}pOqJ~ij&)KVR;` +vwh40z#-l}Eo{v%kTXwvMm^z$CPySBwUM9a!w+oh4nKhwK$km$9|aqrc-X*7iEP&eWrB2|JH%>)vtC= +|pI79;dL|A}R26{v>1=3@6TPX4(OKp28k^lx}wM@m#=ts&g*P0AG(lB-l;5JLHVN2sy&auYeFr-)X+F +9wEqq<1AsX27FAe!PNWif#kW!lj#v+94FZtEyG9(cVGu6eSz +RQInwv7dn6#nTiDermMlq3g)&Snv&y&6S*GjdwA(9W!W9rg|KB{bAbV@jV^OlvLeW9YX%0rtv;E9m6^ +G)ga*fsx14BJ24O-Q^ebAUb6A;3sfTyB4&lS+C`T_2zFhMF!h{YWld->AE*;a})UG4%o98cZ6+>9+`y +a3m9ep1XLYx61%7~AUCvL*F7D2sQ$t~FUA0kf%n^?Mp|N2k{5gr^nwm-0k=6g2WM#yj&=Xq6FzQAlzu +;D)kXnT|(;pB0C^%#|BFrmj75H_g&uBF~1KsdKS +PBXa(65fl%2p6CZe$Q{-YjddSEk?g{y8qLglE+A7XRcO`eD@e4(o;r492@b;II&KImFaaSOkVf{q~@P +eOgYO_*ug~^U8dOe7(3ec&Ul5XmCpB-yTo)lU7`?>9Q|D#Yx|jC<2`KkeG=CJKxORnHMfS~_Z=`v(0p +j@O%v?)2sS?M;ygKKS;7Y;m0^t>zPsriMJKSh)<{k8&`n?CB1#0X(tE-09)ZD$c#CAjxdQ3n174H)PA +nk^9ENVVnp^g2b+uO@D0eR!2S@YSoL}eyD&ghn5`vr0XVxnCQU?yZgw@=`u}TVIJ%T1 +nF*2n@dH0S}7%HED)_-l~8oqij?m0$lPB1&ESL~f7Ii2r49=A-S|C3H5#c&v +Uqav)saUt8a@U0TTSdZW;~1jOn<$^;>Pb@>q9Q(b~w3&)#!6LkIup)cSHA_kv3D8%KP?CTDVf3&|uxOQ(@c}GA-F$1j`sNQv-YK`)NW6+9J7R83V@h-x55Dty=usDK-hkMjo2Hn2za>u*#j7Ob{^kHmHf9QlCnAJKLNquL|4gC^a&1djse@yc2G-pI!&MXf` +Xk=rGh6pEtEtiUWzDlvCZQYTBDfSr@jheUn0ChwyF|XpkR +%3)q-AyCLioVI>Jp9ujIo_ZzlCzib_p=C_Y{yvE~Hdy)|^1ngZtn<+P-6bvzPWl=WW7EU`pd&Q$8ehj +v|g#lq^K~OL`&Ia|!aqSI^m|D$F+}yn|q|DB)wPxY$MOL|FG=k6ZKTCEgg%C-lBp%^j<_&K2V761<7C +64oWo3Nk>AT}j}^iSlRD)$?gGJ=<)Aa;9(~kMwQNNC#-T1E@g9I3Si}1*YUm$6`=sn|*E8EgqKEz?*R +zaF<}tEX&{u%nCPM=X?#(@o8bty&qQaKTN}$zFuB}xKA&g>Z*WO1bcWHon+ozQzc-K;)dPa$&0Y2QEY +f9x{PXE-?Dw!zi0kf-A~*lpc9l)35!ZBTni&YJA;`GdUXJwv2emi&!56>_9;yTfVykHTNTwMOf*4fNW +9sjnpy?61$*aucFngZ7&On4G&ybdLS=``v{5!ByIhQwRpoBOMiD`uV0v$%eYxR9B(O7g1_6ehbhhGv* +R>0#mPKyVm5(%Wou4j-l9#ZwbH{f9MC#@k7h=iaZtX^6cV>)*6hU(-MR%#V#hQQtDn80x*yurrF2SQE +To`G>oKO+);0q{9O`;GOTE>NuuB3AXK^_|+$C(+d2uiqTT)}6oL1yjC82(J67d}fG{%N%gR$yq(Q9>* +n|4A#BGaNEq!bI`&L61?s9M(HNt<;swqWKZ0Z?S?W|KdsQ5+*_m4SsQrHB$99Avm<~tRXDiK$eTGhGE +b!HD@gb4p@*KOr7FDx+DN3Ki;G`^cK4;sX{Z|ab3mw*p~@_ +`4;7Ghf9)D4G#aHKFkzYW(8zGD4lvy6mv7GMa4pcrQ>NmDGtac@(EIPBrFB$>p>aM&Z*9AtC1tbklxkWKi7@78++om2M0j^Im4!4dJ5DnS!-!24+m +-^@b4AaA^;l`0RjBkpzxkKzZDwv5zUu2T|rHyb6pc8lWy1}@rr8RsR&71`@rHoY8sk5P34E +ha6Bzn7W+0)nK)qbEGz6q(n1U3bkATvh4ZU?ks0y@wQNG71H-xI_-e{G9>0+Fw1m@Fb2JFU%sLDm;hB +5YJ4TL60(8$mm0%GVr41<-7N`g{fnBL+W0$)g_O;uE;KcY@Fb;V|>C;(&p`4F{+i0pGQgME@-@F{ozG9 +W~rT2+K#4Lid&35YC!o&1n2qL--qlR>SM@wPnY-N^aBT7Xz#q_VXGRP?JZ5oa{Z^F91t0Q9o#Lb*i+8 +-jAZ*5PAxZQO=^MtExSKvmK+f?K3(To2L?X0!z}rtk>1}m2eb30P_=-z|~%WG!QzOtPvuCnt}wJzC8@ +BDVP(UH@Z;lH-w=uA!r@vTeRpgw2@#CPbW~9?auNci#O+0a5n^=hS$#a+Ttou+7~}h2_Pp~g9>P=c#h +V2tf)j=8jQ7r0Kv-j7B_^gYRA83N1weo=M#d6eR9sW`vA +3*k_^uWrHSQ^8^A#;X_dSa5!31zdC^;@0+o|RnvqU0!0Haum(|rVjAT$ptD@2!JRQ9cc}oQ{f7axZ@5 +Q=tW=YRHy@^2Us1@c%H}pyR}^m#wHzW)6HdGk6e8v%>hZRZaQF>@ouxMpG-Htf&KwPsP~`;C8NxNghi +hxG0z{0NkM5LDQB8ETiJzrO9)YoU9~WSyoGh$(mf_Y}M7`Y-sJu2ISRlvOX;$Ju{31c*X=Y)zb%5V9!3=+D-H3+B0nHw)~wqhTogv}FZhQ0YFDUOdxt;};EV^fbuQ! +l9o4ns1+4l3*gbLiPLqcYA)yCv#QB6e%XT>VPeteu#6GPShHf*h?GE7~-wD753(VlPrUE-(IWs$keT0 +Z0OHnIix$$NcH#rs<(pUSULoi4d`W4u1CfO<*%XH6o2oF7G32s#(5=+(gcerpXMh~$S)!hY*Un^*2gV +|o}NJ#P-Qu5JncDiZ>RxF}AgoY*)&-yf}6FL4h!MVfjDXK%Hbq;85N|Y7ZKUwzYjJOVACp;hgijRU1l +I!%lH@AXd*vNto0VMYjVKN7zyS*sS3vfFGjOG~#*dR`D!OVp_i+`9U|Mjxpnkawh1nz%Vg4f~9K+N_6 +2<zZcE&!X+SG4BrHD0= +{wzFoZlTU&!1*O)5A#ST7anjJtuZR7Gqs~h28ljm?gvN%tORda`n!qUCbpzCbE5yTqK9M{v|h=N*?Y; +)yGGXx>77WwUPhF_M;Zdu_jPWMy*#v$UF5{HD7mLUJI)75|vQi#g;erPh6Fp+ae;w@EeOrJ}>385koq +eaFQJl=Bn`Q0R+4xyw1jp0j7+39hBl*;96S)cuj22_R6Eu6kUNuq*!;MV2cf-I}Mj@J`x4 +eGobAIyp7VoBmBdu~raL +wlG^V}vm~jKtjWfKgJ1(AOx(gq~-NtrM)%q$$BLXE=0bMp;F`MqG!Wmmja!aaQW479+3 +WWZvv75vVU7wm8dSP&FU0)Hl8HH$rV(cCR1nQ8IE~$Iq1 +DB|J8de~?2tdZ&ky*&DCZ;RN+)pYZ|8-1)x)3(Zz(@ia@*;UwvU{A!X#zz;POLW$>oAVHn$v?;3^h80)PO>-r=kXA9d4v?J)U_3d +uE0YJA~Hk@z0+>EN>Zly0rPoBi`W66i!oPgWh{(+6R-h+Rg78kmdo82}ubUmN%a8jv~vn|dB%E3^-OmgfHI0Lmfa?xRVbq-rN{i#i +0%+IhW1(}%?m}aE636u>yZ;tZKySJpt81P9+-5Xmvymd+3CJ;8yj$$8OR&2BhhAl&oL?aM+PqsDoQSf +nD;@IWOx@$?;7 +8oRSVQ)%s6_983-&mV&A9s01}WM@&|o54<4IH5{^ZgZj4%ng5XupfZb0X=HPwe}pcw?IPweOYkbCMbm +ouv2LQ1lRucj9;Fc3S!-x%(<8V@NaNxn-J8aJ@wFVxNaWUAr~%y$UQb(R1Kt9zPAZH9d|F*QjiM5Wao +tQWvu^eEV~L!#h|D!8}qffea6E3@uTsXwFx*)oq?^a3aLjT)6v-`gd|)4Vmdel4ByRys5zelR7oX3E@ +^inqqP*r)lu65Ds<8&+%zB0>ke&!HSuPc#}F7Eo_3!dG1zBh97h|_etHf}n<7sbmMwn8CAO>Erq*DmU +XSGJ)4=gZPYXvAE`4s9voEx?hBo&STsY3yQgs^2%i1PvLtMiX@D%4JIW#C26YMFusUFD8~Y;v5lONMC~2|L0Aj*3p*D5ccoD6uIkzXh9W?iUtm^Ns1KYk)*wP`{KD6f<8 +=W>y*&sT^51a1Y7R;d;SEWDB{K;5fGLLQXt1>^u;9_}(2$EzPz`}E)ezyIiRZfmTf;@|8{WJ0Sm&QA< +`iJ<-V_pWX0wqKxZ{O>iiBW(kS|uteS$l~Br1ydImR}fCv3gMG~gB%{=oFVC{i-+fj3FBBG%0r0z9ER +mW>=t@Y*KOvp|sYTbGplN}Q!9vs%7aU@+%+H6c<&tj6DHKgGWK(CrGGp}#j_oN@dTQJ%$_^S0qHZY2o#tcc(A<2S6E0} +tD)4?S;o$q@u>&`#TMvlaDg^1YdTN%#~gT#-vJFuGoi#IfcRxMLt@ZaUPCCOQJdMk`D0S^_q*RB-e`J +zAR}&eVB=^Iw|pBPcUYqJyrl2&3G?q5`Kp!~izyoQ*%!RkaDh486Gnwi4Lt-fC$mRl+Z`2es~iuM?T++S8+w+J(gvTbyb*rGTUrm$%dM8Njj=>QvjUslJp2rk%3oHd}O)$gi+)N8bXcS}zK>vI +8>$ES!dVLywE04+p?Y3G5%=OoQu5dMZ>&D-jI3H$e~Qtb8hAUuFwbhKXBE$)|xIrsw?#3j0i1EmXF9B +ctQDXERx%SkY;-mNM+x7_dAy(y^Yjyx*>H5HzxVYRqdg6up|VjJUT{RkG|R>qDllulH$IOnB-=9^uGw +)^B#{z6S{LJ0FXk2Z<8a*RU4R*zH9)94)@XGri1%)yg&FPr0tR{;`0wJ-qtxWGv)<*P7y6|@*9>@YbC +=#@77I*-!o89+vrQ<%sQ{Txh@M%F>oq^&MD4-!Qxk`F~aL55|OqwX+52Q7jPKOZrZ7GVB2*lP&9fs>M +giVo6?5Mry#Qw78kY}jP0goL&*T~!B-#cY?1&Rz4up(V~*6SNpF055l2O(#b_M>RoN{JT2DO-#)w+EB +Jki-5x;@P_kb$(+iikJW0Q>b}8dhm#gzi6=m`{C7qUdG?%`9S~YKT(H08!YfV1aAnZM_OAxM=gu^dPH +@4F@~zN@IJ7u>EkTt(h>BPz6!*PDV+yeE!j$0z7arWjJ+^#R^$+%9qzWxCDDqJwpw`)7CO7>%i~nd;w ++Lkf6}F=r071%KTpcJsMpOC(H`47^%7Wk6ww6$V;@J+zrKCgN2D9Z4>=sAHOC=M!< +3pQ4#2!QyWI$t_4Fc)OeO)gp-z!)N!2;^DHHhCfLYg7>nA|*CMdsJND=ai^8m6`cxyj7NLZRI}dEjb* +(A;s9HQe$+idQl~XP5OczcZ&wnzUY%RhAVFw-tfZ*w0DtcO6oAc-f0Xm?x%N45=T9|-BZYEc?2qgqjQ +UzsvU{2&1T8oZg{%f;Zb06wdy{yl>wb5$8F9~XG&|j~=26ZBF!_WgMK7R7 +f@hx1!ar8sPjbqg(-Z9vU4nQ6wwgcxVh#qZr&y{}oR(ZWpYM&3>Fx<{?F-flUImUJ|FL`7V)mko<~^0t@yo3!vc&;yP{>(CEWJ0~g#hCRH3Ybs{zU-SWV*gDfg<2uWyT>;`k2*^MBEVsUIsj9pJG +#Rgh|=|+4IX6<|>C=%|3YUW;6B9syTVap(y{`uV9Ax^RNKyUnl@W{AZr=uZ8j@e<( +>%rwB>Pop~b8_sYaobp$+7uu>30vYAf;ji{JVUD^b(Ez~F_K(eT;3wQ-s00e7Ms6GRl!Pm|S^6^?B*T +^dT_hJ%krjHTpt0t?x-BPs+2PD}cJ?lWS;j(Y%kvZyIDO0d`Yd@=!7{jlLct!;_y-^1K)FoaJ&UIwj# +-KcabGT4aKP_)jwBiwdhT2!IXLqxQ}tkDK1=|nqEQu}>hTqyjgsc~%w!#z!hP7nISPJ2bB2IU4yFhXR +-@ypaRG)CXo`uZN8$9Hnw=Hn{$ot2%R<5}VHCeaB(C(&<(6&H;ZT({GD?+isV`S;+vd7>;%)^$oSA#? +@F9v00Vf$LF>s>8Y2F+3YJ0q^2z%UP00qRw3`=^npR|Lmw3!r`#aSHc++uv9Z&@oILLec07Hoz`_FF +dV!8uyrS=}H~+0ovgra&ro?Hyl2luLL5JI9bP~<&EaGp+LCd+o);fascyP&mpMyUg!3#{b +&+zKbEWnCvb>YNmDeLi3wJq(Ka^{Z{SQlGdDInvBD`*8_}VNz{pXpH@;}^MuW*thm8MDn`^s`wh?m%f +rszaF0wK{)c#sKhk|2dstFCR!-aPrW$QH^V60E!#CB%@1V6tw3kPm;t8|SG58G)iq9yNZ%9vos0;oU8 +tUWaoy!2QI({O9|l*cNm-Yylq8tnSu*kFe^K05ySjMB-7eaz3MB6k~L?4@f7PLl^PevO5(T7))+4p=y +pDWNOERy`Ou!c5Lz36_hYZn<(tlK$7{`-h;2^G3oPbGaq>)t`7)MZ?+pJT*aYBC0DcE~UY?7x2queKN +g4U+U~=xU|P6TA|t@G&+*ui#N61D~te5Tm?Gd96Q4nU>C^5vma*Q1-%A!w-AO`@GIK+U|d^Q7`;UuxG +pYQ2*HIU6Rfc{e?O7mST63Z%@t<%aVcAST_pE(?zr24s%x3rAaVk&p8TSmTrtcYA)=qIyR5h79e3JZE +v$Rl*X^m1?suHog*7B+X=-qel8C_m`5j-!S|9^Xk#lyqtbbK6#~s(sphtKTC5iqpRS#PXvi0>K{>_Km +)GIcq%eD2SH8@XIu|V83Q)2Uu8)xrNljzr8Tr`M=3%JpRcZTQg7}?-%yWFLB1Z4(szO{Uiu7&Z-o>^D +iB-m-!NXn%5S^jY&X}F5hH->I#hae3eu*bndCMfU)f)fjqf}7#$TkK9X07$ +p~?o{p$`l}LN0W9QUg;!29ak0xtq%OE+7sM=d=MG2*MSR98+4e9qx<)YVlTa)1U;II6qJje#?5H4F(`sztDXYyoTO5gcODQO6yZvEcr@rz3<~1 +``YOzWI>KRQtJ_J3sUm!S6Ux;BpGdsb)Vlv-dg5ltk|c{5wvpiW3~)Dr?8MX?dYvL~YZS$ait(W#q+W|+cJ9FUXo8 +{obhDA#PxwRNNQZ1BTak-zv1!uY5%7pQ3xdLz5x?jCi=P~pfYlXb~u?~4k>}5I|3>I900_x9A7hq?ryl(6qaWB_aNXd +2l>K9>fbB-mB( +-Q*FrL5(*z(I~d4nh(>Tkbpgj!GkPmFkKh;wn9QEa1~6EbP|6^wmLl5oAqC#zqKukENjTA00}n2|0cV +*|aIK_Qk%2k|fzQXx5~lC590GER|2%C?u>m0!q+yiHhNffA2!vCVmtp^0*_saRaNC3YALN5lKSLtzYU +%jH70WF`EX}AjK#x(mOSG{z#`h6!anX|0-dJykgEY2+GG;=zS?31s$nnk+{Ts&RPR~gc=hEkMk)_+LE +TNM7Rp8jN!IzpVn7GL?#Cs!^PQ3lGA; +HiYFL#8Zn$f5+ItQ^^|c>?{YTa+1u2MkBQ1=37y+{v#-2<4mZjzV!%qNd2+d={b1XCEdDj0)<5{7Q+x +zgh*~%?Kk}%9i!S3+to;?;-9jw;a8O2?As&9558!#R^SwM+Y;3gCs6-|CFZX}FQ@I?637_OmR#0P231 +quQLoA^frCHJ>f0*QL5shx)g{ +ouaeejQWD`NS>@Hnr0Sow51}?uh_P&;9BWbNpUDysnsm5m8?OQ?dYk(Ner$zWBwh1=NRkDGA%2bGBoSttd0xGrs!2w?%xL0p`+&eE%MbV^GtNYxl +(LmX;j5Wl5%Q(dwxvM!Jp~lYeRU*~5NRJz8p!~pa!MQ3ZKk8_qf6t9ModV4Lw<`UEJRvB95E;FJMrIk +Dq%>)JHM1rFFX#4RQSbF0_lR2WvHgeEGvlv6^knMX5|E*J0FfFA2#2X+X*dknb!|Ar&+kDd)78ihOkq +#(MRt`K#OB;gI7u2Oobg|4-}iMCUq-8LyF3y3C5&Dy*kR>Pb*s^qj4;d(bS>%L(ObeUP6CE<`R*7`xP +*LzuoKet=_5>dOIXHTEF9nR?Zx;kCmAldW3aK=g%=LU+Z&#~@KA{cCe{jHISg-k0ID=_+1$~|%0U+w| +JR5Y9(o$QUn&IW*)51I0k~vER>ASEB#h$)b89j+MF>F~JKa^7`-X$y<+y4-*;0c?D(rLreqMOzmf;QT +_%b=^Z$-G~r-1dQN*Ue#eoGKXPPs;qQ@?B-TEQe_j)cU`Jr3zo)WmqDIV%N467rVQ|OLfj +eYfxGak}T6LGD0&m*tFjGd=#IlEC}7qGRbY0E?F9BMQBHUyGdE?63VEKpT!bPDxJ0jWoX91J+Oo{p%< +Vm^)1upQJen<`$q|Ez5HKw+<_mGGZu75)_gr@eK~W`l^{&8XTKflxgNJ1Yf+Z=4s715=j4Q}_-l(kXwH$V +V60Y<}#T7-e7aM%0$~T;|B*7UN$3AKOk3y7kZl9X?0YYjMx}c1L2e;&bQ&2;Zi#(ZV9W5L~;Zh$&ldv +ugWcvNNiGbU7sMy1U-tY;lvux(HFY}h2$(o+}4ZQ!oj6vPddRBMy0Zn65`-EIky7aT8ipLWboQCe6UF +QbkATEDi>fR`O#MH6I=l_@DqbHm+3ow!Yo0W{aRye|0cti@SD_}!3meJ&hHggJx?PO!o#E978KXy8-*x~O=9Jt)v4{Z3giT-f7WZLvj^sjENpC8 +(deeed`)Z^(;Bzy-eGA50J69D_dh3X>g>%=c}xry`=E9(>eH`33ZcqgzG(QDCx9z{UQ7O|y-eWpL__8 +`3u2s!dCwPxyuU9@F@RbNSuB<=!(x-;>quYAf__>ku+df2hBgu*$dUki8Qv?AIw>SgUE$lu(NYi^6~B +@xM9Ffy3fd_1qS>PDJ0U=~?d+1evZ@Q+x64$(u^wu_h4uggTbl9+T(!5S0lgr^6BChj-kSyC^xB)<~a +6$!zj?jk7q|S)-k&{AYW)1bGo!1AFkKS)+Y|7WZ=4hl@o8vCQ2K{28A&GB9QOHqOhkh9D-Z+-R68b)% +vg!HjRKAe?*ta&pc9geqpI^38Y|&ilxYu+1oRRXarcgeqV!ABvOpEg14qN@?(>Mq~E+HMneqraMIFSE +|8ipFqS2uo|`~aDb7#1tz{5-W7fLF8qWXtz~}N3ziOCMG|eqFo}=#SbI1@y*>0Bn~!uaIwFY*%=ouP@SL3orn*OXZ&3N*jK|ft6VzL8?D|aynuM}C9_6xv<72?S&^F_3mQW| +t}^TKoiW=D-MP*jC!p{F-jmp$^F1GLpP|F|**Vftv5h`~hv{_wZeB{i%SHv5GQXt%RGiPIglovxht2T +$KudMW0fXu&G^%soEPFBcynEH{PIaAV?x>&w&J4R0QQXoPfOGn<9lYRbo(grJ#OBqXiW-?}FGz+7n3b +nTENo&n!#tE`K0_m4IDIQR0(<2zx_huspyEO9Xwi&s)GnaS><g|N!WLxC}JyOf$y6rBXHxgVY!> +c;A^&`bWIO8U88+fHharq+l(!9poNJsqr4yOqho1NBn`(3lG&*Nk=I&qS9@!DA$y0LVAT&^s^jj@CI` +!rNU{m66{JOKkndl25`pN2tc>%`5t#IvkdNzohnK{6^|PaV&&@qx>ln(IsCfL3ke6AT#x+)70DA@MoZ +0t%TjJ2Xc~pIao)R!-;+rw;XYQJR7<$RMkppCd#Q(c1dNBVj%pUr3mv)4RI`gV*v>8Kl(6&M98wDcYj +`)LPC~XM2z@-F!)B9Y)%GKQUcc2+k!y6@ae3GI?Ro@A?57ouev?UK?`3!NzVZaFDlV)Cu${~L_uTV5l +8`t`H<(RV_g7Z>tjCiu%R^S^rD>)&sK*If?hg;+-MYH(5fB;Ku8ZRey+lB(ciq@7m-+h1L>G+~aJ`@ +@~RbCR6USwaf({OpZt{{$F1+GKjsOYhc#1YMy79l4J$_TnEuT!YJD;t>Erl +7j;Gof+P0nElaQJz+FRSZgG_ez~6O0cR1YQ+6L?+Hi-AY&EASm@mx#S$EnL8M#v(tI|Ut!Gx=JVml^{`+nE;cD8J*WR_B0@&luSI!~;nLR +wGb&tD<%ZP)$Irl&|Ur9&=uyB(W&e-K#EOH6^5wEH~O!n%T8CpMKE$Lruah^V`q397_v8%1X%zT5L3A +uRly0^PNRrQRz1Y%^*%5kJYy=B5uF$1UB;EY|co`}X-)OX};XPnsAL}Zt*rDiJj2%Su$bye)*ef$#P +uuyAaFC3p!3wsKY;Fc~g{X0E^C6bR|rFj={53FTSZ&Jb^_n?5lq>|kP?IX)Mf*v&I1oYamyeN$6ar3L +_<`78@PoA+JSE6L6tSr?bDt +oYfo-$&AdJpHI<{ir$aXS!e=uYgPGaLRZ0A=;$;#q(gw(o?Ny#S8Iq18Sj4!$Wl^zp9PxWKz;z|9}dh +422r4K#8P0KwAJaw2f_S=^lBmcIwtPE4k9%R(O6rla1qisvyZj>#3gHeCHam^n-P>8wJ6nU&MLc9=nk +wVs-YAZ&tWfJ~g&W0O3MHwdVFtCAQv4X!$9t3>!@kRaLlNYnG9TWC#0;0zVLznKxn`Z2A(+H@uC2Ehk +;U~TqmJ4SV1%SM7AKURy-Td*W+spcJP>~^Dd8Gus+ZL#GwC)u2<4z2{L(wC?B!?Z1Rtt7}wnv3#CmtX +~@mxkWJ9uB?6HtZ6bXx#WR@kY}gT^^;972;Q%Bz%m=8f4{8}8!aU) +Sa7kXU~J+ytlw)_?ndYA4!1U;v6z4lBejr_L96kT+|Wz=SPw8Goqh+U0bt{fRPeE+lF9D~HA7Lw4T8n +l9iv5c|Q?XPVVL-1(wAp8a(axva3(P3A5E3xNM>%6k2Jge#WfB`T`oBi-HQ0{0af6l1MvjP+a@F_A)b +1X0}IB@nX2xZO;qs2mG*&)Ty7@g6tjM{RKkfsCG(6PFM0SY&tc{fUooh^<;DGU?^aNbM5(h@T~dk_i) +>0al*)0`~F$KD}9s2R=rL(NVtp6>0PJ;6yz{`X4^P6V8g=%%CV_h_Mm-;$FNKXNp5IU&mn-g}8IH=N0y(I@_rX +2n_ahc4ldX?BXJsjFnoccyssBV$bSq-nfLt57T#Ni}U9P?bP4EbyDUo9u&Ub$A +PPOGQhJM2dNjo7s({4bW@1FTMZPxfL2Kxi2!+f+~dp+ej$GRv!M(%)X>o3c>w(h~$)!+Drd%33jU50t +ZIBeib)+*OZuuFjBA?$VxBfQI1=4-^`n6OVDgK-k=x5S6>i<*?K<(Fq!VhB7Af?zT(C?i|(PM4dJVO! +{Bq$lHcxub5~4+bQ)FF=&?S=y|l2gmuzM@VPhT&d>F8cz{SSdYPG)!v^l!d(1Q$+b50bD*$Sx2wwkUI +C7`O^tPgm9yQZ%>UJ`YsQ2l +nEr0SbB%lSJnU`Q+_OseQvmsL>^&=l}2X*4);QA*AWPFuHbKOO1bv4rSDx~(t>K217|o=nWtEYGR<*X +g^Jgl(|}OK$eChAft-Fyt*?fTAG-J4<%sHLR_cY@T<0etS_6i=H!AuTZ+HT3jUl>(E{3y#w#*%#YYkX +UoZcHP2A5FI59WQFCT6#z`ffTGjcd9cc4T^75THI#TfzE?EMGwwt0$pfh=+rC?ybD_ +c&AQASr<32C-@^xw}7T)6%L-Efa`HOkhy*+TAD0ac4?U&gR3;bDawmGo^%$}|FEsIfEl$q=Rr5acMj9 +#;?b)RH7QTu=YV|}_jH2f9}Kl2Ra`|B@b%`ldv$x${%U=%#9D0dmwcW&##Gp(z#VCPM1WwM$D7P}6#@f~nd#Q~q~ZkUC8Ipc +-rkhrmAh#ecjKO7nKh3}IfATElTlUjp>{DT4_qNx4yJu34+1HoT@2#65b>q1;)c378Z|%3Mui`^XL+v +uJj+rXf6LuEJ3P#OJkyMqy2^~l*rRDy<#i4s52}ZK8-0NAd1n1$h1D0<1P~|63T4mmkb02D&SsY_Kqt +h_56|W&@jK$;^ZYRq7$~GOcGIo_B&Xsyh +;;TIx9(wC@L{IB|60xcAAedvQXCbxfMpN=;@;%r{s~BX7-m8R1(wBSLk-k=#JbZo}9}Y1Xn~k91Df3fo?)e&7qr7?nkenb|1@6C +Qj|LB$|M@F^HXg=(cV!Qr?4Z;w$7~8=eUf3ZLhCfc*AUEoiDk!R&3C~A<#DD#AY(-Jv67#{q!S_4!U6HACk$8)lnwO<6-d=k>Z5fvwnUmroc1fF*_Tpr(X6ts}icf>>_PxdmIqjoHu>$ +@TmAH@LF)p4VA&;;sf8F^WRkwIVH|(i^llDcWfHBbf(96PW-nByL&!H33fB~vogYMX)=0`=bn4l0~y# +j+I+mlx%bV75=@xkY`n6BMO-FPS-#VTi>Jpghwi(XJv=i$6npef^C60oMaN^JjkYMRWaZ94Xw6di`kp +?9YZAp~=H(eNxSdt(yFtjGNASY;yzly5No68DdN~WM7yyii#XnX1C_Zniq#oI#jyUO7cAA#XVmXq&PA +DSlNX@38UlF$W77SD;FsD(jstFbc66ZgL6WNjFzesH7Ve(TPpk<~W@*H_A&Y>>+#zJvY)# +_$&rtIlpO@otH5TJW$o6`388xJ=If?6TvPRi`xCjNDZ}AO@~UX_a+Ioe>()nv__*N;Pn~}lYWLwW^UK +hkuL7K(Mtv^0EfUX}$KzD6rR_#SA{cFp%t=66F}ZpO6>iK2zLk&;Vy_sFn&%qJNwzQIvn1Wx8^`14Z( +D~bKEHj3)1rUUA4g^**Yf$^+wL%wl^%FICN +>JS~16j*OBw(2e%BJ3L8#87! +?UYZ+BZ+%VZ+?^NmYKzS(uvP9kFu5Pb7yAH6=M3m=f5a<;;JWT#umc71e>&KJiht;9NTKPJM;5?s|$I +06TP6eb&JkFd`_o3ME+_fgBZGP?{JTt}FpULCoM<}2#34dp#_M_i)o*n*}QN-irhu$NOtui`y>wUmGJ +Z(OV;$LUUN-{pLe--BoW~q3i&?S$L2MZ9u)`tljJSyHvc}BMiOK*i`Z=+*LCP?iynb=;{vT^TggZrb4ig-LwTv4Q8 +ryI|T`-UO#3pAnx?lA}J9=D%JnKfxqyJ9_n5@^Q59K;fhhJo`0_ +(lB**YDb4*vi+c@tBMTUYdX +IZLh->+DT@)Z&JxykptrHbqzO`52H6k9_B5hnQf`IWK%x((~IjK*5((?>Nu1-7#We7e%a1tn2VhcSIR +L7v1x~Gu#1%Z(}mr*n!A1+WqLX73sATA>glf2q7Zu7ll7ixmtDd$c$16JF2yof1XLlquGJVI1s4R3Dt +ZK0iE@8TU7-mIzJNFS?1z3I+;x+coch>0iwIg<9#H@ktNNuC7C8qOUJj|p`*oocrN?u3MbL%Z>w@!Hv +4xIof{C}KN#fXe2vWH;2z*{%#ZhF%cDG2l|Gi*W}ou`lUWOj@@ +;J6cCjOz|fJePeMog$w3ZY(ZgnJ_zEj$rR}RF>Ad%2T7_p?)iZFu_l2^v(UK7>?(!-{(=4?y_fGGM6Q +E+spu-K5weEXx5srOE~te_I1B~XTEv6tG2c3dQbhJ8qq+gWi@vujy-F1ICuF)xe4FA%hH#B(5~S;RBl +8LzJo^SRJ0t?qCh3+Pi10MIgrc!M(;VrLc;zB$!?LJ|pl{cF;AOonBejd>{dvSV +Cqkw8S&kzg^+@rO~x>O^qIpIi{C2x9=L$wVNJC*QOQAV@aZFlckp(Zg}XrGR&1iY6i#wnbFSQN9-c!q +3pqZU{zQffboTzh3nu;5wG=3EFQr=tia0Fd(dA>5+23A$oA;#^+meJ0Ec(_o6mCHKTeuBXc^-?irrbd +_io5XxWeJ2H5K7A%#gA+w#wHPx{U{Mo<8IBDpbxGFGt_qTEN=n5xhnDnSXmzm!H--8kZu6hpsQM%EWP +HhvMOxPFCaAWzEiqje>aa`q&-YSK&OUeF8jN9q1RAT93UtIL6b|$Ag;0QW?}FP=nP$3gwtufaObPuH$ +A&2*?z`>w9f{Vuz=x|F9R~gcJ67R=Sf)+fQKU3Y>vzI39Uky2LzJV;pRuLNwZ74!)9wCARTB+hujslx +M2XoCgqSzDA&yHt08Qg1FHa+#VtaIDyy#8}&;^lVBK`6&5v*R{*5Wh2>G~kN9Od&^tz@#+=Us*_Xi+r +rGJ7PdEjPnJ59nnvc=G$7bNtI%d;@r>rALkcG!;j@tXHLNKMhj`HhNm_{qlT%Ts?GY(vIkWaJ2}ZY!Q4t2|I_KgAOn`bINGnbl`o3#bt)Q +|22WZtc<;CD=OvAG&s>cmog3?-?bev2 +lWL}z-+$l2^MiLfq(=OOA3S&qpB>c05j?-?{aO??o{Ldy-J@U)H_a)qz0@LEs+LwZ_{oY$s?-<)#{4{b-c-*=Jy +Bf`lQ=?yMcaX7&1X%p&ITDF1W8%Y-s!!R~zn1j!&~?eKBeV+nXs(5^5XDF6u +TjNIw9$8f5y#}mquUpznEkUTe>*O0 +^@yeYj*XB$E>VRXcq+^K?Ve2$!nw2jpiK%G}qBQ4AlHL`NrYW(3^Y$D@0&5gt+Sn0kA#52T+_Kbxk?XyAyt?fJ2l4@qv>cC#_(=T{F +8Q|lwxZdRz&iEPvAvf}XMduXSH-c7^_P +N`3I{u`knnM$XKAaQw3xj+*#fB!bBcSXndysPPR;Vj7#hG#r4s9mjcK0u&S~C5-k(Sn~K`go)>^kFsB +2;2ITI^%f@FGP;sE9gTC9r>_45Qfzi0_Urd=aR-n+ShT+l#Y#A3AVf|h0_$JUM5{P@c>zP{J}OFVs|x +(Ud{5A1uza*Y_rAmhj)k#-#yGkNKo?HxF3%^yc6ji*Z5=B)dTt}E8$LmHVR^#LjZGauHr`ay@ihju#R +$*nwt7xPo<$O4m~dMMNqFY^zX%M1DZV?!AtH`DbsO89no02(c4>h9QyK})Ja=81BAkX&e*@21zt7&*i +I$zBW~*b?7uy&ZI9FS|xr}Tbu>CMslC3tLw2rP7ttkZ$SqE!(6*pbU+;J!C^e7@F92fzXvY%%)ZB?R#F_G!G +?A0pMfho`qsPMEY1*RkqGQ1blt;oLdPBH#h;chulO*8x1feIeeksIevlfs<$(J?B-7X@V+AluwgSAKk +4M_CMO4inBTbp58vlW7#2@Ln-g}tKiw~LdFv1C~n@zJh(kxAOq;Mszo6Wa9?KF;;1T`$%e>+M#FW*hP +T}IW1Ztn*2k#W+ghR +b8Yn8IGrrEM1(@L9L^kZ{g~c>9BbeSH2fTm0P=K{*Hd#n6~K@uValB4wS9GnnNMnUr<+!*E(?&c9C<~ +?NlZJY34DHa-TWxWTo*8cQA*dZDv&V)zl%_653&i^IV!QCQs~dkf3UwZl|TjCBA6WFL;VO&7_E)Es&Y +O%qHjaG?Ju@aMB_lW7k0iE28zf=E3cOiz{FUAXk0Nw^!z?z4+g%)!N?7-37ltVGw6HGFvLD(TIc=M!6 +`q+~Hn{5C~(X7)YGZ +;bnFjzSuon(C&;}e`XIXFMrL7bxaPO*t!>gC!+XWW?;(XNmOD!;XNq4Br6K>QduE@kf`8(m^{IKD`RgYp94iX(V#l8}qydhi9~7#u2%D_$c|KxAAj)>A2G0n+LV0(eWxvFa0e%uzi&(&%B`uW_%52x~J$( +9me?v3=;Joq$M!n*9+cR3?7vz4j@mB_b06y+WyRyi3f)1rRKA5^6ZKl|L8R59Is~l`F!Bp8ozM`3Uv~ +*zQ?IF`ra)LZ`hvziP&UoA@pZS^6fGlZ@$6QDZQqWC%8{R#c6Y$4Du7|0C2dFJ>fKO2v2LLL7^mCW3C +`D@6a}k*duHfv2^zWQBy%C%=LcM*KoMpT?I$oX2vn^P)owylyY?j}5$uzqjz)c9ZzHpd2Jp +83rr75v#Ku!dleaT^x(OPVPbZScF#TB){qGCcaGQc>y+gxWkC{#zvre4mB>M3on|ON+*+knoypn>J60 +AG-5UmHZnYdskdkm8>7 +wR*s8pE_;5k{GgtfA`s+L%3F6v3;2ljiu(l`evZ=sr^KADCZa +!F$=~x--sxtv!CF#|{?(s8c>djXRcWMLVj;;%JAMTTcT^cDJSbew}=bjz3IWu1xTJiw*2SiL8aV+(XM +A&2^hvwnGjE0QHH}<*bQI3fRV7+ZJQ8b~f4L5dCx9zDy^2yEc!zov79``;2yHSiV5yWF=B!q%}(GeE= +Sl0BO$=K#O?-&?Df3?hkRA(selvg4Ftu*~RlD9xd;9u55ylyPIHV=GASF5{in~mlef(y+~q`iIsDN(9<%>GkE6{4-j@m3xWio*=NgF!5KUl7rm?Zggoz%p# +`P+`-d^ip%?%u)e1^!k`C^iYSYb6hPx)x`#CI9s%r?>05R7nBJQD=6od>IcWxcivOLgpT^Z556z?I5) +OCI&U$)tx>uQb-K;UPrWB3XqD+dShPEQmDHYe|hCQjfjWHy8VdEL?YNhuY+tHcxsVfh8d +I9#u^qdJgz}o3U-YXZMHx%$iD%ak9l;g21Qd9Pu_!eP0d-)-o2qvx}L~Z65zVsMhP`v=F5xDhZc>ne` +H}nA7e{-oM$hsRmh^_F9|gyn7uoii~GUazzyw?cBh?F!kF!?cD)AG;n;y;qa$DaKTD`QeCY1V)F9K7? +}(ba?7YT&w$6mujARA(WboqOt=t?xsOx5)u>*?+2)z?<3yydF$nd#g60eyw|QoKaE$UjNjLTV?IzU~d +%5T%C)zyvJqMemDkub!G><0J1uMMspE^ak@o${taQnKi++`6!n`gbxvg}yw&`++k4B?llXU{`>sBtdg +mSM#*mIoxBa1>+HD_b?pZCIOtOIHl4BCe;5^C{Y)S9AM^Wf$ha=r#{>$C_{%y}g_j+UBwC0JSiq*hnwc7li-|C~m +k_qBV4B^C0#`mTis3$*Ofhn+LEf2nwH|Ui3V#tj!bGM_~3VL9aP>G}A|oVbAgn@FI=5e&=o+?@O@ggy +1yxxp~#tm*=uC+%QzLTJ6BKdFaW|o>@b%9{n@Ff178v<5+0y7XmtL?AvoqNb=zJ2UMIFlS|q>y#4X<= +i*~K;i8JA&BNW7?$n#P|9@lWw%xX_rRi5;_eDBu^s+m0Y$v&-BlQ<<=7;#g>3 +IO5!_Uy5G@To5#*TvL~_}&8OY_@D#_`0nA+)$+FE=?Ev8pEDTpcm^uMC9)P%y2=YB^6dH64(A_w&3RCW2(6}0`^`h+npH!=4araO#D`hY6paOEreN6+S8ku77(2O0%0T4h-(VEmiCk}EWxNuILY +gn<(CuV+em4iuJxF5me(bvkhDFr9m9(}v6HTI3+PkCYFQl&oIzM8OH}6EeL}*^}e4H)2X10 +N*J*s_Qgd_YF{YCM)&>b(#zy1e!Yly!(5mF14h!I)J^)>_8}M6G`s?>K?}VOZ*}?4*St5|6Jgs+yjs# +mDb%sQ?Bz1h{pPJ`j7Xn9*r|U*n!c;=WmL&+*L#M-?k&G`G9l+s3L9+bk$Q&IY;vdJ +qDU9k)0(NJ@xw04n+!^%0;xv1bIKoTlbW-0wyDn3;6{2dR1H$`g9F2c8jBbG5O*a_ffV1_#KnFVp_nu +VZpoN;8S#i_oEE`e3I>qcF2~C=luj25-x*}4s*~I{OAJ8h6Qh#c(mui+A>^!;oWZr=d=`)|il)!g~%7 +l#^wtk!amZ9#WtZ9CA>b3*!yBbt)MqpM>(R6@ypO6UBPgnl21G@YDVR=SH1K~3u-uv=CbYhK-`NAH_n +Dm)rUXB{S!S-S-!QgRTt7~*uOvXL;54g-wS=otvqUwySYIT`+0C}IM8ba6TDt%8rr~~@DRy#D^*X;_G +4(RV>!BDHt5eM1Ld-T20Q4LP&c>33fn!k91hP*~HNS^5_1P^hPyJOl5YnRP3rft~=Z_MwbwxtxjT0arr_Wk0e4<8Dze`QLUHv;eIp?$C@Lp}&BjxwE6ndRVGS +KnjEsH2NSnJexfQ}#BxMg~LrUuAoIgW6dX7CVB$vS%s{3R*z5(u+5uYU|U#rZOzkej1|-2o1M+#h%S@ +lQ{X*^1N&&g;>WKMKv)M!Qc3^mjigt#u-(<;dezA;ldkIk?cNm)@1T +)70opxKwvxI(vqaHSff#jxg$t(x^0b;7JQjnr<*t(}q7~4UVpPp_1wiCs;bX`x +B;}^LRjeHzQ3{;tfU1ESZhG@00xwEO>vnmj9`|B3?;~=dWV#zy4?F50v{u$VZ>McRGN>FNh|{Rbe=Mg +~IfI2D$jhPF`@~mtu2}6kAl+8z;7Grvn`PG~U+jm>uxoslC`%vm&E&#%l&CKFap3>I2)aku=hB9T4Qz +kz3wP2Z;CIiIkgG7TUNHmf&ubq)20u`i&l +R>{BMXy|%ek@V_#v__R0g&DUI +gfayAQ_7SN`A)gIV+&$2%yTI`dth8rG+_JWjbX&Bw>CO#dh-bl?m@tF-L*7T@|@i!%I6by@xB*rS>Ln +)r**R!MdMeGk>R{ZY5qmFt~I&KM@3zlVB8ztuY=s>0-c??veTb=Sntb>SjUOE(S$_kj}FWD9LlQ`e&Vlz`1?EF6aIX!p34oFN7ruxI1O#SX;^S)&9mDHoH`v%O3#!-X+>r`iIs;I|k4%7CLV4TqNMfYA@>9A~Z +e)x;v5L$G-z-(2+UG*66%jpG|lJ@ctMx=4S0Il4zr+uGoYoyBP`e&u^(8b(O@cdYwaON>voJ3ewZNVx-#~qjg1g^pwVyQHRRG`BMxfhkYel~fc<-|#Az13A543kC*{acUa=4(oD?e$IIdNL +N6JWg0yA(3a*718luMTMMgCu)}RCaSW4)Lk$8tr}FPHg6V3(BeU@c=YqJC7-p}Lbj7#a(^D6>6{x7^Uu0n>dbvi#W_=sql4_5rMWuOc$E?zp#O$Sy^&Ugz3KcC^WGLF`R@UrtY(9 +y@@!FXKNVcmITCbVb=E(4BMq)@Cj^8m7$+etwNNl57|orEKoLAiSH%E>Q$X4eDHM8PxY>d@SRW&cF_+ +?@_#d^H!HH=1cff&{>5r2Kdutfxq`jNCTJbplwbsm2PMQ1m-a<~ijCYy +yTkK+xydJfrHl7Q67Ze5%-eBAh!n*bh*!O9irX){#Ixg&P%z|jR9QW0BKD+E)di}B29f#puxdKx^ih} +vyp4#mf^JU;q)Sf?{&S$~jUZgg{Ad1G`Am|6nac_=qP4xY9~;IK)jUgR(I3LP6?pojBXs{d)!*gK!#-PiAq@4Wfb6BioP1AlYl!rL<<(dG>g2 +xR!+?Lf_H|7wqb72l^yz*@Ye@dn<&VhInKc}DDu@D&gkJ}z2c%Eg%3ffGakzjv!Yf1FNtJ2jC95qq^e +zsm9tDKa=cwjChgN7eJWcmsg%Bsh+=)}4AM|Kmsvbbx?=&|-waI&&b1SccfA_+4gH{Q{E))c3x46?r+ +|xdjLyzAF=Db0i&aMjtw3b`8n@msk&xa=hIU1qUS&EBA&9*p}eG>$;c54U=JAe+j!2kI~$F6#4FtsGc +tZndXuU?}U4`>@h5=T)bc4-vI-DIr7i;9(O=}cSNNqYD&b4GpqJzv`*yel}g?z7rQl-#f_+i5SmxSCQ +8(M?+ZBSr(Ec58~)z8HM+$%>dpG^syTpcUy78Nn6KW#Eb;7Q +OvEN3`#C@3H-h0l70+r@G7ViF!)%X!yGt1>i95IZhrn|VH?RYqdsxPWEZSie@Z8k{ieF^fIB{dDKxto +`>eB5-TmuC6yXF1QM{Sk=cdD)(@Z9BO{=+^Kc0ztv`!XW}DjumB2lhhNaUuv~~>Tq(5=uQ#fNcVYOmpE +Nt?(^M`uSe&%t5tJ)g*8`A}!Qn`c``aY+>)&au(E?0i`4&%N^);MSQZAtbY*+5=&KySCfpsBKcU;nM< +0XX-`Pp@uQ(mt6JjRV4cC>O5(O#m_{AOnVbofGx7>eq1TPrSYwe|4xo*Z3*^IQuKTJj-^k$~VEmuc(h +GNVdtSpmu0Mc4>aufb3X1HrLoHWPZmDaae>qqGi!)pSGrR +kB(x2P`-d#Ne>Q=xZ&U9o&k!0J8kkmz1RP|Sp0AADd0Pfun7t%q6bwGQkr?wLDRF*}h8z%9B-;)@g0!c3rWGY(vdQd_1A+y{&?x>*7&kKon5y8Wxsj +D>S#7HryALC+$jNm!97-|ZNMEM-5G@n4clx6oTS@ +(*5T)nJUb=&PW2*N_K|C#}pVxU0*wG*`D=_C+zHdw&ma;i>_w(%E_DA0E-e2~|{!A+t*vSLDyL$2E(~ +%bbEjt6XkWUAYciM4cnHx(BME9tFcY34jUp!QQOfQ+I3c`7>OymB>$IAI&YAj*u<6`FWeU)d8$sE;E9boQ(TtbX_J1EsRblAK>g +Wxy!ut1&6FQULmCU`YSNpR}@Qg<{0|V^Hrj!wVBB1HqWS~&9WV-9<8;}vX?N5pA$j4H@U69XpTbtdsi +TL?%W-KeTHc1_oj0vN&p~xe}T0C_rh+%F!Ulbxa=165@kg;qJRLdD}O>+pcu+4)I@MKS>n8vcex0RzuHbi0S!}=@CL-JKi(HVfidf{>I6I$=-m!iUYUEvg +uSg}#f;q$$KA4(woc{`;)MMuTsx~5R4aTQ0PO*{pU)Eb{?r@h|HsXuYUo1}2x`3gNsDk`VViZX92dOJ +6TGkUA@eku=bnj1kld&@VF8kx9+H0CS44d;mq8iL$r!JfDL>5H!vq+*X; +k>{qR@7^b#pHy3&}3uuFPiLfl=QA8|nUZq50*lr3JKfe_a_6UTu#6l>U@w&nvaFxrui>&|syL6g*|#x;TjChvH0T@ +Y-v!L8Qy#y`wARF6g9MDaPl+MCDdbn6iy)w@aEIe#OqO^%--%Y +;G9R@u<;=6P7msNIG+xFS;r8l^NFOwq0-Ueu_7iNz|Og~!zb+B&Gw0S(Gt$nr)LNc)zgoYq`4_ImQZ~7 +7ESVz+pGgr`uxG0%;yWo4l%rRYHf-FZ#o!WIs*G05YyEzfra7*us%{}+-Y3^4PS1pZ*0BKvL`KIv;s+o_=^vH0rxtq&2(_kxk)=Ut$fX&<5-Q9M5aRc7C`j*C1K +;ImrfB_{j4Bb^(M1DcLUWW1kD{7gmmTJ1k3UL^yBPzv%MU&bXyGeQ^wg*z8i=FFP+P3OmEt`ATluN15 +zc-2`&{MsraX^{lcfd0{B4Yn0te4$wx#&+mpJ+N|ahi#r`2e+-tQv$>;cVdx7*+T*lN#eYUC+_;h+cn +WPkAvE_Bu;P`q@$Ye@X22B3IQJyuA}$djbZV49MqgC<=XwWb8-En +c`qa@DOvk;sS|WPUd>J+hF@QrS@U6oiY++T+HphOz_exDY!FeJsBTw7vs2!lu2YI|E6qct4*vdxQhAs +fpr}3NIdw}6+b$n#_@S(3ppDFU9dEfulbWg5rA|O8va)XcVPoj$`xFfKT;~5s3-y4-d)&97|J~MhRTU9q&SFkef1!slP%y;{GnM1Zmt<(nIhi3QbLFd!;WP`MFpVr$*=Hys +?C7W)jj;ShIr#;`UKy*dh&+KpKVjv+@HFIwqsTojsc0Ta}(*h^cEu5%|L3^#(92MDS&>qUKbejzA|Lj +q(yj7Y`VEJ$l9rFfYImE+1TSIUyKqv6G2*t{R%zYXVWvlq*I(g-6h!{EKzW_-WbI6C|8fh;HKS`{Igq +!RFs4&cg}rrpias;6MMBj*Hc6aU-or(kK0vbEKf^LH`ov;2b!iClW_z(-A_y9Ehbdeh{J3UD&K +qDyK}Z{fY0?lNJNn^p~{vMC`ktt^sd~A0m)0|W)lVg{bBrjF`hZ!i)tjX(Lq+HtPRCB=6l)6m{5~PLk +aqC=Of(7eWHNe0VREq$U_>xG;yCD0Md1URNHC%#qPb={SR6zp?+fQa+n4*WvPjR!#cw(+qCL-J{x}EG +VnCTdof=|&9_gzYwl(Zin=i>^+r+pVl|?eXLI-cCoJKG1pnR7mC` +rtx0!YL6v)@dQeUR=Ci{HgdYY#I?bP_oH|I?SxF+JR +E0yyIkRPemTs#*oc2q!hczzm8i9(edfvLn9nFQtTf}_s7g3b^7TB-@y82y8BG0yYodbsIAw8>2N13Z< +c5Beq>Fw@m=Av`WAL`!zAT3|jS0|K6aUL~$E&f5gwJei50|!QXkA(h|FQ{8vdEM0TA$*2YHhH;)4x&3 +wKn;!`edVC_SVPy&$7?7z6z3dBK-rZmk?)AAV~U4>Uk{~vM|0}$s&{>0*wrbNry-yQ5_?ZAeqWm_;5B +N1L*GPnSv5lmSL*vMs@`BSjD~rWcqxuQ2VOG$#&Oo_#k2<5<_(C7-qV%e+ +lz^CI|>}`tN9IHFnw^;^3w8q_p9rchNc>P}B!%A}Q-Re~vfL!Y#f7O?_5rG^90&+$t3?)qBez?9I=hT +{}Rl_diVQLS5%1TZfx0QHx;Xueg?)n?A>V*Wh5!WD@irbeTmx&)Gc*eh%i1Z@NY?uX0+bO%6|=9g~@Q +@HrhekKqcKY30`ywV;)~+pCUMG4bxKgJHlNIj+FE7_j!bQl7 +5KAO*lcj`ah%%5qUlE#*gc5rvjv&&)iPUSSF&WQI!P60!oM#J`E4@IdE5(& +Nt`!mpF}<8CtT;dG)UE +cs2m@W!P4t0IPf+F8!%{6g|GHoUkYE-J2$(ogj5*8-fRae5iaWGWuzabmlU^ZJ +qnkh@}83*x_J)?QRAjVUwBxw8qM@L4#7L)s0$^iWENw&_^^H2VEPH>CvK@c$P;w~ng4Kv1U&o8n>nal ++RU2)i`lTb~HjZ0j8sgduD +3Md+1EY8ZR~*k?WdbOYsfPJ^lhaDG8{Gj;|rt5#Mu}f_};cEjr=J2_U_^b-1l@nao~u2hK=_H?QH51L +`RC6)}d|SzJJFl#EqPByTu+x++bz-Olx*#2W0PYsw1LML@LylelBnTws*7@D`5+rK=i&-&#d*~&(O3f +j*r&X#woVit2g-~V;tfY=-XKaN(Y>8oy{icP3xxfSvK9fGT$&q#dH_D^<^M^8}40K8qL+y=2(257pjW +T3EyM!%=H*#D!X5Li%?v5Jei-7hyw|H8I1g{6WPFBu}u%XG*d8gegGgD`x4hGyr6$mdy}$)$!f*n4i{ +-L+jF0xwH}!7K+PU8%q5-@+uO=*?UC-OyKRH*J*?tS(2arh8 +pq~238@aolj-TA#b!B$!`HE!0s!xOaz9jlNd0wem#bw!v|cW@#&4*22-+!jQDB?=N2P9X4dE!9z><|@ +|GX1I0p9yA3Y}TY=Jq@}s+FQRb4T2SH=mwR9^tvS7EU(3hx7Sd8N;r07{K0I6^EmdrcuR=2HV|1`jk{ +ogD&XaGwK4HW%))HJ1fHgqBqBW@(UfsaBl4iOH`JpucTvdLO(cr-AEP|P3tOSz(~`lBX2kwKB@M(=tEp!%q+icwWk`HIb+Ty?DUquP0>vh3Y1S3th|dr@odIL +-?2-eFcy!lzkKX#n44Tq4+aW*uXr{9#PO=IRBBHT1t@Q2nAnDPJXRz4T5W|*VA*rr8j!8zPADtYD8K*Jx@fDbPF?KTtEUE{)b(EGCH@4Wd|qb +Hd3;c>al3QlrF7biuS`;46>}w@?l(~n?NaR_>J<}Cc^-(~-SK=me+-u1h_akX5kG6KBKLFrcB_@ui4$ +2X37Hviy~8c{Qmt|D7Moc7toEwfdIs8i6z5bSdh*!8_nwSrcjLJ&Z~?iyKMs3yO@h??Q73*{&t%ZMm3 +a_}x5gLqq8KN{F4LirlZ6w&?gy%?c6(R(B+Py*95;}1-guqg>GJ^2dn9sRN8)6oQ3a<9G05J-$Wm-ac +h2wY5zSumdarbDo4tj_Y;1&EPi~I=hKJ*U`iJVj4Pjv>HIWGlBDkDF;AL(gk@E|G&@1^&&A=8YUCSI82SZol6u<)H0I|Ebcz +2%zu{(;@-B?Q)XzuZ|@~I1D;I&J?I;Lg7YW!$*tVRn_3k&BN3A;Qk?NX-GxLt!jUSaH%cEIh1hRMkm_i7}u{Oc6gr+Y#B%hazsc{(P%|7#wO#w{7jCbPkSx@DRb)xW?yfbQNOwH;El3ZVh+9>j +S_fFX)Q!B5C{S%=8H2rJ8khGgY96ewj)yB4`reSt>U5>v*WJZLb +4~~~jH$@Z3K0`FapqBhCe?%f%ku=+d)jY>3BdCn&%*I=S~JNy9n-{|#Lu>~87S{NioeT!JvPV(kjpLJ +?D_*f_i>#FUheG5Qa`P$8yiKkp>^ua6RpAkpu4*wp*@n)YRCPP1(e&%`^?j_+-7G&Wx#oN)fJFjK|7Q +QxcAHUiMF2;>1uGj@3KU$a)D*9^Uc)9dXa3zSloHVUdT-CzJD5rc`M1ZsGn2Zd17R+E5d3r(V5e{r!4 +$l5Zu*^0(&0>-n_o~HYPQH`$wFxl20Nmk5pQkt#`G72N3s+r2XtS +0>P~o|EbPCnU@&&?auvz3^^@omY~iE2yUWPZ9LxE9knEow+HdcJPMx*c4FnMH&#WkxJg7M@RxtPR|IV +3iUiTyNf4m8DW96QS9S2Wqe?@9TQU-M5IBtx5a_qTgY5vfE!B!!WjX#?4 +n?2k3{kk=k@aeCc8_}!3Ka0oa}xcAB(n%)ko4eIf$lr4QzIov^k5q>aAWBfXN=|#*c2ia_w$lu@^E)i +lckj6cOy&+6=&B`w2BR=kD<-|PNXTZ5uSGaJ56bHxG|TQ{+YLc>Gq=L24mTsDRc8$fJjy~yWEn37JM;*D+I_nlD!gJC7|^KKB(*t+H+MX0ZY8 +b)(nZ7k`)#2MGP$FF()rSR1U{uBpLbs^Q#un@Rv@*>hk*R(T(kTpb3Hj;^b(WS1G +RdVy)_qIwzwaTaZ#wH@155J_P1{1IY;}%kF)i?RNJ2JI;+zMAXU#_lU6M)5Y^+dt=?PzB@f9cSh}UCU +{f#r$@yY8u&GIWvRKClTfPD|^`lHT+3Peew8d-oKeo6>$^bCB!s)?*`l0-{muPh`L?R08h{VWL~gothgW}P-TaElwYM$F#E0 +k<4uC;eD;0*%dP)yS%z#_FLjE{qZ|OWq?{@0)E@^`I$GWb-hle^i=vf|1zUQYMU6J@IZpBbJ|)NNiVx +fx-P8;1Q4IMgl9(|`2k*I-2@@0qXdQWuQ~SM~b6fOV!p#j)G9aK?K>EEHI!MsUgI=9)GNi>BST|O +>=8(We>(PZhPOl(*@06D`l4u}34=G3VyfwjpKEqqri<-x$*;P=UL-k^)pdNYHsUlA4~X-ERFlr={DS4&i;H-_lIMCM0dXcjWW9|`JB!)uCeBCx-hd|IGgVKu+2vX$T{9CZ=2sXwz2)Nt4yQRG8KSk_E)Q{EcpP$Qs0WTpcLmR%;rSo5 +5VTZQfr|8xFX17l~EIAebE$s}9^&j2=*529Smr_*|&xCX4^u#LT0wxQB< +6Ho+*c`7%r+T(TBJD7=xLUS6UPB`<#4@Kc2YNsm37$o%Nx`2q +8S{`EQ#~dvK3AG!l#QMN^I0nZ!N^*K`o`?c=C?&=Q)BT!ifLbF%n1V>BSo^bs5{7B8HN!>WSX!IQ0W_ +5~$?vWPVqdP8m!xCFvghUwjBM0p*&~#j#Te>fAWn&lCT_|NYx{dd@&ejy~`VXJeVsU92~U?Ul{t@od1 +oXSH7j7&5iJJ92r3iJWJzDPv+xr6~4lSv8~Z$tOt3mxXpTcwDucGRA-BFa3#V`^7*1BN;-PvEv|oQ?WxG>^J%KP +DWjeps6p;C9gVr2YoJegQZ!>0-S&U&9vkbgm +0tU2n5)eE^(TSrgqXDcx8Wn8d&3VIAjufW6bD?dY(HS(fPli#Sv!ho%QOK?U%L6Iqst=t|yJKpvh7^? +quyG@b}7W~wkdUDQDo?#?GsWCY^MbII%IE3a!dEl`4|@pCG*YiU;iwvBZ)Q+%*C0iU`yT_0M5xJ`} +$6qx2I?D|fFwNgG*X2 +Gf4+JP+Qn4ttMC~Fz>JWpY0t7BFne|a#6{YjXoL}{+hU=Y(C9uGw>G>K}Fo7p>McoH!{W#e~euy_4?l +l1eShp@u1s{Q9rG8QHXFeN->I>aM*HDW1F4!pc*A+S4MuQ9ug4T`&*LR}RF^jA)fE+$|3yr2csXu=ME +uGy?%j4BS8nrUjZZSB&!(d4*2Fh;;#}lr9;GwhAWtA029!OLEQRQW-3{zcaE}DOJiw%UtksH+!0QPc$(C+BeLD)DHn7zGucU;e +7HjMr6iz|oIW&eP6R>om8#sR2+B=mSWdB?|X)Ez+#381A%v5me~(`m23`6Ei|syBtFKb;nb5(J*OQVwv1=v#e$aiX>{o{e1pFmgu +f>DKl#9?mi=Hv9pjZg&(?7e=g$sd2*}-GUZtC-%qCpH+zpCCytVb4K-=Y=K+|fQX=h8!`O91?>}R#LR +z%CUp{L>ht+4Q=(aMGQTlR*?9ggloP(n%wIqoa5i@f>np22`!tuq5= +Zg3P&vc6E@aJ5_P;LQNT)x0L&;u|*&9`49a4WMoxSzfnJX$l!;XY#v%-3HaO&JhfhKdyFa#G-+`^@{^ +lLY$f{K;QO8_st6JMwA@@Tz}{>V^3(FWvi|pKwPe=@SrAEzxezSCN7P~L(d<#f)*g&_LWmLiydnb#M^ +$g7P&a7>o-;*5V(sV_~DVu%Ex$TA5Oe+sjFN&^UTvw%yWCL-_!DNDs@xcxb>WGp1EnJ@=sU +{Tz4wIKmkg{^&B-}r##-D%a%U9E*h7}j++J2U-j`j7Rs%lXQTPpwv>YR$Y-hX_y{>)p94bY5c1ra +{$$bukvuPGnFmhImKEKm^I_e#_!ng`E?!lKb7EfT-=mpherR1K8HZDjLBYe>f!8V+@cdUPnZ+$ocV$} +5*;9Mdl&gMzg1G?o7ie4eQ>upBb?-Tyg=99zs70mh}(l(TenN)Lfu??p8xH983zKXCs-|IPz}Vu*~B1 +Fx4n#H%#^#+EGz)!c0BcmWbA%~w;5xzA3@8Z7O0LnS +CIq-ACp+tP$Ra+f#@wcV->wtmcPL=UrtyKne5R$fW;@F1GH&4@_g#n$W@m`nq4-k`Nf2nO+o&zIN!Kma>X@3uM&gBHgixMNR?VXS?m9!na+Q;M}}Qhik*;)Tc1GXMoemM +@wS~mH}jcI?3wa&H)Jtoe2_WPa?PD;3^8N>8*o`-DUdv#vdgn4db76jnfqQql~v|qZhUvw#^#Uk3mWe +WszM0+tw9^+)aeeYSJHB>&!Q;`tw55ch-1RP8s)M +1{=1VI2Z78_56cM6!$bBxffRwfgJoF8%~BRBBPZuqlB0%lSp@&L2+WBp}Qx7n#NC>ObPmF%{tf^A<+8 ++u5exhdj?-8><7G;{Gw#)f(Ca#p*GLzfAiR|1R6)k1{EAriTzW1ZE9{q;9TYb9$gYhKdd +?PnmS4K8Ek=e#2DI2voe{DoT(BVwPVC5^g`@EdF37m&E&cK2u_bZ}cr0-wQnybN0NLKe?*>ap9|P!E* +M{TdwuQ$MTL8NqxUp18%w_NOo?$%8+pl(dsq^YCa}8awm%--wqlk&NLRC!8B|;4T?TiW?Sh35f`>$1- +K*n~v)YRonU;tzL+2KH;bU3vJ6-(8uB9SmI$0Eu}6~l?zf%!UC{;=BnslX1JO7%qoXd; +w_>UKZWAK*H?>Ojj&ambQOukcLL4dhpUGLItvw|WGAH?$imu&@6X<^le-cja#A&MZK8WtFSFp>Z57MB +=SkqeTnKJ~oqst@dCXhLK$kfM(K$%|S1Oi8*rx(!`&H{|#IaNgZT$oCW08U^4dWbSS{B`c}JY67sRHw +(H$l)q!Z$BF`G#V_!Bzr>T90gx&F4vPIq7R#ZFk!Rx>3h12MV@JFuEnPcFErdbUD*72Yoa5k$+u#5`- +jHD-^t6F?`s7piPSb(%=)(8^M1AEv)r#vGW|aJF7;Djb9i*`KL+D}A@c#7>K7D2-Nkks5pNC#zIi5W{{}l{2c^=M#(;vVmI +Km3Qk#uh@2ULpoTMdysDy?pIGIbKM_W1z9_mWGZYj_r%~5_CE{B(-a?dOE#gHp3S8-LpAZ+&zMOI=hW +-C{@^wgN=DxCv~I`0L3I3GlO=oV=bwKa1&M{}Im#MNeHQO|xhZYSZ`^ZS#Qw*~^Le<;^9=^GX^_@{$O +aKG&O!7t^gbbUV2v74Rxp1mmw1md)x?RAVTQhR7s{PDs+#|_o(?lh?wkkfu}=hx(!53Q0;I8i{K61F% +gGd=<`O->-Bc9Wc;nv${=KCVaP=X7lSJq~jNVoG!2btRJX#tECa;q-)e26}0~A384)o4L&3d2x@kJ*G +T(5`A9E>sw6L6(r(0f?c%8}rc(yAFR-}neiy(wRpm^-Im0~zRQccLB)An8QBY1y;$l8(TXDnlfQ3- +Mpo)6=J~Mi@{3>zk?nT5B5;f5cuT_0d~VG{i7;t;KIr>g7*fo%*<~lD>k9d}3MrpHWP2Yp|wN0UwH$u +g_o8foA=$`H~NOGV#cmva|e*!7%kV-FUU)ZbH2&?Dr(aVDA|~)8W-MTmr{{0?o9q-p!dj9H_uknFS5$ +RD8#+f%L8Ns@U=|o_kdGlsUh~$izD%(@@}*`e7@nAXw&WUHyUS3N&eLOA|I +u$dy{@bZN+SSwp)(DAj>GvpbzLdw?dLUOdLfGfEMFl(J5LqQ!X;M&Pr&f)QQNUL+gB_pdtA$y*Jmq{? +bbi?#YMdQGszgGjniGnPt0)C5p=Q)-tsU`Yqcv^YlFTsRLEawEMv<r`RKi^p|65J9f*oSONX +HpXW3%WR6lq+@ecb{N0%_;g;oXBds(kooS&tH%xIU=@W^X4itpSg!%~@yT&t}g+B3>zk`$5Nx$xU22RN*>#(twFvHq+cvo~F@nmIH6j=3F +xkp_`bYX*FDkm()IQNA-xSomHxj7JrL5#5NRvU01uB_q+uuYpGzO6q+y9y!>flZtErKER`=T)HDwt+d +vD5Jn?WBu+RVWYMtHLXQ+?-Nh-vM^kS&?ef%R%XwPSyInRKAHf-oUe&6aW};{^YC##Lv`RPdr>B!170 +-g0RLWRH3KfV^x1LS?|2kxw*~&J+M%9>U+W`;a`irTFA$eD2A4sRfss2;cKF4qBbRYWke1>}qvX%TtS +4Egb!_K;E)QP8*#LzZ$jLR+z^9C)W}laiLTnHUI5Z|Fk!z$bGZx-G{1IfBlzSZ62E +c%Vd~G$Pi!*0W$UyRV$n#sg%ldL%P$0q*j_8)MpC6G%*b$tLC#eEZSZUOHex)h?sTrQq$L_70t1VwVl +{(D9w8eL2cG$7Wn;mP1Y*EYU|&<~P$D!W_DAnl=x&*ctH92n{Q4TvD6y_G5ZXY*f$p6r8AWPWVl{glt$VulkT=r&ZYILtLwo<=M$PUOy_fx4*~F74@o9mC;h~o9=@FawuM>Zhb2#qv +P~NXRvgcl5-MT-+MU}!cu4rXfz6@i~6%{RnMtk)K1iTwxFb$iq2b@I-o|Q_^{SSuCv{;oqZ?vhl3Fw0 +9AA;pJU|}+HYrnV@aYRDEt6GlzIZ5sO-sD>L$Fa90~cVW&uUU**5}Ubf9+pLfLepISrf@j%{xZSMuKB +_W?P2m!)OAD>;`*g)iugXhd9rAAO9sS!P<}>Vae1e4ukh$|BLFRQ4Q4lCwY3F$F(CT7QF$w>|+G&!cj +7KU#&jzfKda?Hvy@kqz>pu3>D=Ew;e>-{)Wz@vc!87D-;AZ{z{MIebiHTZF=d&x*~2aod<-JQkY +HKKFW5-j6cB%R=V)|`G7O}n;>+jc{JxC0W^9?fufmnl+*iFl5h;`e3A;#Q4+vVvw*9s`8cN#m74)u+6 +*8dqoLY(;*G9%Z0S7N6gXBJgB`8PY#LkX9soxz&_jDVYm;uHIwR*IQ7x_ZQuiRpUgIVIlk?Dv5J~&`b +GNla&H+GcxqQ68`^#P?TiV$7>SjQ5_S(Ev8;uaP)m3~JePOgH%Or_&v!;PQIx*sH?)7t3QKmj#{|Y*G +H{#7~`v8u1Wnp!VjAsSV=#;=d%FcGfX}a9Go}_?`-cgO>E}@*4$JRh$r7Qp%mE=!oZFu`52&ASfMvl2 +GMBqh9;t~Fs>p8Ra0nBI^QnHx_5v>hDRi34*0%%Ac+kK5-~G=vnhtCyWka +ctw(X$tM|g%z&vpO<+({luv*88A&L~$aQ`WK*0PCC`8#?L0bIy)VV-|><%GsbIo#Nzst}MBc@AIU(3V +_bAN_B@JKhYC?V!%3sI8W$T+N+SQ#(3VATAcfMS_27kr@G%4EqBsxY5>2p3CeU&-y-sT*dAFD97^ZOH}M<6>Nb^B(k$QX#u@!A^u+L(bY$Dd#aOlNP+4rmQI06Bx@+-FMx +5$f^KpZK%DCHw-rIT-ug1q9M2Rr(U7u5Jq@_z3UOe7g{}D@lon#oEkVWQ)2d@~Yx%Wox?k5ISvAKyCK +2ojk@T?P`XvdEX6Mor9oiQk5_15LP;&1&n6sPog=N?y!Ej*c^TcX2Wsh-DSCY?9_)eP^(&!6@_@Nln_?ToSKPA#aTM9n+6)}M4#BzH8#SA#Vj`DL@srai~OlP&s1 +bpPiSUPGHm1(2~-HGcM@}*W1&4nv}&@h+`3e&ug?u@Lz%S7zgnYZlXiaRC;f7lY3#fW9`$xjvnX^VQz +Iks_EBKcqO;b83}kS}LyY34#Na4sL!jQ0AnNX3zla=c=`@a{QClkr;szU5G?cbR#q9plv*7&dT+$|Eg +At02W}l7@I0saMoiM8O0A;If-k{jB^`-xcrKap|WUWghb}6W&sGzbG!cBK>0oJN4!bVr3Z@JLPuR9|x +vVP`Obm8@?0I($?U>uK$Kb9X4)Ok>4E@F>F;A@UTF13^Get+yhY6kQ3@MCZ8OAd^e!@rK9~+oK +EXA+S)z<}tAPnNr52xD$7%gxj(hzI7o%Y5^C1>PUg-`&K7u9pAavtcFH6*aZK=g{vfvNsQ4w0jiQWo6 +$d>Fu-PWoGUI9GmlN?2%HrnRBF`|iwnoZm3I2?`dTrF@gD5o-cjjNpywb`Sq-S{K7u8Qt2!Qr%Vsv*T +K?o89-0H$)GHjfh{0aVJV-w!#wK)_e~cY4^4a))&d8X2$IPyQz-l_dqEd-1{0V?c>iD-cby^Bz7Zk%8 +J0s1?;c@fBGGDm{;=xE^~KxRAOpZqvYw*B8tNu$uX?3A_Udsl1e@uoQ>JC7?f)rm(ZCf(YrS+e&&I|N +s9QWXNKy*Oe{}H2wp4k+UH3qv@QFutbkoHI$=y$zfaxK<`=R_T6SfcBa?5q|r(X@Z*F +^>6|(_fFHZ8SD~xg`S2CQY7eK;0bm~oViUYIZ3cAragm7Y;C<{-;^MD{!v+v!_e0mC^u|+6szaRPwq6 +pLkh9DwvIqas+}vZZuNn#KmlHZQG|cB^4iw|CU}u +G5lh03Ip1uvMmyXh-Nkden_JtXu8e2QMd~@@o9Cb_<0_#ydl)Wgoq^VZ +_EC=cWKk@`V%fYE}--(EW;&`VVuv*s#1V=R)qAGVnw*WX2Sb)TV6YfVe*>wBM5Vpv2%~j_81n5R(itL +J4oq09KxrJeO`q3D_(D +PHnI5@LWkKpYY;7N#dTXt573SpMp~!gY)Y_R2T*IQmK$Zf%#-S=pw|bN$fog~P?P<{RsqRzP(5c(t_A +4EDBDLm`O&Cz=Rrdi#qp4xrcJMGF-1xWRk~qMhnD(+)ZFR3hPPuMUkzksh8h}&**>5U))^f(fM*7EJ-U-dU2- +(koMd~1#aU*+3sxsywUGP;prO6w(;G$GZ5<53h;Yv;e*Z?Q0I&F3y=$op`par$%gXeGQ6~2lQTqYD9e +-^Hyx!IK8yamy@bb!!#9wyPw1(bcN~m#9Wdhq9N3e^lPn!2ep8bN^5V4mBW(=?xQnBVumdOkC%`SLS+ +=Gr{lOc?WRd7oD4s|wWhs7COOMT?0 +bUQ`k+7DP&-?~U=|1$`^Xz<9g__5$A~SaivB7*7zsA}p;bZKM$MQ|B*Q>a>X6t};FZ=t_dS{?8E=4K| +OVJ*>Bu&W=k4xq|B@skoW*$~53jYUB)C%Rj2>aER5)$g0ffy%Wh(Vw!-#KAf +k8DBqX(hf>C{eZ62IDtl~WBNhN4QUdIsT0;6;vm`QjTho%Wu9$=N4tNkE8Pjo(*dtAwp>=`i9f=byx_ +y3;1|3oDXA4~h&i&r{3X#K#eczV{y7n$tgiW26Vu3=t#y3TNap8>HLv*ux2E@l_o-KGduv~?U3A=3 +V*)m@D`-57bUNGKp{BT-+-r+mX!`cJnZ6Z|1|$sRM5!@LeB_#o?Ua40alByEunoS@Rt3Ms?RId05{J1 +^^EKM$8EMhcVvPp|<&Bhb^PrpMb;nu)Qm49R&4O`?o&HAW$GxkB=nliewp| +;t)N}f_ntr_=+ifT+(DWCoXtE^B@yo7vK<<<$-8rEPVhEjF3XpC +`j{R;-oJS&IDf@`#r^4ds0Zqs39WAB*6iQHI+uC2jnC5)*hEK-U7WnbI=;R&s{U+vaKOfMn`oLG)AS5In|DfG3-eC7FEEBQ`$+c1 +JPx+-XL8pdUb3h}EH&4};TP0oVo=37#L+B7Gw5JfZKbsuIUi#wR%IqQu;Lp4D3r+_HepkpT4ZTNu*Qn +uGE6Ud|0nd=t@%E5$k}osp>$Yio5cP+BEN)#8Uvch5%6lSHVZZb-&5@d$*`NtIFH1xHVHn#k|1aQsY= +c&pMy+x>H%;}8XUt(G@g!U{b(5kZU_w!L;pkHt?O~G?AopNBB89@;Fg;2J>WWY@LRo58DbtgjEe?|1; +M6`_jBA{4JS`d|&w;8kp;t6M9nW-x0`v#dtnKd)!bZQyEBs(YcTP3~f0EpqM{lWXP@JJQ(Kw +rQJ?vg%!)r**&ex6cOIS&H2mo2?;{4(90Y{l)JaxP01=e?OqdW_~bj-z5=&)t5td5-=kzDAl|&BTNbP +%|Fr=J^TXrJ1aLgTUt$%oGZL*6CMF+q0$3EU1M{yv*IjTI@2>sty;^cFTZCew~LlUHTYM19ZOKb}siqPqbMqI1L7b@6*)Qmr9rjs1vxE`~ZZJT%kHw8+E!SWh)PL7!G=R3-P9wiM=Z`@yY7Vbw!>Zo88b@UDN8MpbLeT~HVx>}>X`#2vw8#K$9xvbEn`S?PfV(#GqxBO(CL)G@rg$ +*e}LnK+pVC;OhZP$yWD*mMs$9QZfB`@d)EriqF!UjGW3gJPBMzMtc{f8-00@aquY4%#TNFed-hLt$Wi +d9#dCKyDxtFOF4U%2GCKZFAR=7W`g&Ut-6dZQ3lRzdHFDBSTP +bt9SIRfof4tsc2M8)Xs@fN>l^+>R<{xu6`>`M>aU$4ga55pPDE1BN|VbCd5D*a3;%@{jI +l7c1hO|k-W7ra{@@}WlQhYJ(f7)*^sH{wTkP-ngy1+)B4Djt(JD;7vRUJsS2}eu_aTL&astftTJUa{o +nrw^FP}!+SUO8 +""") diff --git a/scapy/tools/generate_bluetooth.py b/scapy/tools/generate_bluetooth.py new file mode 100644 index 00000000000..9d534a0197c --- /dev/null +++ b/scapy/tools/generate_bluetooth.py @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# This file is part of Scapy +# See https://scapy.net/ for more information +# Copyright (C) Gabriel Potter + +""" +Generate the bluetoothids.py file based on blueooth_sig's public listing +""" + +import yaml +import json +import gzip +import urllib.request + +from base64 import b85encode + +URL = "https://bitbucket.org/bluetooth-SIG/public/raw/main/assigned_numbers/company_identifiers/company_identifiers.yaml" # noqa: E501 + +with urllib.request.urlopen(URL) as stream: + DATA = yaml.safe_load(stream.read()) + +COMPILED = {} + +for company in DATA["company_identifiers"]: + COMPILED[company["value"]] = company["name"] + +# Compress properly +COMPILED = gzip.compress(json.dumps(COMPILED).encode()) +# Encode in Base85 +COMPILED = b85encode(COMPILED).decode() +# Split +COMPILED = "\n".join(COMPILED[i : i + 79] for i in range(0, len(COMPILED), 79)) + "\n" + + +with open("../libs/bluetoothids.py", "r") as inp: + data = inp.read() + +with open("../libs/bluetoothids.py", "w") as out: + ini, sep, _ = data.partition("DATA = _d(\"\"\"") + COMPILED = ini + sep + "\n" + COMPILED + "\"\"\")\n" + print("Written: %s" % out.write(COMPILED)) diff --git a/tox.ini b/tox.ini index d5dafd033b9..1e5dcad6b72 100644 --- a/tox.ini +++ b/tox.ini @@ -96,7 +96,7 @@ changedir = {toxinidir}/doc/scapy deps = sphinx cryptography commands = - sphinx-apidoc -f --no-toc -d 1 --separate --module-first --templatedir=_templates --output-dir api ../../scapy ../../scapy/modules/voip.py ../../scapy/modules/krack/ ../../scapy/libs/winpcapy.py ../../scapy/libs/ethertypes.py ../../scapy/libs/m*.py ../../scapy/libs/structures.py ../../scapy/libs/test_pyx.py ../../scapy/tools/ ../../scapy/arch/ ../../scapy/contrib/scada/* ../../scapy/layers/msrpce/raw/ ../../scapy/layers/msrpce/all.py ../../scapy/all.py ../../scapy/layers/all.py ../../scapy/compat.py + sphinx-apidoc -f --no-toc -d 1 --separate --module-first --templatedir=_templates --output-dir api ../../scapy ../../scapy/modules/voip.py ../../scapy/modules/krack/ ../../scapy/libs/winpcapy.py ../../scapy/libs/ethertypes.py ../../scapy/libs/bluetoothids.py ../../scapy/libs/m*.py ../../scapy/libs/structures.py ../../scapy/libs/test_pyx.py ../../scapy/tools/ ../../scapy/arch/ ../../scapy/contrib/scada/* ../../scapy/layers/msrpce/raw/ ../../scapy/layers/msrpce/all.py ../../scapy/all.py ../../scapy/layers/all.py ../../scapy/compat.py [testenv:mypy] @@ -135,7 +135,7 @@ description = "Check code for Grammar mistakes" skip_install = true deps = codespell # inet6, dhcp6 and the ipynb files contains french: ignore them -commands = codespell --ignore-words=.config/codespell_ignore.txt --skip="*.pyc,*.png,*.jpg,*.ods,*.raw,*.pdf,*.pcap,*.js,*.html,*.der,*_build*,*inet6.py,*dhcp6.py,*manuf.py,*tcpros.py,*.ipynb,*.svg,*.gif,*.obs,*.gz" scapy/ doc/ test/ .github/ +commands = codespell --ignore-words=.config/codespell_ignore.txt --skip="*.pyc,*.png,*.jpg,*.ods,*.raw,*.pdf,*.pcap,*.js,*.html,*.der,*_build*,*inet6.py,*dhcp6.py,*manuf.py,*tcpros.py,*bluetoothids.py,*.ipynb,*.svg,*.gif,*.obs,*.gz" scapy/ doc/ test/ .github/ [testenv:twine]