* @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]); } } } Eg~$Iw/΄jLLqM)צ**8ԵqDy<7tֶ@1Ch|g?.])G$SlX }jOR=:ԢksK !Ḍ RV){Gbڇ_7,'m4B O`Cep A3{w &SBs >'/'xc$vtwU7$1+^"6ߡ:K\^tRqoOwu'DŃc8TcmzO1$2 @e!RNVmcbGѐKR,H"){ pV$+K5o%{s6ljѢ )_ϭ<V;RvUUW!ƪ545G^*5z,4zh3& [Y%= axGdЏSf؜-cGg]MfĿZ6}OVߎ~w Y稟s*J!+(mJTu\".s.dYW,mh5U "Cդi+6gyuӆYwH:rGM{Ux_(|LSϾ̧0VA6Siv|YSZ r9^ZƉ8થ D-.|WŦ* r&mp&_as+z-b)ڵ>_[OӬw1Fi0;-m%^Y 8 mmI#f_dB#`\֖Ͱj뵙`5ϝw-J֌"2AC  W nCOC Z4PT/ Uh/v)&5ع]Y.68Ԣ>v;OLQ ;SRD8S;K}//=8iEW%`><^l YӼ|CnX6ȂuXgQ]~9Qv˾_{Qy٠sRI4T4Gǐl,p1N|i3Eb1w*mKAaSFYLpRCfXG> tdJd3F S= @G5JG{\f|,bo截ƌ!VW#V+bm^r8e;Ҋpqݷϛ @vODVXkeDѣ)j$(b娖'ANEjȁ"'+PzR -(;uN ΰZkVBucfպ&Mh<˰{Qs^ܓ7u>{3.cF/]ʋ1eKE 0\DRWP79masws6;,5JQ7H쏎%^6`nTsYN}jK]*eW"I".Zx-:eRlh-ݍ;D&'\V{/R+< S3﷧Qj!TwT_3oEs}Oʍ2V5ں/4=xVc^Z^q[jldWgjz_~ ;/,VpgwrED%7;=s-$7nH&#!@L;F,q™@rݤ-?|ulC9zR ,k~5ϖ_ @kZΣkhi\7CpfEof e9!V?H'B ;KhE_=)Rܺh+W;eUlc@8raG^!.w~m}ڐo1]"R r]fsOYa)"pvn+ERk sz}>ɶ;qt\]0G=lf#"| @[N`Xg FBUscZ2 s v0bʒ ЅvBݶy1'*P.->UשհV /Y&b-]܁>7w 㥣v7E݁e3ryJxWL_qz@hpBrx8LnVkGv;GyRɛ$kIH,sj2gzhDNtJF/L`x bpe)a%;lUʄ-!2Mpd8BQdLP,k,w* keR)i0w| Ly[g$qIR-R`^e+_A#L'h]o~D)dg#I Ե^yd4RIV&iuю[m zv0VO+T 3 Y!d0 %cJ#ҢLjqW U?}'4_bln;;#H +m)|#̋Ϧ5h4=8%MUd"ϵ*=WˍԄP,,酚u=K(/oӸS"DKD_2Ӈ{}DV\hCz~,N}yR`N030i'ʜ̝mu@jJZFiKo]ێ=IIoZ8Ag fYs,иFu9L: Q$3o +Ls`Ǎu]f $]ExjҮcZn՛Ԥ)z\-Tm 9 ;? .=:lrt#( U =ho^5٥-xH+6Vjf35fJp`dIWmU%"OMwZxc;4'g2_ v#QH}2q6@D߆.$IMT,L Mljmؽb#f)XYu ^:QhoTkz_+qІ=^ZTᾈۘ_o0z&> XBKY.]'Um=&hѴ n<BN+y l w .S1ꝄKKxEvٞFPQ:etL߃r'}! af3/88ʋŠ M0aQq4B u8ŶRt(3yAנwArΎ6s zG,:z'=QJ hQ 7B eG ^Pc,tv&utab&0WrjVI]s"՞[wC+쇮|bBBeH U`C}vSv{U."xg'.oTee+6qG{*f F#VPVUߍ_Э1b01u3Fq,D;O)_b?Sݵе&{Wz>zN hL#gjSxMi~'՝~s$x)]zQẉiQk NU A!.SXK7,gt(N6z ZRpKz=V.Cro;A*!(ƭIͿD.n??`, |vF]]b\!"H_؈Ԩ糚UsV^zQݜBe7WPHWe;aH4V6+/PiK9 /tZ:l!tڢPM7[Q{pY#RAݜq Qr.|;ӝnN(qPhNliaBޤU$@9w*4lB2{Dlz. :k]))6![w i_ȘYݱ_@ uxكZEz; ZϴdлvD!8cPN&~ 4.UHU3΍J>b)tIDrlo+L+}d=#ooHy%Z-_bCv{A[wPv ?Lt~)whicE6 e-c夲Jy fVӢith^@UI"Wt߃N==n)c1B=lұ]S,ھH=_^! 2x2[)&s_p41`#(o!L/oFH1WΎz*D:JM හq@O}&TC&ֵMkufݼ&2|`zW'V<+_MogL+Ja!yZx~ǺFh4meT]n%|Xa}_P_݉_C+BQ-m[PnyvieH^)g<"˂g7)'Y 1֎4&YVpn˜5V]!(}L&uI_VJOFjؕ8v+=RCkmZ,b #w95i 21P&І2O|ƄޔwV= @&(j u.^@&UST{0{̍X3=:@}*FNdΘQKw02"CLΚ0R|rfʙBkLWANL[KxG%܂jfϛaKyU6+gIk;.Ex--hrhMTe|M\Omڃ̕>3Ҁ 6PZsB+MS0 "ůBQ PMR$+1G!?D~[9MxtpHqPR4kS0kƨURoqП|yW`{xMVǟkiSR6 L;!Ut? qIa*b=oCIyL%O2q4([)iAs[-jkU-*״EݢFɵ<' z+!ÙFõԄM \PR>( `LnzQAj&*剬2H|bZf)'2֐%Swqʂ&vhlr?l-O|"ϵV(IS6V!0X?e=iݸ3Ν5$OaRh}jZWCltC~]XGu Y`2%+TAt)@zbX﷘DultXj-p\;X^Z:f ./1yl&rx&=hͰ$G3 Y6jsAI΅ڧG}l@4'ĬD|D4ō*.rn20Sb=>E0E.#y2)_MiWq \9rԡrWMsԵgvA7`xkX„;Hs1{롆[DTʅXUշc +d8 Hj^CP >B5S-dVw %'b0jjG0G%V;`1\DEkGn*I,dz0WoAeIl$c/ժL?j ds¼籮ڻiW|-LUH=V׬i׹P-6hGMDTfb¢Hf4}\5#2Rd$Lڀ9=,)KlaʹXn(|ّ{W3ǿL00v:ҝp&T1-S``{!ؤ3I* Q* FڳU+xuؿaSka60Mm>~u/=WF:F:4ą? 1A.Aj<bb1%=ׇN?|߳MRv?c t=/ۭo۾! PI*,Mgڿt0{{p>,`i'貪Tƭ4X;|45<.}xjR:wubb6'QX`}2u΂J`ve`PL8-q"C|͞ȒE9-J MCsFʟQv4zOv+[*9J\k,P8+8RLkz%)-(īaй Mrx> hE ؕxdA;0TTˡJ͆QT0 G!\.Wso %cs__d1=¢|_M6!#f-FH L@=1%Q^4z5eɡq?gBG]lN|i7ȧOe7A|=Ԩ@&`yNϟ]dZ=#,<}- @E`R+\Õ )q5nIKF\bCG O2iD8C1D`ޖOx/{JPvM|9|4j~rp#Q\OW7wMLҜ ![-YWdW2gl^3z7]#K,:]rӖcxO_;+=|mIJ["O4O >fw7& ިz&Fb/N21 uö:zz0aYl>r}EO(jxiöx]kga1fC|cVOlG_WXͥ=#%)1bv̟/~w=L)d[>>F .Hq`nnP? c-qʣAAھ!U.]X}|YUUH%:<5|?(h$ҴVfsِ*a~ԪUF˚2rܵE(LfH%}a^YcZb%8ȕ KD}18,bKugȡ$2Oȩ^hQ߉FJ-OX{+M@ #|cm1]RXLxF0.Xu(`aGybD㟬րOt$B8 (BΞ-,Wg5IR"[,=?j,}\p JĦ?hG㡍¡mQK[^0)>LjFi_J)'tΖ4ۊK5'E6U |7pj5NgHHi>A.݌ b apS\C} r$^$JϨSiݢj\XuILq8hd Y3ΡL_qmN(v8<7ӣAJj5=]Ic6*m{Vq 1*qU^ h|b3tgV~/)e+%?#Yd߻3;}` 0|v濖 "cYhۤP~u$;`X'opzpz#72Tiְ<4PSC9tXy=kUb[¼M16ȏ7^z/C-IXxF9~tc3}^fHG3[nYOU?ʷv^wuG(#")I#c`/  NM׺r 2v"$,Ӟ%4JDn&dՙS˱aXO$:qQ{M[WEݗ~hj<beXĈ?$y[]40/kԹ1.EmF@i_wm7lj b֤룾aф^c殆Kf"^,.t\ JjO`#I)=5kxklID0=RKbPAE./̭hd.joĭ:*n"!]3]2LB#LQ]Y%x&}Wpk,_@o}8T%F8 .[L#xARe`=uM$-獬aA}Ɣ9{-n̪x: eg;œŃp|kz3/RY.UvGEq},?U0ҁbF)ýq`ja< "]mi#K(aZ4/~д+qˎ@0E]\ڜrvvCK^f#0+xJZQ*k߄0[Y/ZT*^ztՔےt(2IWDSVGo?(<7*ٖ*?LߊLGoSs_Hբ|Br}hnJczL]@Y~pVPg = tT7%CVwl#XuȦ1 ,6&x{:M.M3Sڥ0ߏ3NT+9偡` }Lv֩Pp?r'q|T=XCH;(s%,ga3[w0K]LcZ#I >Tѯg3 ;,2~eTs.ؔNPbǔCNM@G >,Fnc܇!lM\2C-RKzRč}x?(ӂ9>%IXpkЭ-\ag*4Ne`LXj/| Jt(P̟‚ܻU#>NZAl<ǺC w_UC#0Žv|\~"=k;c o!sQt]$Ar`@q{-s,썲͖Cl]Ew"fYKs;Oi%R&p?4%I Pl7PwJ##(}}^\yHI8nRjy7v:XAA\A4oWȢ_W7q,&`PV8qq:pWbdy9 P ҫG|J>})r!r9'CK (;?O<荂GfW`yUcZEk͋ZahQ}L{zĞXqsSi}gSq/=!:R &\`f[ ҵKTo*<5,Nrb{9Ł8u6]._βjw€̔|L"TIj۫{ pڃ,Vʺ\ <$` tW'4 `܍X; =.u7>Cw Q ϼ=AVg/y6ݫa8OYCU6rQxl(!\:s_H:?r|)RO;HҸYU L-yW*n281l]1\Q>\Rx9Q_|[ٙ]=%L2h}I`Sv(nL 8grb2[yf$xC.z4[CPG-#|ԦI'{\?E ?hH1۱5^ɹ#yoddm;y.?hwv&gy!ن=ɂ6vGɧ&+PU*N%Р&GS[ᱏrQ@_̚ӦIʱku0]Z,B;~ Ir*wqvե@{tϷQbq47^*O[Pn *&L2sdrs,iJ'H;c 46`Q2D- ' ~%TJ.* YJ<6 ckݏ]CB]q@JlO5PfVO5D$kER:L:|>\dzFmfjJ _\fb\TҴ C~k2*>̪dXpUOz:&l{Q`\D4ZxƢ^fSFp}]U@:;BGMe30!@ r0aMĜfh/KZƮ OCypGvRby[Hz/O2SX|^J0 ߨP":kNl̃S <BL9yA ~np.2gQDwC# v6[ ?ɨ 8~9TMͰRuMyJ)-l5-`ѧN=zQc)&cfiAȸvL}-/4hZ - aդ:ޥ5\=\qչqz׃ :+6X"o%[\պIy#2/:`SءȎwx''.6B̊^벍fj+)Lb,.nPbY FZʖ'>ϲb^9KMF?)tS !!rXAӉIV >7}0ڠ'/2 @Vam wV%!MzԄ&, V#|6Uj•9;û8mOO )JQ[OD%\KG e/mT7mWQA|Ƃ+|6ro\1`ɣe$u9>c5?x!{fIš.7.KSGX$%N\3Js5 sMUzr# R[SAZ=2}pi#P{٪5\S "ޭ剔"0:_ c_8цMJ~GJsrHPǫk;tfgg:&;fh:Q}q5PPG q"!RRTF&I qqg~8I=>Tq!MYk&\rUB.޳mQcG2FѲ^A3d@OAخז7΁q#׸ -5 *ҕkV_ofeP/›{g(p=ыa+g4>uQ!H5Zhs؉K- snl܉[;dhVm6VyCq5AVس,Q4e$Bq&GS8ٿ?+p|n MNKxGZIp5J., a(čTj94Kyk[/l*BΟ8ᥧssB)@lqM'STcsoF+R^JܹH)LM !!qF}x;@t:)?lQa7H;]3xǝh˺H ;8͒p~ ҁgw9h0IfѷE%,I,MWA}{xQpȩˢA:HDZ3,8#)/K;X5/Һb>:Y \W.:$OpaX2ߛdb`D_;f0%ǚ ʌFڕE Z9q30DyUVRZ};ԶaV0*LksAɢ7%="J4h E/ٚ8gnW~|a6xt6E#VeCTȄc?$r7|w$>~wLc\8ahG59.LrԼn#X~,+ *?m) O)ar`2r- /m3`@|PRӽ4H%h{&wԹZ泰$sb^!ެ~ȎZ-̈́5EI#,'C$GB]YhT!F{xp?QV;Nl1܇nx:Z=unz'#Tc\To#QC+U÷z/*s INk@ZWI"LJ */1߆&#:ćߍvBS+Bί j-d|t~ b*֢R WYQɽGJ\}Xr3Me4Ds4$>tjC Ơ,yF+1MTp':3DV 9jb:ia `1qny9XEՠO/տ~[v(i'ytwHcgv6i=!)HM}81-9wW$>a)v)3-? @>æA2beH6L foT7z)&]PL0\7UaHE x6{\$_LaZ݇QK"mJȭ* ͙55H=t2<IkZؒ7w2&بNA=\VI=Sȟz0L~>Uϻ|~EK3&Gys \+ A\:_i67',h\dzQfYX1(E,эuןt[`7f3ܳa&F?rW;w_%Dآ++ĥMqB*DD1mVvyK_){%EgCEYڥ+|W"6l 4 «BtJ@GcLO14aL^)7OכgKhGN=!ytކ)RTk|hs1P{yt|=drz(iVoSW z`l8pRc[4thNl/CR UQL7GVDkb>Z^Kd\W]j! qKn:5uvIut5߸ 7Jtye*jf@!WXN;)==+SeRxtac|vb!+[Sń~i=\fsTU1wHݵG-xNQL'ᓸ| Lvܰd8(pg{P2\/p˖[erCLe 1%v%! D)} ˪jҪI;zlLl571L&Y5 \,B*iKCguBx 55^]DW1T$[pwĹkI$rt8Q2SƗM֘nE'@FT-c[H$}DŽC' ;տWY) c~7nh,OQ0ࠣ5OybB{()ǼA{%Vʹi(>0S(;nxj%ΪI1)%[k_M nhΦ4Z]GKlz7Fw׼D8}CP:o![__Nq/!fp$&ߥSY<[OrhپvO+lYn|==>1Z9ʂ%oo}8多 )9GI5!NPQeԥ_AoQsfS5(dDl f>w!#J zD NYZXH9C fI;5{Yl(Tqw=5kdn"P=~Nt^c *1[ƇPG8ݞ|[}#'hL~Ih/\RaDyѼvZtIu)e2k;#Tc&<jkw\MX8`wJ=^+ƤqbƒIo*ȥoC|͞r FuX3=iXbbx~L셆Ԍz6٪Uui$so8v*%X\%01Ud)p#{h!zL`%RƤn ܖ5@@f^&H@(i&2DV֟,  i)KCm)V .rY,ibqvA?p" ^p(椒ۆDU7 d\e+}] wOo?@cP6nh涊+79s9Fn*qTi0cZw8Db+U&Һ={̝Xyגʀ#oifgRPq_ 9L|5.f>OLk׵5z}쩦bM6^ e-z fHcj10˃FGzr*E{X-^]9*MKBBAwQPϠq@"wtDDsAU9WeXdeي8źǚ1SӇ:5ğ*%FSnT~*04l^w+y.E];oR0cbHD0]u&Xp-Eށu;L=ב -9,?@ƛKlQS`oZ|_|e~=Gڞ| ļb1-l,2N H!-\пLf0 ƥJN<3d..ìLzȉ9u042HOIXA. kK?}v7F;6ftduZ@Q4Y~[ܱ$%*VYŏAw?H0QrX+/^Bc@MnJIphW]rI xWX;A߰>ZTePk{R,ǜ/ߥO\WPdaXQs|XS34%Q2D)V I5Zd+U*~%' & >;81)$ 9ܗ#s` Q\ [>@؀E2cys߽ bӚ~ꦽ n*G#XjܚrQYOkTvD SbyuKQC5%Я=RL֫K.bsWa>=W! ;{F"FGY޲K[Zн$䠋}sFًIR mdJ(EZER CV}NL\ojNJftǯU.9辒hKGs,. ΎjYoOkJ0cyd@n\Z#{Z4}u=ozJ6_{tUL^`;枍zé՗ӁutiE݈mg *lt?i@yjV~&v,c&zdEO.=Ɯd8Xa U<;5Z#Ben_&t y$zyцAVI}H:8 (?ٲ|q *i]H?4TZ*}k%%tHt +/`\jN&e_HLD;mQM~(Z\W+GHIUC_ 53osVI[ gU |35Y[E=3?QoIẤ ɳb׺.|fT4ϐ]-1>l##pLz܏# 5-" Rx){xͨK҂{{Hlي> "7<5uK-J:6%醳sA,kdAXme5$nj6Eg]xY)&? OwC:}7.#>_L.Zha=vr͚0p^~>^'T-E` ClT?}gn@\:wJ@O$"8Ld$c k\ik^d HڍtO~u3:tF1p+K)8)1.e=߰9>)Ohm$| R2[&iq1* GUYgUuiɊ[Lk"9~G="ԡ 1E|#AvЭ|An&L;@G3 qv Ix-z<2 9ĝdB#G:1⨁!#%]p- qzBDvrd5 aQug*-6 [u>8-}|Pђ8&B[^)ZDž/-q3قX_*h)^ЋW08?b9b U2::DhKΕ9U0BUktٷ7iRs+/FZ)Q=@R1.:4rL!آTI|3KƟ|^cnX]1`4W(#{7Kxƌv[^YpYjbhW/3S6Mq̩:,ϔ>`%{Q6'?T_!1MBnXPpgVi52-~yL+ug֣wÙ#-{+O6A1)8R,i#c'}/ |@0gwR| nuv7I*9ܑ4OL+2 sTr^',&!{cVqyHuJ+׈X-aʔZ VJb̐dYe4 -=!zTJ@ɲ6=QS住/ <YcX.vr1nzHŔf@@n7Ě(z1W1xףHs|*NXsH+/-;!Fb'KBb+ڹU'+`RgoltADmA n̡'hz"r!!VŪ "La:vȹMv X"fuTQ16S.0,J MxiT T=N`(͌|m֌O b_OC!A=HĂE8y^w:!7TGwb eŧ.AXHtc9cD&UQD5V׬lK3m ѡ[`Zm' aSi(]6&-o~̱2@ 6bCdeO"vܞ3"ݞ5P#$kv8lY5uDn|1%ca%{[W=z`m"rIxp 餮|]2M<9G%w3.:ab#% ȭ 5P)W"g#0JNe;0h#~ Zh7b!>d2b0`mU0) \&gA(t1#Ǔ73*og84QPm#v-&!( #sBx(v{I(@Wm q'h$7~%x <k<%5|` '*2Y?DwOP{;'k Xj ĸ]M~^ZOfD^XtV_+HNFGZ^z[Nf>hkڇ>_74egƓ!;(R_KD3 x"."r q:&8^i=;wR4|'A-Ts"4kQ 75&^HejsvyH,Q)k,gW)L4拗Ѐ]CTOvx0Ե,ĺB1Jq3HE9 e>5,H*=ldYmA;ACSuŝ~U9'ZW BFT-o[o{ES*Á˜8] pX!S{00afyWa2AVb9)3Pµoa%8C᫰DW)v`ɵk+O|P`!?m +GTb4 @q#Ar 9|<"ɻHLW\| J7n4b| # \Y(@9UnK}'f[bE,pXHG, Vr;pʛ=CVȇlF2Mj*KMIild᜸t@ڍp8YgaM0Mkx:8εEV뤓S`diGw[Vu9@IxM#ꃌJh ܙN;,!*̼SjQ@7Y%f7|"B)Ɩt]}4q^Ϭ{iC/Hx-=Sj(y4y C ^2|jXs @ov fQ{]Gr^mJTJ>⯫[Cg7X.Ӟ?A'R=YK4!ϣՀxT,a1m>1jR?Ɇ73=aSWOT}iknF8eHP_N R/3WO hfMu6 ~@e;LjiDCp,H$q=&4g6+rr k^gXHľX/vcQ,yV){=XW Lģ'(Od΁0UhmJ.˭9UVmN ~W=ҋʜ>|Ii9`6`݅ 7 3jh*~榯'9'AARa@B|~fRUEYePݍ.ř,l^HҋJNtS2JɃCLG# i^YTyavD gnNk:0R?erd碙scy,hmcV((-E| ^&vu<7!ӛ 7Bx:2_Uc30(*z^a.ӃGDп ~QEE*C*K%##]13uXwA ;D\┾,u_sG: $pN9+% FxK'tĊR ^L[+Owj^2&w]oRGD24Xڧb5yτ}ZN]xd_$LÒi-'faƯa yE; _ꔬ=+_Y.9@>I${Gk߮~a#͕GNuej]\~L bFmڄ*ďĬ[[&MiIGy@L]07 NYK^-Hߜ(%tGN_@T3.@Iقvўq%pr%f%YSBJK Dΐ Lk3ܰ\h8ԙ݂n$@nWdM7==z; |u@rP]""||!PFQby1hsI 9guyofߪFuU /cN&yB$#v+SFٖ/ #ijDep_hBDg>߶`%:9McO K }rcpsMwӹީ2xP>)fzqWueBr 0r]Rji{. :Eǘ{x `,KfgM;/Op/D(^]Ӂ)@r34en̟_vfy%G 9P|٦R2WdL(Eġrŵ*J4Msk&rs8JeU\bd{+,%fgIl.bj(r?pBӕPoރQ>4d.["Ԙ6dܽ(?#'?z>/(>ZG3)"iڇW;)*w;"˅V낔PrM~zTX갅J1j `c; 鳲ij+fTjBȳhюS& 9Sf+.n_Weܼ[9mSioBD{# r }u[:$\\\dMRװI~QpǼЍV1&ľ5 Gr~6(q=C gm▊q.Ds|&*DDF' ^S &sbʵ1_ s*1@!f)E4PSt+85}Q.t]@؏-յ5+\͙:[DJh󛝋=׳, -#cЉiHT ЭJ؀'H ~CؚJ~0Jq{7M zM(n8IGSNA:4&͹1xu})y. }9[%K̒L֌6[Æ)/-_Q(HK"^SO[Z.v= ֛߲6yzI 3]ajнL4h8Y]BC;=1F4Jzd5%b 2~r@Yg{]ώrԯ~F8]:7AHY$~jDb7IHhTBj9H#_ #+j9N{]VO;?J/CX,Vօ557I51Y>+Zõe|*t(l+u嫗8; yHZLyӆ._}f O6ZOKmɫ=KzCDėMDIV\_p஝Vmqȩi+$7e盳Eۤ+$*g\)әcÌۄyfr;9TN2@_!F^Y!v/#azBUgdE\3ٗW|L1Kͧۻ#RWy6`X? طdئ.8l2VQ&=-ˣ|1cdF+ɵDx\M^:ٶXҖX(St7ߪX]9Eǘf\?h (|QۼO8!,11ҿh;YpNy߹Lɵ^C=m͛^Ŝ%ٍ bU1+& ']oFz :`rAv_ULy0WeI_(=HagaZ嬌z*TWV?SKz`_Iaeۋc^?]bK`Ufk9Gt[.ڛj4Q0re3HͧQMŕȹ{_]2)_$2IݝJr`l{? l`Tyy M 8[#c|8?BoPxcMI<9{sIx!8_}Wфzʤ8G `gr5?H*ׇ@),oTKTVdvw /1jGHQW>boU}g)"&X x *c:It%ué. C#_-^݉ڡI[)^K,7:#40j7'1Sm Q ӓ+,K=} i8%EZeTnWAy1] ݳdaτ3,'u {wao%>e ƫf.T9aL^3ݿqn )mWjM:P\.i0SrZH d6 ^olpBLHj{܁=|V[oB+Am#~R"잰1iܖ@M)z3< ?k&BoЃ@GhYj,%Ϯf"%S(R$4QYП"jn@Xl5RK8yW4͆rmO )$)Fi:!op??-Zk,O~E0q-J GQ'q]eoL ;W0\_FsxK_Cw_cj-R&9>ƥ5.W:[R@槮wK$'yK>pm@woBdPؾCwBf2%_vCbX޴*!Ǩ,C8.߀:u׼٬Ce~@r ģ_/;Č(VjWҾnT#虁S۸՞R5'\J[3gR@2~϶u~1m,`.XhЭo+EmErxQ;(># 󺐳ܲSQvs79'aH4 NOFh*a &D~-T"v^Sa}{]vfl5V5Pك=zWOK(](~1mZCذg$?,VtQuF 2m`ZiG]6^vv.Rfpߩ%XcJuV/a \G4gW Bk(1FF|eҫ$B,b^rbvW@,f~jRΨ~+Lk.(uEfG"#=`Awm (FIXdE#B0Fj9f&yXga@K\#;1E`N#'<,!q'Ң^pC?ft/k cu2 _zT/g,sS/Ogld@|.6*2:j91h ժwuW^'SøOPnA n6jJY_~sl#ǚ09?c4:rOSHO%{ڭ%?W6Yx.cRܴƣOƨ0ةTӦj!7[6ɃFH!|t~]S 4N, &X0٢QUAj{YbTnc"K#^:-)aYa0 Gܢ߆cB;n я@ HS}9R(> l~?/,.0DJE*S%>x ] m22ܹlҘ%yRmgt%dwkЮ5͐ >RmrnE4󍍬usARg(DskU ?6xLs#r^*o70;a>ֻhg4كGR$2(vH&>>w&E; g/HS{FExm"IS -dԎ;ETYUkkL!"Ɉʺ̻BaӇ[{|ir }:k3w8(XY gsxGKeH\0 3TI=9%__I$ZNWg LnEB5HF jUd[8⊛kU϶}$Z89*[MG5[|hds  cipt\s;'Նc 49ǨW<)':K)mBԍ KXlT"{܀= q,9j*,sEmՁ%z*Qr?Z":{_`0Ts%9,nu # k?KVf0}~?Nm2D^_] q k]6>'V峔QNO-#Ucs[h%'}c2nqSsrA8k?&v8Jmu=Xvj\l\G)maoGF>msEF?-Lן"bhK4h]N!~b f^ \4NfA!̯~)i(G+ N!H5BCWM NsQa{gu]LMH@̿gp^ h/[%o'#fHQZ( %J^8vƉNZ>w Eº6i43l~ܙvha;Y>}FȃjI8\~&DK}yafiE4`ܰ"q01cȐYDs ,>vm{Qy2flHʑ7GT"H{ڛ{-eoa`58zƄKL?~aR$s;˧oJ(8FD}P ,C#*ϿGżgro@*\1pbiRteJp SLU4|ĽMqc"o@^ 1ӆB݉R>Renc+aK U|h*< Il#(V C-g'ɂz<=Tp @t3zmҲU[]oD!Z[x6ѩ^5/q`bΕ 7Y2OBT}We^¦2OsR+0>YoXNB^˰qeDO-k?3K._aa"H?4و+P xݬ(퓗᭠EP ڰLqAk PԌ1"OP:_y8 iw0ĵM ]uv`[1rԡ-|R^k$:N70p#D[XϪ u<Ŀ$wMrz֢,3D;,1`PebHS, IH?uԢJRe @ҿi%3\Y `oƹMu隧wW/ēJ GF#覛[jZYꇃXCeC$Ffuv2X-qF1BlmM]dOBe! qg5s:F4cQ@5^!i$TUAPO(Hn`MPYyrƃpCc' mV0ǢP}xI?7N'R \Ωqo5PMDZJhs F>%L8حbobl)tCTvҫ42ň즒 oV!LuJ8=1?mҋ_ ً]6n>(܉Q~nc@`4LIkrP'7i @PKC#t3VXZ5hw.]`[#)F`x;\xX* S^L&(@+ZHS\ף.ޘ+ m\@掝,%ѪJkC,pD.u>E:QaIS\ <ب5~/ @uUwy+%CUU1PmRǁ4-ڮ 43xa2H:)\:귩,a1.,<#KJo5iX<9[`[!D6'.TBq\ЮUZ3+Mg { u]UiMmZ[+'*Ÿ-ǍKrЊ{i:؍``yM-+(ө|6{d5rF1ODx6I@ +yA wlΛCd1ff?  ˟ٱ9o9[ '\ Cᨍ;YfQ꿱;HNFn+ӷJ21'U& LcSۏ3Z Օ_ϭh ,Έhd,Iu"p$+Zv@n)m+';y>"fiLTTwdl\[tޫِ'?gP77[;w7\!Ɠ:˭)bJyYa~1. "'Sgɝi Xf^$s 5.㳒oWs*U6٠R7$b?m ,վ0qm6<6ٿр;!=G'BKR,à,=\X,-Dlr,JpY Ri{]_ ``{Ʒ2FѼoc(EcJ}*2#á4f`0 k. b逹wVƪJ':cH ;j~wфtf$rNu yU\C:b߂ F2i0NoĚ1-. (q i!rz\i(θP4|{S&(09LhBhai弟\$%tqU:ݶ,I.6r$?&=df"/J-a9L]_ MJY0 dq)xtT>jLLٕ De9{*n:Sz+%<HTMjjF`DHؽv;W}(C3Qh޻?ԫV@)Tqlzea/X"Zr| 93yː,Az>!fW W0,dHQY*WQG^%:]j Z='֞ L;E+M +`&{f,G=77,CxVo͏-uHƢ۷1|QrHJZ.7qu|4Mz.?*ĂUbY#UcetSAcJWu y`T?>R16Mux1HI4&;uUJwe$VR\?= a]qh'䮩_IՇ\'*'܂rJ7$~[@À-ɠpTutYr LrҧҩQ0x˙U}ccdj׭0Gi?,Xi+^k{t@Wо4K&Ш'=JjROBM|txZK ɛGNwl]/dUԙ%-v;s,Ab6u#+1ޮ T]_b>%'ոaسhPŏYORÛp*Е}CƠsc?@ea'=56UE 1^5"/2;C,hk5iƳS7c@d R9frLғ)B8<>i܃ t*&:\X?ɈoLV%"u!~fr(rwƒ,<>}hE=="Qr-֤]'r+&X;m6#jvu"::Bѹf(;n#Q 9.'yMHjvZ]s%6D|buAeA1*7,Nn ۖ^# TsKجWЬ=Uw, E*kEJ?_ 6SW~/{YMq06"bdx.:ϺGKm+(R'ӧˀ§$ m6}^{gџ:pkɠ2i# 쳸iD%YӾ܄`aWr^BؒmqTh;,m0RR9J>א^VBg'CmCOzLHqcZvZۛQWzGK{ KT1H cj/`o}u#{v "P|I[nAeҿrfˑ# cy,@_&5N6w盕QWj"5z19Tʠ@,ޣ|ӈ{Dq*[| W)MP'Zmun RY#~+pbPbZ]|qp1, JsPH +F nn-qB: BVMbR%J*ˏ9,@ ,?We Ԗ- -F'cYQz42DD]H-^T,\H]B2'"?D@#?hLUΊ΁'u?d?]iUeJ[LzP_Y>7+ TX+|:atch:Nn'O18ǧ sѭNaX# |!_q\Q7KKIQ :XڗtV@,JWߪ -CfAcƉI Ա&hA@ 5shD?'pK$]>iB?6އe9992&Q2$13PsлʒrB|C5ÅLN;DRcv-Q I`?±8J;>y#ο~1H̆޼-V"q@IJپXϊJ]JR_-3[ޯp2e&_lQ`J$buiT&Ǔfv*yycX0❧Eop2Ra,ʽ8^1 ,˒A(]V]r1joAO3tFlV۬R; 4XpER4F3, l̨ӌY'zXIf K00g &%89Y`b&iC+'`[{|[v Eahd&ۙѰkF=lP_?[z?0$UDb'{ѵ?󑆠ΧTs1yTo/:_ 5e- 1,tV&DjB1,̷%wF ùqlx,#;-1?\@bbѐ"sk5T2[4xǯsXDj^Fy u=+' =Pg<7][ Ko#&բNPX,R%Xi-G_:&P{bdv#`ȱc|?ލG||ؖ|gc ;mUz"̓xECPփrIT$㬱wV~XGu.@+*E&7LPe1٪KyCPhJߓQWɖј»nw~laJj a$yp51LKzk){^ݒt.M?/sUڎ:^/ h㼣%޿YP2$Jr9wp>j14R`\Ł#<#[&dPj< YT) 4U m;A/d# ٵ"hۜvH% e”%0G*_DEǟco$) A _'kGICXweEl0hQk/ܾk/>졑(^3u 2iOqZN$D}6_= ;+Mz޵F$<\o<;<"RJ$W:e!5@fYsˉh j| GGdo_4ȩE`Y*Ԛi'eYn3^:1#jL FOG6 v'ݧ,P( *-pΑB"饏3RPt^` @g Tgg\>UN58sꎢd'.뀿_kz%(b.pVxx`2^hRd'k=L$Q_Y323aiM1?i+zTÕ[@: }_ /dz7oP|Jus>a(ycYT>;a8:s`͢7j${V{r֪ R iNij@h0fҁޔ҂F|ȥƻY>Qbu'ZHcr}Jmܭy[{fr+,0\.VVdm \\&'$ g{_g)N:_z%18!S!@,g븃Vor%H-'01Yn\w(v6ʎxIcC x"DaEH K#D|x:&vi(=B&8H1θ7~|:[[I2gj xڟfLW~>_$ U2b]}F2l~ Ч,+Xօ ? i@E !bʉjTVf/>"±nUx;Wl3|7 uu`=۲bȱ6J-ԡVGsY*Q]N*I Y{F٧9VAC3/u+\!ҹ,~(?o'e$eO^%RPKGޙxQzXX"(Ys(՞{O*W_)4. J.[.&{g69y#1v9976MFSgUna˃oS]2LWFf6u!"n t!$@.K$cVpݠ *DSmewA߉} g`n)kH3mJQkąI" ~5qe&Uu5_t\N{i> _DXOG5> "يݬl<`0 L=ٟ,$eec*MeR?Z51jʆ|́ !=MfNtE9 !).A]-?0V#'rtj5#oN]#X8S"TaNoGR:Gz4SIʧF[I&ds+4>Y8|y@Yf(b^z't"QSX&&֗k=c I݂t8829Wт4~t͛OUa/شgd&*x쭅4~m:kJ5=KΆQKB܉[O6.NtDaS'c"@i8fEWrS70**Dg{bou2v|7w BkK<0UgH:uρmpi_Dxsoc><CMο|m; ,DC҈pT mαeII2D=[fجI=Q+Rm0VmXqgd2&% 37YTBh(d p6IahDO _Y`9}5'_w)hP^ >6v4y<[?/ V?2xu4 jU_8XP\,+hDUSʏe9T?}+rSO N:8/PfܷZ|,»邔o0s'uu`IlW9̛7HjkQfWAZ:׷uutQwO>sòvj. ㆺQ%1oh}/XdZdFjVJE_X^@˩`E[ ڶ䊈fٚG7W%u8|x1lMWFfv%beP\-Ui˂Zs' {$o0%?F 5qy)i h.>| g$d@Kص_\`DavH[kYnFGN^c}L8*Ty*VXQ6YX/lgүY/T=Q<)O p/zNNkǓbqjO/:.18t5}L>z7Fm yn"RqJI4"o{Alђ58.sB\. M!z'ܰfm\[y%%M*CuEv^aL.i,t;@\ٱ |^F]b!0h}+t۳(bu ̵;ja$ hЬ mlyVwWk+ F^byϒs~;Vݡ=#bPpuwŤ sQqPT VC̑/+qБH2G5)Ay~Fއ [NƦqQ1»n4vv.AL3Fvz1W.~c^ҽB1 =ho`p:^UNޘE*ɛ1 _쾄:?ɡ~P6c֞|QHB>pi\cjsTy'V3^RD2). EA BC辆o'*Mm"%EbB͠7d-HPgj6"oS%eB^+0ލB 2K"!T 0߼[W?:8!טӮPwuIv쀃ؚ q12rX*n m!tLAh߅&𘚧Ak:RlrZ3tgM͇|`Mtbu˔h(rMvC .T-C?$)"2,vF'θKYޏ :#h;2TKI%p59{]50X>2;6gHv19<*>RC` K5&/̡ dl\NGUϮa '{^Iz$^ņ(-һ?pMg9vZc|emN}TfňpFE4βRP/u&g1. ̬غFTTTi'{NpU+f_NM/jR3?>W,NG9Dhl;`pEtLpץs  ztǦ/c@SjNy)Ӄ \5;>oo(Q,,,]@wt}f<QN䎽I$)>LW~?l <:ug3vwNzH=@._榫g$,5Zey!!4O-yuk̇OW5L=O[)ȌH/Œ,'7es&3%?dJ\,\N)}0YhWt<*4v+h[s`yPK _VH_$1چV9Q7 4#aӪN󱩯 bS1|:GB "9sBɍebU "`>>ia͔o4@  [fy7\Dq@פi?Kb~FeF⁳͍_4 _m ٟ:›)"ρFB05@S5