* @license GNU General Public License, version 2 (GPL-2.0) * * For full copyright and license information, please see * the docs/CREDITS.txt file. * */ /** * Checks that each PHP source file contains a valid header as defined by the * phpBB Coding Guidelines. * * @package code_sniffer * @author Manuel Pichler */ class phpbb_Sniffs_Commenting_FileCommentSniff implements PHP_CodeSniffer_Sniff { /** * Returns an array of tokens this test wants to listen for. * * @return array */ public function register() { return array(T_OPEN_TAG); } /** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return null */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { // We are only interested in the first file comment. if ($stackPtr !== 0) { if ($phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1) !== false) { return; } } // Fetch next non whitespace token $tokens = $phpcsFile->getTokens(); $start = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); // Skip empty files if ($tokens[$start]['code'] === T_CLOSE_TAG) { return; } // Mark as error if this is not a doc comment else if ($start === false || $tokens[$start]['code'] !== T_DOC_COMMENT) { $phpcsFile->addError('Missing required file doc comment.', $stackPtr); return; } // Find comment end token $end = $phpcsFile->findNext(T_DOC_COMMENT, $start + 1, null, true) - 1; // If there is no end, skip processing here if ($end === false) { return; } // List of found comment tags $tags = array(); // check comment lines without the first(/**) an last(*/) line for ($i = $start + 1, $c = $end - 1; $i <= $c; ++$i) { $line = $tokens[$i]['content']; // Check that each line starts with a '*' if (substr($line, 0, 1) !== '*' && substr($line, 0, 2) !== ' *') { $message = 'The file doc comment should not be indented.'; $phpcsFile->addWarning($message, $i); } else if (preg_match('/^[ ]?\*\s+@([\w]+)\s+(.*)$/', $line, $match) !== 0) { if (!isset($tags[$match[1]])) { $tags[$match[1]] = array(); } $tags[$match[1]][] = array($match[2], $i); } } // Check that the first and last line is empty if (trim($tokens[$start + 1]['content']) !== '*') { $message = 'The first file comment line should be empty.'; $phpcsFile->addWarning($message, ($start + 1)); } if (trim($tokens[$end - 1]['content']) !== '*') { $message = 'The last file comment line should be empty.'; $phpcsFile->addWarning($message, $end - 1); } //$this->processPackage($phpcsFile, $start, $tags); //$this->processVersion($phpcsFile, $start, $tags); $this->processCopyright($phpcsFile, $start, $tags); $this->processLicense($phpcsFile, $start, $tags); } /** * Checks that the tags array contains a valid package tag * * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. * @param integer The stack pointer for the first comment token. * @param array(string=>array) $tags The found file doc comment tags. * * @return null */ protected function processPackage(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) { if (!isset($tags['package'])) { $message = 'Missing require @package tag in file doc comment.'; $phpcsFile->addError($message, $ptr); } else if (preg_match('/^([\w]+)$/', $tags['package'][0]) === 0) { $message = 'Invalid content found for @package tag.'; $phpcsFile->addWarning($message, $tags['package'][1]); } } /** * Checks that the tags array contains a valid version tag * * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. * @param integer The stack pointer for the first comment token. * @param array(string=>array) $tags The found file doc comment tags. * * @return null */ protected function processVersion(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) { if (!isset($tags['version'])) { $message = 'Missing require @version tag in file doc comment.'; $phpcsFile->addError($message, $ptr); } else if (preg_match('/^\$Id:[^\$]+\$$/', $tags['version'][0]) === 0) { $message = 'Invalid content found for @version tag, use "$Id: $".'; $phpcsFile->addError($message, $tags['version'][1]); } } /** * Checks that the tags array contains a valid copyright tag * * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. * @param integer The stack pointer for the first comment token. * @param array(string=>array) $tags The found file doc comment tags. * * @return null */ protected function processCopyright(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) { $copyright = '(c) phpBB Limited '; if (!isset($tags['copyright'])) { $message = 'Missing require @copyright tag in file doc comment.'; $phpcsFile->addError($message, $ptr); } else if ($tags['copyright'][0][0] !== $copyright) { $message = 'Invalid content found for the first @copyright tag, use "' . $copyright . '".'; $phpcsFile->addError($message, $tags['copyright'][0][1]); } } /** * Checks that the tags array contains a valid license tag * * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. * @param integer The stack pointer for the first comment token. * @param array(string=>array) $tags The found file doc comment tags. * * @return null */ protected function processLicense(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) { $license = 'GNU General Public License, version 2 (GPL-2.0)'; if (!isset($tags['license'])) { $message = 'Missing require @license tag in file doc comment.'; $phpcsFile->addError($message, $ptr); } else if (sizeof($tags['license']) !== 1) { $message = 'It must be only one @license tag in file doc comment.'; $phpcsFile->addError($message, $ptr); } else if (trim($tags['license'][0][0]) !== $license) { $message = 'Invalid content found for @license tag, use ' . '"' . $license . '".'; $phpcsFile->addError($message, $tags['license'][0][1]); } } } T%7wɓt N2)>2ZJDymu&Uy :L]ZfBo1NI7텼 i8qfq+2hbP`$j-(hؕ"bPԐWE+ ejU5vi׽\˄]=}U,ǵx.ˠ Ą$"/6[\b*dv1Ҁ|<\"=>M_CW1=g^&2TcQn{ cI-O(?kE>*\?HXcOR:" FByrI*u79+@!fַ,U<@5vRr6- tZĠ{G7⦱%M̝q 3 r{gWh^ <8awgZi@KA'!\\7X۴pANVfNsgph䭤dt'2j;!H@3ufuC8o7cT8ami7~4MkZ<}+S@KyۦUc-t͉+KJQЯ51Er_nO1զFH)qG3tm  wJ(O4i 4Z3|&k(2~-y*D,n1kg0GGo'tf8ؑ/[c+{Jyb-ߨCzkX&իmssﵝH92ϳ5Foz|O.;6{N'"!T'z6@ py}7׮E8Ype_@KjLq*҃b!Zdaid.HH|qPLb䨼cEsb@ŒW xdrr6dvxyJ*ذh#ok sUBaה[ ?ςkYBh`sP)<${!j- AMYՏb%{gmΚؤso ,ٹYOZf)gKOxʆ avuאWEAgъUVGEe]a)a|XǮWTh_b-~rwyXGRzYCY*84@fL[?XӱT]P3N>dG'̃E?vx1c ڻTX%2GVҤ5+oAqkT(h~ n~<='@B>HuTΥNm~wym@-œ^F=-efaLUskDr^e,4 =OP/r X}+ي_ \] !Jަ? uk$ɱ xVb3JiVYG ғ'͑C˼uzҤ :-c9fM!1 ][nI$ *a;A}%5sf4_+&ҞXk]ҿr|/\]U:[ܟt$6'翐'ui>vl6JX)wffS-aи[ڥœZ@K a̦(y[MrSIOI=&+ic#{vJ?,yy3oŏB <1Pp~3v J&Oic< ;;6nW^ }liG٨ʁTW [_ ^1O75OH'@d6;K _xl%'# Ot3YZQ8<./i@1wEG"Cc 4Zl*{Lhغ!_UKxϓÎ]$Mm<[ *q򱈬rO˕"2AEt,ݣg JY,k|Hٻi]֫i2l*Mf4pG%^>ݛ}H5+VrVNgoF'/Nⶦ(}VXRyw34s(n eqY~p 4RI`O{|0'x"-'|\ӻd0L]h>}⸴njmB ?ݭٓъ3㊄mޣ&UEɇr**[oiW,=m}ala >=6tpx1ޚAMdB5ИoJ2xެ'ЄxRZZ-b*ghJX#҉&j;I}\&Ba=_kJXlbX  O^;ӄxm2Hm [VB5wΌ|A֥2nlme ^!O_|gXTt'09 xuZDZR d5zft%.{Ey 0֫}5Pd*|$9iA,G7? \EeS^Ҭw1\g$j:i5jVW7䰵D;~v ŁZe6ECоL\4:b}5i!,! ~ Y8 i3glpin@ϻ7/9m e>\mzɨMrȣLqp֛O7F %?.1 nB2+PvQlmeyfi˂-9BC@r1JeF2NtI-E} 6)qO'#Bhmia(HrB0%Siw]t"N2g?F S xz7=uBSq:]@tQl?Hht}l/F`,dQIz*2jp"3W՜Za~I'vu5 ^"C7>/sdǗTNᵄQ Bef/{,ǁ-:':qPn?+ˣ& a4k`tqNۯKXo;s79S(k~hndgF,|#ZSaÆ2 10ypsw8z*ju)k^9A(G9 d1y#ZѱNtv"0LG(Ŀs>ʤ$c-QD@^dnTp5*agj Q ԯs>~_jÒr^92{ Va;;YWD!HIn4#;N.+ɗeo-7ѥPN&e&NbNgVX3 I{=ər !x'լzU5%b]ZnO`g pwbsΓ *;A4WGɅe GodhOC5*K^Pb<̗;k.K$P8f1-;DwYi}yX݃r YwԾ\v.:ZC~c%,lT1ʫŖĥF$&UmZy네Ҽj^\[aFTu&1FA=+ka<غœ每HʡG5zw449}_3 qåͲK[964c3W~q^jqPЫ E`i:`xF,"y= ;z>N74 `ceJ6~@#˥+a.|5)=DPcVˍg_b;$?l%z]熩ChB+7vTh&1,*N^AJdq~7"`_TS[GW/kI޵/NR+ d\+kn|Rʹq[<$TLf79s$,݂L;UX8(퐇$h9=Ok]۶U a M_30@G QckbkY="ܡ=HzeFp{ IL )6anʃ;,L㦮~f@8{h8gdAbIxMN5Vj'"H+A $-nU c@i&WshN`avc}1oj!0玬m^񡸂2ąT^nU~MX <Ytѳg>]?/%Zyh>Tgټ Pъc_|g^gےsƷ0WJPdRѧ$}!ˆgs=0Ò4÷y;C'{չ ^K[@U0ئSym VqΩN81Z*5>ʷNҡ7>ܾl>T FI LZzeF{,ySPf4:J0`JZO~[ppQ?VAt GٱKjm ;e/ޗcܫ=*rraϠX f\$H|b܍49z2Ľ99հC0u1LJ@G4D8, ?==n[^/p$1BAS!p!]Ri厌*DX꣹lqw߯[l庘~.TЍ5:3攅*7UE2?ZSjx۝gvLhm˳2ݗh4 %<Ѵ%Is|pv|s^N$'W% ėIMܰL kہe&.5a_NCnÃ?syī N`Û8}N$Po)x-TJ6i0u)W 97+jFF]Gs|a xK? .S5:$duIpCN&R@OZoVٯ>.WpܩhB֟X,ۅ1^C0Pr7Ž$ڛ mPV; PT~dư(c9XJDWDcɷ"d([Ő1:{bb̔NUV=N@KUe周 U{V']e҅Y2M)d(/0ȢAB_c @Ȥ> s0NJGfjinГ] %Z'Vm- ؁zf_3 FQ[r͡E&-;jL#zjӕjz[Z<u .t{CFl^؉ɼ/#Ph59$(wxP[#MfRztۄs Mr[hXOyD,7M { ! y=4_@yH\^S RrujҔQ*tbtpFjP8@̄(orҺ S^.qwB6>#[ܣzئVPgxXm=Rj/APPi"m>c_O)? I5bf+l!`y GGdh# Jb^Zl,LĻֈ>M e)(QJ,ZX y]:7W[ u5FyצQ ])ivYz*e;($ӵgX~-2U@_Ql.rDO12`KLxa%Vu߶aڑ#o0,hz8=1 >rK[/ E_C%«1rjAs m̈́lW;*-amŏvWD*Zۖjwe<=c;һݐx=q3[JOvY򄸀Ȗʘ \L-{*i_$^մ%l-ܖbP^IȕKWxjVrN&dﳛ'ifi܄5̠̙}5cWX-@"8Yf8W2hCAZE=lqAȉӺ,HGȺEq,-| άBaÂG'H'OS3v[ B rDNm}b0o5;ٮd˿qUF ҆؈Q3 d~^dI;ZR20pq{otźwVf,9YrYqe4%$פ&UE# +60Fa`%vQT{{"+N Iξ"D4 ?$)#dLF 5U^e(R5ŻV>X0vݸj\G! FDA2b^ W-@,ZE*/WP6/i7?_Yh7 ! Ŵ0Jw\I= (:zP hmXQov z.@:ɑ&FBtW3yI8qt$d SO}#bPIw;Ff1"VYx5#Uq✷z"Bj{˅| oue:jܪߺpZStn Zc)'",QSQ$ 6ghvxTo3 ;Կиd7Jts6 'ʃTl/ʚ߻PT?yeN""bƊE"9m2'6@ .t7JDn'hzSv^, LTnt;9[h}DO`Sqx,yӲs|)ݖL # lt *caq+s!E`B٤*H㤔]aP[/ 'T?>aXo&S|:WX6+(ȕHjfЅ?>p).8'2͟DW3Mc *+)-M_VDb>aԕbp+93Ouz]91 /n5#‰{5%4c E H+n*P&Ko$EM;"_Y =;UkP)~x-u&ZgOW;2'q1bYbqd)m \/m>t*RA͵(B:lG=cEb24O!DQוJ,'3{§'XY&l; ]xjO}LWw#1mqcVd#7?{Ɣ&pS^+Ce+96ָTVA1I>pc *Z ܝ!u=nٌ#YV?Si'*sLV`j’"Ex~ '5Dg)W0H 4n0P@0:K&PWԮ#`ԋ=1ԻHsdaҼ4f$ÌZ \zXl0CecowRgZOl>%'4Z S-S$z>L!휨coٰPәf@ h( R镆uΗkPТKȔvK4ݺ-wH|b,8V~=Cx2TH"J:S~W< zfX- G $K kG<LslL{5,^Ls!hb8)&H:OL-_"E9 %,X [&[ԑE:mRuuD Y\~r?gp7+PMבQ0_٢+?քtM`gX*ǩcU%jc&"WdMY̿S68@<N 7^C@8xu^hCV̘xiKSz>x()umJM4ObF[/5DgF4 f1劢 g>{$ᔲH> LyEyDF&.{׭$0bo@ʣ0 Ci/߭C!+e]F 4M vxLL'̽{wP? O8"%T5-4^AJ\[,^({j"rTGz8ҡAI{Y3tKB|ck }5IⳲc4F Bl_ZΖ|aov掞'C{>Zr(wR:h)Z]c_r6x;) M:+ X38-`;S&*_w6L}#MjTHV7-4;hR6p[ȰS,bULCMe?[5+Q/b5kyiLVi2[ख़e Nky&6/9'*(p[zy70 1]%q-7,iHXx,d]E4R*4{l Ph˓Ř;˥S&{6]vNp"WTg|w>62H^PI?e2#= zc%JُVۿG-3PM4y!6c-Ja|+?&:{J`bCAѪu74SVޱ[?IZÈsRzY'QUa"x>]ŽȀ;]唧JE &^>O+79K, :@WQ~*)V^[zyN8ɘx2| JgvlJ?F7*a "s&RCqi|r+`'`Ƅrn:GRdW+)Zi$iᱛ#+z{kL \M̍p;Eٷ>q}oԟ1XE")Q^AOo'h#)Z5!x1Y߃Y@N{ ׀М:gE[QLMיB_:_TALd}ބ䫏JA.YXE+eӧiJ\Ew@ \ʊ/5ummDp dB[3:X\b_E8Gl"\PTG0YhN#Rpޙ B8(:_ࠟ!2K_e2cYwgp<5v1W{Y={? }N4~^/o|:"dDDqw%~ݓ8}.3c,,zTTf.w$\CP-܃2RϞ7 ړ_(+=@Uqf zG kXy}.=p wo H%WKMΊ2ҡ|ŘኴZ٪>A!$,%XE]Xcr|Zx͍USddOBC+C>/Rl9kLd[<:8^hT$+" hH3mka`q 6Re-|dG QPYeNx# c\ؚ+hAGI&Wv[ sM7_Nc*hҫ;;%k3C*q|EJeX?sQ lu:>Вj3qMVyyԊNSaVN=Aʝ d0f@Udk4WɪI!GrSZD8 HDR5@/5:=)RyIL5`QKrW9Vs!Tt|vS峚Ϝ qy$@R,:CwEyȈv82M ߰ PxHKJ 9 k:C tvRZ u| e=ܒ+s:j(vM?^Ȭ4ٽ1l=\[eZBӗJ=.@5W-NҚa{kb J.rv q xV jxM~ CK-CrNʓcyj:\Wlrhg]$|W&.‡]Lu2 jO}> bm3G`ķjBL1 \@ ЖOJ0d,I #A7.SK{g.;yc>+ di"@υ f<`sw_'b A/x'+2_]3ٓcsBz񦠚{oVBd3}^kKkA'v% &-AϾ#C>aY@ܥbF¶Օ9ɰA"^^Ƨ,- {"?2y i[(熓Fyk⡪1K6 *,v26!ۓ٘۾C:_u*l(k_& hM4DZeWH @ԛXT]ĠYe|ӦEq={rsEPF&4EPtŸkQvB_A`XSne[s,4FDS;U)q:-1f|t6]8ܘl|J^a5W\O1P&!|wor~g'Ֆζkj*UG-z$+鶶I #Ǝ0 Kc >tO]wlrJ,Il&F6~CVVgvʽA%mF=:%-wV}UO\S6-BXY''!2@K+o E1jP+ru:4H_M.B4BpppMLڀ4GűH68▘M0fٻ,t:oǩɟiFgZA{1'^ǩYv])FKhqE29d<81캟 |$7dzazO/0*UG˟γ-l17"r&N`s:K9 kMȁw4z4G_/4 'ny°~Y^0ڎ$Ͱ7#=e5C*Wo؟>-S5-]JrJ0o]"7dbqmdM n9Fؼ#=/|@FF#*I<H t_ K" q,Ǟ7q8fat}>SG~,[>tҵ'_DbP$J..\i R8#O2J 'LG0E<6HWXlf|/& x.ի(br,pq;ƛR n؄/5-z&ֽ~zmͮ:HL |mc#rm#UIwǘPhF~}g7JSmcP>E`,9GTTAJe[{RyerŠ@ޠGAzKca;/PPZn`HgҰ'+*4_sybKTsd3 n jT=@dzS'O"3CoFXI5{Gp6=g2fH'x-.(q.~Rx_9{$A%/COGrY>~kZVpH޾_Uqs0ᘐMf-7C/:>@o`łhh5PV'juh "`<<':kaU陛=bR]n6{M)~2''ÂH̘# jպ'ؙ0A!Ep<w%xrU`;9 'g_0NdKDQ;FLk[%qP`ݯ(="Ӄ|C{dx2;;IŢ8Μ=0 Ʒ~*>3]=8l6{FA}UQ%O犆Mq^ >:w]BVw{wT9nW9U3{oŕcHmjlWSl.]H{%`4y)NaQJoϒĪM׈zC~SARpIԡ*rjˆ,c.W bY N;\)9kgPvBZИ+IH3ճ+_qJh4խ Bf徘#;N*%$S$ܿ cJ,2C,XTvejA1Fȭ:wD[ǒ4+jyhU(r铹Bb@zMjk`24e,Q"U\g|~nU;ĵEՅM]U0#zɔ.IiGLXISL7;k0yd o1)1^~'4Qtܒ:Sahr^8<9Ih #/ߢDT=c8r*9{/Y/F]I-]I\;VR`4.6_) #GgUPfE nbĻsN- yI<^ѦiU]9\_~1[w?pIޕ7W'1G槆abBW)V-a7Cze0 QNT3bkFyBq,|d>A(-ƐH#'7w,C.hkZP:6rm'|[/׎,cX Haܠy fӬItIfjl3Y'DSr-3 O rW!zӴz)M3Gn);+;.w2]E\9VGN݇FŇ SqpuzǾ2_pAs'/,,uSFZNH︗AC.&kYkK@`Gѿ8S6vBrWsAs.ؙ:7Q,jX 鶫Ǒ9 hfː{p$WbWP-Xp=, =lXF5I^KL 5H$_#\}+!YZYG|%]KG#̞n ݦfċ.RQpI,hhkzG5r|d[Dd36-sKK76  S{e?n넣RPɣ?bR݊ZVN$NKWdZVNO"68x֕~z7:k -֌AvW:kC@yU@Rpӑba1QY3fDquij6 !xXƕ)ڌ2wXbPu h qf%&Ǖ`nv%^Լ.i0ȰJ yV_xNmz5M"Jt M/ ؕ2, C 9QxgAJρ!DUYUDo8}wA! 6# ])u2Vx%C̣ q?}8gtqy8dZmSŀII)%axuzm Lk~p^в{v0ZMq'4Z%x;4Dz9!7XF T>fcY'ނ ]NQBs9=2K' EB\郡 ḳͽϞ73_űD+7./tiLxAqiSl #$Bz`(4"q/Z>|X`PsR0O0m؈T@eoAm?bSDww:5~uotDќS4Wb_A\ Op@ƦG!^zIFIu!g{̓'8r^&假j$g*ڏl]tnIub94W7kx1_kV?keLNO CЃ=nE8U #SoǬ A=k)S=@LnJS ՒpZu3=Tgfb}t[TPuYAtWܓjaGŚ3nĭ08ηxСzZ4^jBu7ҏICDL\t #x]3^ݗfK!7*O &)ڳlonǛmаm1N ]S:yT>=GV6=E%P=5>xN_A JrlF͎$ج {@" +7$M'eMGЕ}vhH,7Qֹ qOB"1q>iɋꠝap55Ϊanψ@L4e+ Zrz5,w6 ?r=(YS &'p ~w/oQb Igqнm:]T|$(qGKo*@^f~ƯFTEn]/;O^mEdGM;_ 3d)~&kݻ/So^}[G [|Zk.0eVGsT;E5Z4lqE\֫޹+)zR-*jKY?$~]Q&,+$]ő񳯳NŵeShz3 y<!8HY`nV߿H)pι=1ƕ[Hb9i+(Gy͈N0ؽ/M%SgmSoP|3_XB9;?4qt-6_z%|i5} $SeٖOȡփ_UNb45neuژ'Dz*[ zgȡQv3U8z@zt;kT%>H2?Yw)۵);hu P.wbq]RZ̃ jܢoQSU/Ÿz^| Xr6K}1iv7x\;Lnc9^@ŷ\"j7H4fԀ|6P`6>t_ǁe]:gW]ͩ9ńM$҅X5`O,.=yi oi3E4HjSUǨ Y?k%h5 C :=g-KWc' Nr&3%$@ Y,.9wc}B9Hլ8Ϛ%9ǏN K0*z SĦ(R%*m3 vx|Dzr׍]CbP7 It:!gE>@w@i)d7[ʘo̤?̪F׋}clUȓ䗗PP\+gXT`6W~!3Uꝙ^⊇ZƝ B$sRŒ~(n.m 0>?/k#f9/]2X]_!jRJ||JyUFF, FxNۤjQϜ1`Smwޣ%\A1feWhX0{|hzqtϭ80 n>[ Bi7*T?Y)iٻR }q(qp|ZhKt`qpFc BkA5{W2V?cu[q'%E)NHףA7kRۿ-N.glkPД'WCn6d_4#i,90ayIijF¨CmblQMܞqDoTtPtZDKfR_\1g5:A n^Na @U"5a#2:jqY}4{s;DzOG@"dҤ{@dYӖ+v߂hBE*VeD'jMb_)3ZW_{B hvFF7'u*ʌ`\t;k&_c4L h?xꕌSiNؽPRKJ)A6t$4<$iœlll!m،5()0SkjFmNEC/Qx\"yV_5Es:vd/9~wsrbr"{/㽡qq>'_xɵ{ӌGbՙ| yoiq՘U3OU(cNt$ 4^ SMz/*qw$14 i,!6/\`~ź5mSFvom@^OP&e2uBN 6l +lKOMh&Om¡ ]+mt \> i.VdGh1sk&hfSS/^Y(?&Y߶K\a l%8") ^0&>D|S Y'nX?Ce(>ji+)^adKc]fS`M35C?1[nc98ӹدtFj&lnQlwÐ#:) 9ې}}ť;F+4)6cpG2hEIOO͙$v~AEDTU9"& =ge [~im~N{5 O.jdvҸ[4|$p4 ̕?X3c Mz*;yvLVVj6vh F_$zf[P\kL7Y4|K꟢p@4/}mE1!S:e8T7fp j m+Gٚ+Iqi8b+!0GGx]x6?%(3.pc;'#~zfmAO+Y1iߌqr>&CŮsn1ѨzV e4@l.tVxYd&sHA)`Mj]b;]Z:];mۢBNGrzMjt iCl?XԋzrU{JA/Ln;D>/< rs8}b!<I\|W^hw,DC^xz"]6Y~|p9-k@Trfjq٤U`qɩ!S*]%:BWdJE37:Y|<7ye_*j71hlyXύ}q>Jx]Jr49XfLZ,@Q<&ZbtzMmO J[%-zI 281OSr_E&@oMN<Ԋ"wu7ttB~C9QD<~[c`D^O gφ Zu=Ûn^`uOO Z}e^E6,1!vuF*JkaרBU z{@6*ٹgTwJPVeWi)Շ.lMO\,",3 |+d9&vgl @G'"+ N3Tݜpۉ5TcR!3f tA(@%kSwuM-k5 Ys$AU^pM[~|`A_ !1S놿Fac!*tLǪ+RTv]._xLcZiJe E-Vxnrʾ٫NڐH= S1n:{ T-!?(S~Y}%?8蝗A)A -cRٮYWQzT0_30\>Vyf1Vtl>r)rvg'+O/2 5bmfN"e\& -4nv ׇ̓O,}پ8"M18IɈy3hnT41!\BX+<ksKd[}&Ƴ6:iggk:"9lZ>žY@ RMY#U FXeRq'xX:]2,=~c~9 Sk!D=%ߜ$zf8BEz><< ,M]dTv$5ك$іWRKöi<Ġlf?{S jٔ+qkmj'@`Ǧ9Νi#_}3)Zc /WCS`)x%P 2;:UxW>IIs+ ۗPW>ML VǒWGot>fўg}%vF۽N񄦉G]m ہ[/?N_}NBqF_1f;&00#f}]N.n\BGvR& vQ飑s~BwWu"g_M}V;^M=? TS[/vn> 98vبas laF^>[G3̙ sp<|Son.0AR-&eu7-O1%z+f.L6wxD0MUՠLpP駃Z'k6 \O!t0ҽրQ[١ DFpŏK&.nfa؛ި:?sg/U19 =шPtpm*T|H6&\V %ǒGxHV9BVKɖm)wCA%:ߟ'˰U&B+zeo,J36Ayz˲>hmϽK FsyVH7 @V< V `7Ix8zu2ZCkٙGurq5ԈyQϻy7`Z1ѣo#jҽWsOaWr0 &!yXn;M@%>3-ioG ΰT8@t5Әe5E%eJl'#ئMՈ*ڌTD>p u}/Һgn|)/.FVivHSt;3>U̪JT_aq?z/ p 5vl gHb;je _N2ֿVR%<ރSZCo)ݼѤ&9Kyu2}BQ G{Vu:}V<]\`vr y7"v#[kcbg& lSə(F9&Se#dҰamHf Al7 "nEW8W:u37=l3yԒEy:g'XV6<`qQ6'멜S-YA3oAv8ڋktsN;ԡιؾϧ$/ 3OA `+ĦeF(} s.yh%C._!-xUt7]<~N@z(Lkrs߿yZ7ݿ6gOB_ q{nz?26=`OY8zVwra^!Stҋ^SÙ8Gw[BwZq[WiYRsjH5;*| uS =Ӱch2h?ej?/Π|Пkm3bu:oW\A!Ce/ddpӵ]WJr`8זJ4a̕"pa?(Y^1Pc1'z ^-WG$+c?9,EIQ[!`,>Xbj#Í`k+Zz}8U..3N))| PNFxT#GKmFuq?xnӬ;֣Vޏ^uxT46Wjk=kF߃9Oig΃VK8c]urP$jN֯he@a2_F ?ͯ) ?M.ڮYk0kAQ>uh5 FIuk$' 󕠮wq`bJ.SU>,B]pvҤOO9/CDy\Ms A3@ELRES{ҵFBYg,կVQ4v1D;B]x[^O#FlGpyG)j#<7p[zf1ܕ³*ɨc7^GR!ghex }"OZ6%}AfQwS^#b!Pm8rՆ1;bF8oLB2$2P±P pԙ#+;KnIfg*@V-wW{I}4FO|'lO BF"~@ Em?͕RQ;z = |q]iz OI9AgY&xݎ TMhf2]'tYS8?&E˯4<&,߱gݝ5BuA UF^B*\5*F3"D"ֽ e@= ְ^ ʣ?u;ʑY SD, G_/ `A6 ]@Q4͠>rfů# X$S#?[o(#^⾷68-qf˓k$8>`g0a7ñn#.?>/) ?XxtA W=Ԟ:J"BFr?Ho}K\pSFK.y@ٟۏw'q)qvfR6q֌*dFwMHIYHci9Uf[P;y'ԢrȏAF'R2"Wonw f+ װձe| 3sVeH)t뤋#_H1REV PӺtFk Ac֑:_Pud};qR\$H7{P ܦ \+󀝛'MnӜs~ F' Ch3Gp~,z nJ(_40}Dy znc*)Z `I^fCox[cߝM,DpUʈ`?8Vi1Y겿52o#Osy Aw44 E'=Hցᜂ95ǥ8LZh|k1;2s='n()SKj5RkAKEaA؎iQh/p`<ƊV/rg9fi¯ӁcUP.,VrO!.|T?'Va,Nͥ=y ֘t;?R7g.<]"FH5 dHGTlz쵷g-nQ,\j즄0'"[[dWfՈ?aR>`E`-e<\4r}@ko&:H ~A_J:m7;UciDYgJD\a.jϔ#A`(z_D:+E~28K̎)T30M=8K1"ӺfЃAL22[Ҙ+)biN87LP {%:7|Rz^cלlVcMݙ\(\j^:1a·|sNEȆMv\n@|Oߧra{YeIXaW>ٮz94ߴH_j6=40 To9t"pχ-Xl맍vs%MQoL2g%(Qrd0su]K0* @oURThN=@& vy5[q0]+8nDaX~9FpuXm׋-AP<)krF aW' gbdzk928(A: mr%~Hd]g*V 7yiV4G׽!U16QV=А~uZzU": p8ED-zhXWG)^0YH fq C~Oxdm!?[[if^n \ywT `ȗL㍜kmOta E1 >P{X_Q4*3˞f\qس0Chh~Y1avO&h)P_7.,ƏBP&\M`jєsFRt*ahJXA1&c.ð?Jal,f6V@/z?"hW|I5G4W-{rn;@ egWT) M옱L~v<3RAG(1qS*Vy>w@H$kbx[ L{[znh*q-Pq3 8ר>tUce)2:^Uh L$ᬦAY u,~?iV,<\7#̄FMaވ~ᙝm|j ?v@C඀Un9I(&YL*]THDޢVg~hĉ^ku @ !s%%h? s_Xl>AqݛηV.R3Z*s2X|xQ1# C3q74̵eݯ‡c84.9%}zJML#[&ah\>s O}|X2oۂJצ@FȪ;.W6ӣ1@P/)DoE7RJ~E欉59XdK1ɯAU@1wV:$j1].!jQh{[ńM\^t![OZd/k-Kdhs <|1Wx[1L/Ÿ&;E~`n)ju˺Fd5nv#]2g. !WM-Ւó8멺Knk e20ʕJTSLdYӐI5E!j5[UWĦYp;U9$g!Qрi w3~qW)J5Sr>1Bf*'XKHi_y3?*͐F H5 lX)أpB@4 QT!ijݽ~c!z0 ~dhS<ѻJ.v8S]IN*'9rd'tJ 7C )[*Oze@PݷhS=G9{~?0C6"-2gO9 GE ].n)([~t ]6[AuMaB.H-Pg>g<4‡2/A+Rqs<[N,S셢N̍YF٨Q0U::h?"U0=inF dEQ=ؼMT_BK"oʟwfCZ*{ (*7~]_hVw%%u+״QAIX sa0b4&"cmK hVxVICܩ;8g a?r ˢ$@j^#K'HZF/?Ow252 .tr#%ܴX W3}^šQlnƇʉc`C̽E2݀ѭ^W#_((xbWҽTalqA0y:c,#AjykvMiEeA ݗw"൵L[ً/;@%s'F!I/N<0VGh$!Mŷ-ڈ XqSxh@E)~iPvyٓgLl6}H| Y4X NfNb%=BnM{qjmZ{WpxvV^?IdYRv 9ar}ALb&"NZd#סqxg+xhDݦ;LBOEMQlI\BP5'\ zR!VN^yuCvXzv N7Y0{@O7'f{ˈç &?V~W#eCPkvd9|1+c/>^aحV¢güVڕ;6"~Xza!"lnV/T} }WZ#j9v #oB1YiҔ>? /?Rq} s9>u2:۹CW1s ɺjl|E*SY%#kԏ(o݆ lcŒ\bOCaaeXtӯTFsJ>'$w>:ֻ̚oe |c"Ɗ? ̚aTUn T!z+=?ИR36خN'q9lMb>(N v)8?Yrkܔ7gxhg g`xnQAHف TDP;o`o+iZz1eyS ,[:p+a~YiXIGUbΓ)N|80S\>)ؤZelILrp\lyvn)ugy+\(/0ٿhT qG ])+dȤ?~].fpEZ$]h2<&i^\س^UtX%4S[0/.PS ;GI'oN1wvcQ^ dOXLbN~ZW'+#(_RxJ[ocUb#!AkhG3wwdvq?.zID3\FbJ \kWן@0s4{D'+e @<~č6i֫I} =S wd5zN}l7BErBDȪؖUO5(%# p^|n]T^Vrwe DX jNGweU_gq1f/h_!vzZQ2 T%׏5KQ1FGQ'.gLL1Xwo؜1h20=Б0LT9u4FTz` Ļp3Ux0e!nлp Tx f7MqLso` /BOXB?Mi1*w?{zWi'y* >v%R7DM;+E-xE<([W}d'>)|HIRo| d ](#kM #Q^Jd4.[ai=!`o|l 'Zp^$h *hmlg/[GSh:RD_U 2{qMK}wv%T`j2zA=I6SL~DJ&C65%ilYf# H$uzDnmmX a"Zlj4 w|&|rP'9 IU ?%sG!ǮnlJ3dx!cӺY=16שU'MUq!EC)?CUűo*&wS0KQ2ҵ+J@u7:?ECr'aۅVbWUNX;?#u%#i0i l52|Dc˶AIH܃Wt#o:bYhr*gƲ}Cj`g+cݐ!ѱ9V۠ xp2.ik CWf:ĂWaeD3xs*JUP q¼ 7j4[Vxyk'+~ReR=֫se&6SISv__,9sd~>XK浬U_5Z:}Ӝ٠U:\4/-:QP-(]|N}܂(.F_/i#LmmB= KʦV ? cA<&6Hϻ8FbQ"ӽ6"bACÚ;BCZ&a4Z`>b0_溽a ¸J ZB mlNTg=2m"#]6OYnYKp>Es(*& f0Ʊ9=Kwrba.$h3| XѮ+76y(&\n0O$m,%gUqJrw-.B?70XY#歱Y_1%l >JyHcjT,ru ߒPЉi[ 9ѫxAlGr7=*VMFVK.+6py bZXEv ;ϫ+_%!Ytkc1zHZUEOw:͚514D*#3 kkGFl!.ܾSoI*sĬ HFߜLE"Qr'6liKϻ*W)ZlBޱZ*P@dž ;HZs7RE>0VZ&$F4ߍ2g)+Q\f2.K]}LLJM-2ݝoPBCk‡1osMcD@ĩT=[I^Ť_&7(4`EB {/i(]b<o 0YxQoK“)&Bt60M4R1VG=i2^YC64tmϓw/0S 89DvRĶ`L; r'˃[ qx ^6mH@ Ml?r|^` ! (8ĉxDgFNw "Mu:_D37.f[z 6tw<,%[TeU;'/kH^Nw;bm'@ԙ;M$U#DNMb_ŚgFiRN~*Oˎ|_^C#̱JaP 4n9^AL%k +#FgB #8R%Nv#v{}v/ǥU)i/Uq܋ =m o'*?{\'R1P>\Kc)MK,x2,&*7_2y{0Kq$f9nNqBLCI؏@ X2ͣz<Jz p> BV0v$ᡊ&xR' >{_[(j&bqv*?#=Kt7KP4mf&x <b--1јՑ+2uàoǝhy?:zzdO_8(@x>Zn!"Q7\(bj|V&y:"v9 ]^/`[烻E4/ }V.=luP%cƱg- 0+;K8/1ͦawmR՟Zʨ0z⋤58 nH?$dsnR`j̦\EchB^F 8 5@mJk|O*Wƌ|PW}p3o\K hh3]aҤ.zJw(7B^CK&ZӨ A]1ϳŝ;4iUV/1 Ǽ$A^>\"{_SU7mH_ʉbo"PEYjdj1 q13*8%؄r{Kl+Q rX$ڿ>}'S>RYg܂@H[:٩-Jy5>qHP&`#>^>τ84(\wԘraMX5R-p ⒸQ$739h^ Xk-!v#rxKx C4@q! ?:l-T#sd9}ѻ z&ՇUGR"_3(b`k ?'ysi2ִ+ܴvf"!\q,w`>08t bK PMÖDמ>h<+WH(w,fı3>Nn]:`?glsaݍ{4@~s-6$x}Im#"se5tjO ʞQ_a],/W[w?L SxlڷY -pKJCǂ%i)z #L rݬi'S~r$kQv [I^TՇASJInF^t|P;1Mlrz|jCylVHχYd$KQ,jw;(5 A/̨ו]'Mmc(=u@T׶%M:fnj85M جY_}79ka4 2'6ҹ)ܪ_kw8E0gfθ[{9g)'6z2;m.Y h;ɉlM /e [ZFAY2y9}[UK_bZdtrZʵCvC"6 jdݖi<aή*ڠ#LimiGG(D?0|Et՜2VeNJ; d+fe q"ۼHN1ץ1J;ˈdeOޤ= ;0<0Ƽ ~游p_2@^jgwNrsMSN 4*AcD=AX5- ZM }#TBm+c/hO{-65rIN@? ,SikI/&zPD6 yT׊d9@dGuز&x_ڹyj$s,UH=ڧ l'R'ɢP@辭-aɗ)]QRfRmh?kW 74v6}ɷABj U`yy`e55sdw)wݎ'lCa_k郅m- 诳E^sǁIq|^+S66buOğ 0I@sDO>5eٳ0O=VШy)ÓLm*fk⩐6 x-Jb"`.>]`;(Vduiud!vn_Y.Cex-pwI0"[m8mi1/|ځD&Ӈ-U"EA_*&@'KA`z30-Fhaԭ*PWkJG1, &I_ϮՃN/3N:#E?f) zX atNq3+k*MRPJE>&^ h$|Ib_Ƒ]i\=/9VPCsD}㮻sC,G⇤pyivo qEb-E9-""OWK 5 $~А8hnYBUUK1=_HjL94c*%H_[T,lO})zr0r:=<29aA-~+6Z)Gx@)s(lƓHnX;̤$$NZ_Y T=zogYWgmӴYo*X Н%мztKmж}(X21b&Y-U顮$~oWB_'w~7xM# h)ch"؍XSvGdJc&:GJ Z) ƽI!w?ʛE;I݂ZX1zFST}oL4xlav-n1W˴!) aT6ob"wo%|A:;x5v4dma]0+$_ڷ17sm e@1 Q$-#ފ_ X\|'( אmoČYIjm fc=H%([qCD${_KϚx9lT\6y^ֈVz3rGWdC,oOsyN.Yc1aE)Qmm;`l6njECW+o .%64Y͒ e ]-b.O(e>[A쩿{GZ*&24"0}ˎJnp^PԆ/)l d0e.$ߤ#tAj)=GZt%5r+nEW%%3[_6!Þfh]is YbPcM"bmB6ݾp<(/[,c7@ٮoIr4.;bG|r~I{F3[n{Šba`(@rXu 9tg0?a!{{2WE;⌸h`tTe3)ҖUjaZn;֍ Ӣ) DWv)TTB?1\\,s~{W f̮80p#6o>m'pi<7WҽO?=/ؾh=3>N,(t6al~P upcmV*@4lp8qsMz ,SܿbK(M6YYd~$]%d[N@i F!Qk 8G 徎5ZAtVU(t7mxN =-oEy)Oa,0733]p%.xE I\Z7!R^+c$B#xr'4<`1haw ދڛ.ok=6wzQa$9=bD,k%Ux9*99uSk!u_a:a[楡^x5H]霮xaXK奙sD ~.#磓('/Bc~ٔ 6\.YȂS 4:7T3.F5>ѹpoJ.EKA}aw?vTfOZ͵AC Nc&E $%>]$4ѱf@}\cT Ft{c G&Fjz|is~뷹?'su KNۦ((YHI+y 6߭4E q9J!=@E9MVK ; dC]cvYWKB9!GP\.Vԫgȩ7113v~\dP_5Eʳ+^h-;iU,KozaS^kB~AM 6X:]3ZCa܏KVÊfsVR_.yd0(.b=6yj3۷-V\Gu4o'0݁,%K ]NGr/+0WpI#\!IwŏTNv)GSXT|,rqKC{5%zTs.M-bWaa3KE%b~+δI׳-DWs6!ӆw^+ Xv9?[xL1$MbzR: /AM4m (EˍUr.!b`ozdݴ{R;O=/ʹӗ &2_uo3R6YZ{"ac`'^G9/z}ō;5!\|/Ejn$?;xOUJIz|5MݝcZ0 p/SiF;uyy!L'pbdiWfݻ1 Y]+`3R^FLhI/ăPc)0+iKʆ*͉P}lk+Yg-6P>Ւ-@-uEvtKEB;+`^:5ȓēk rI2F|pOaItRD3O~>GK:-nDY'b1dp@3eJfuކkXy3/eҏ@nrZYgm|a{SR?l!|0-TfVG5Zcz*b!M/DS[j0Gܜkv.^X^\ LnB_njgk~Sf}ace_<+!ܓ ȱKh,EL[;u50hpasX~,'ݗ>  _bR<ơmY8mf)u& <81>3>V60 "jR6tSAHS)fڻYu &F2,ڮ7xby=c9n{#C/HyW h [c?6}h{"NٱtLq/&oj?m93xLnNq{%Bqt- Ln"ryv #rRb#Y#3 $Lafn@;)M X ;<_ܩ"=}7q~3RBby[XvC姻h1rm {'-drpb)>K(u]T[VK8bdt&;t r8E[¶CC\k `ƈ [nX7v)B]&6#KDI^H2a}7*T\!6L1A! Nɕ`vƑW+ }Π l0 z3-hozKg"o" ]ΐ1zbXB8' (b8d"Vڷ#mK K#qdVL7Zz=_^tKŚdK(k./gl̤ie{s)%֨3䨥p_U[Vdӛr5ly92#KޚWZ >S} }?ix9`Y*y*ѦyӥNAtVKxY-/.-7W;ۋ JS%[}q vN3$1FIyXopx;EPyNj6}%\v{ -s@]GʻIP Yՙx]̌-Da}3'ӏu&dP+ aӂF0SmꘈhכtwȒI_2dB^{16.M`|6<""8&^x߰ =&#\><-ײ "CL,:PI"ESexp禙/2j]^1MgU7h6,Z ,e/ı@Ώk&ɮW/rw,`= =8Ҙӿ4j !mMk'0@ZxT@i4vpm =$Oɽp p$;Ѡ]s4Ӣ/ e$v@7,#[[7TC2R,30$ig3D͇0$WdKLpڥ&^{qV83(fLv!d?^Dj -L2I5uUi֊ ["ڢT#X7Jeh41ڛ#EWGޣ ?h r|lVGॐ5| QTg#s￑Tws Yӏ{[yX&ֽ3 NtZ}8I$$wwj;:(ΰ)@O*9cxA7HzYPh[Qt$K]+55ؤ9giu8I`S X fX PxnI XăZ'T"Ceqx8ǯjb^h.~M8KT\qiBgyElHMd6 q߶s~BmW7]ބa&˩AV y3(S3}ZH58,K Z;\ (w_f:_Cdq#6VEY=8$A4%y_ Csb!H1ADTq &N*ú5%6KKXύWq~\K9yz'~Ϛ K9w9 ן_9 m#,XhY[k\q0CIeW4LHzk4e={b=ģ4)^@4ضz 0>ʋbAe܏OWJp4z/|sORi?04_/ckMϏ;}ZQK}9ݭ1Zu>Sۈ\l[(3 s8wdI8R> TZrكO^:AK@`2[N9 "' Ø܊Z7PK𬏍qD{xse5NF$`9rj5:NpJ duE) S厡D߬Hv*NGfQ1JLzI.xU5߬xߏ.5er<9ERM0jq&c$$=,ߑe%R1M0sߩ]HVףh7Sdҽ-En~7Edq-"byXaFvcmfk$~LkvoK>H:4Is_5zF~ˏ ̄IS鎮s?M8Pa@7`g ɏ '%t qO||ȏƳC[8 6uwH vBRٟoь_lk"_ZG䋝[&  @~#QeI[ (M:zյPɈL zRQ'sv׎uPeiK[`3