cache_dir = $phpbb_root_path . 'cache/'; } /** * Load global cache */ function load() { return $this->_read('data_global'); } /** * Unload cache object */ function unload() { $this->save(); unset($this->vars); unset($this->var_expires); unset($this->sql_rowset); unset($this->sql_row_pointer); $this->vars = array(); $this->var_expires = array(); $this->sql_rowset = array(); $this->sql_row_pointer = array(); } /** * Save modified objects */ function save() { if (!$this->is_modified) { return; } global $phpEx; if (!$this->_write('data_global')) { if (!function_exists('phpbb_is_writable')) { global $phpbb_root_path; include($phpbb_root_path . 'includes/functions.' . $phpEx); } // Now, this occurred how often? ... phew, just tell the user then... if (!phpbb_is_writable($this->cache_dir)) { // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload()) die('Fatal: ' . $this->cache_dir . ' is NOT writable.'); exit; } die('Fatal: Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx); exit; } $this->is_modified = false; } /** * Tidy cache */ function tidy() { global $phpEx; $dir = @opendir($this->cache_dir); if (!$dir) { return; } $time = time(); while (($entry = readdir($dir)) !== false) { if (!preg_match('/^(sql_|data_(?!global))/', $entry)) { continue; } if (!($handle = @fopen($this->cache_dir . $entry, 'rb'))) { continue; } // Skip the PHP header fgets($handle); // Skip expiration $expires = (int) fgets($handle); fclose($handle); if ($time >= $expires) { $this->remove_file($this->cache_dir . $entry); } } closedir($dir); if (file_exists($this->cache_dir . 'data_global.' . $phpEx)) { if (!sizeof($this->vars)) { $this->load(); } foreach ($this->var_expires as $var_name => $expires) { if ($time >= $expires) { $this->destroy($var_name); } } } set_config('cache_last_gc', time(), true); } /** * Get saved cache object */ function get($var_name) { if ($var_name[0] == '_') { global $phpEx; if (!$this->_exists($var_name)) { return false; } return $this->_read('data' . $var_name); } else { return ($this->_exists($var_name)) ? $this->vars[$var_name] : false; } } /** * Put data into cache */ function put($var_name, $var, $ttl = 31536000) { if ($var_name[0] == '_') { $this->_write('data' . $var_name, $var, time() + $ttl); } else { $this->vars[$var_name] = $var; $this->var_expires[$var_name] = time() + $ttl; $this->is_modified = true; } } /** * Purge cache data */ function purge() { // Purge all phpbb cache files $dir = @opendir($this->cache_dir); if (!$dir) { return; } while (($entry = readdir($dir)) !== false) { if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) { continue; } $this->remove_file($this->cache_dir . $entry); } closedir($dir); unset($this->vars); unset($this->var_expires); unset($this->sql_rowset); unset($this->sql_row_pointer); $this->vars = array(); $this->var_expires = array(); $this->sql_rowset = array(); $this->sql_row_pointer = array(); $this->is_modified = false; } /** * Destroy cache data */ function destroy($var_name, $table = '') { global $phpEx; if ($var_name == 'sql' && !empty($table)) { if (!is_array($table)) { $table = array($table); } $dir = @opendir($this->cache_dir); if (!$dir) { return; } while (($entry = readdir($dir)) !== false) { if (strpos($entry, 'sql_') !== 0) { continue; } if (!($handle = @fopen($this->cache_dir . $entry, 'rb'))) { continue; } // Skip the PHP header fgets($handle); // Skip expiration fgets($handle); // Grab the query, remove the LF $query = substr(fgets($handle), 0, -1); fclose($handle); foreach ($table as $check_table) { // Better catch partial table names than no table names. ;) if (strpos($query, $check_table) !== false) { $this->remove_file($this->cache_dir . $entry); break; } } } closedir($dir); return; } if (!$this->_exists($var_name)) { return; } if ($var_name[0] == '_') { $this->remove_file($this->cache_dir . 'data' . $var_name . ".$phpEx", true); } else if (isset($this->vars[$var_name])) { $this->is_modified = true; unset($this->vars[$var_name]); unset($this->var_expires[$var_name]); // We save here to let the following cache hits succeed $this->save(); } } /** * Check if a given cache entry exist */ function _exists($var_name) { if ($var_name[0] == '_') { global $phpEx; return file_exists($this->cache_dir . 'data' . $var_name . ".$phpEx"); } else { if (!sizeof($this->vars)) { $this->load(); } if (!isset($this->var_expires[$var_name])) { return false; } return (time() > $this->var_expires[$var_name]) ? false : isset($this->vars[$var_name]); } } /** * Load cached sql query */ function sql_load($query) { // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); if (($rowset = $this->_read('sql_' . md5($query))) === false) { return false; } $query_id = sizeof($this->sql_rowset); $this->sql_rowset[$query_id] = $rowset; $this->sql_row_pointer[$query_id] = 0; return $query_id; } /** * Save sql query */ function sql_save($query, &$query_result, $ttl) { global $db; // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); $query_id = sizeof($this->sql_rowset); $this->sql_rowset[$query_id] = array(); $this->sql_row_pointer[$query_id] = 0; while ($row = $db->sql_fetchrow($query_result)) { $this->sql_rowset[$query_id][] = $row; } $db->sql_freeresult($query_result); if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query)) { $query_result = $query_id; } } /** * Ceck if a given sql query exist in cache */ function sql_exists($query_id) { return isset($this->sql_rowset[$query_id]); } /** * Fetch row from cache (database) */ function sql_fetchrow($query_id) { if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) { return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++]; } return false; } /** * Fetch a field from the current row of a cached database result (database) */ function sql_fetchfield($query_id, $field) { if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) { return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++][$field] : false; } return false; } /** * Seek a specific row in an a cached database result (database) */ function sql_rowseek($rownum, $query_id) { if ($rownum >= sizeof($this->sql_rowset[$query_id])) { return false; } $this->sql_row_pointer[$query_id] = $rownum; return true; } /** * Free memory used for a cached database result (database) */ function sql_freeresult($query_id) { if (!isset($this->sql_rowset[$query_id])) { return false; } unset($this->sql_rowset[$query_id]); unset($this->sql_row_pointer[$query_id]); return true; } /** * Read cached data from a specified file * * @access private * @param string $filename Filename to write * @return mixed False if an error was encountered, otherwise the data type of the cached data */ function _read($filename) { global $phpEx; $file = "{$this->cache_dir}$filename.$phpEx"; $type = substr($filename, 0, strpos($filename, '_')); if (!file_exists($file)) { return false; } if (!($handle = @fopen($file, 'rb'))) { return false; } // Skip the PHP header fgets($handle); if ($filename == 'data_global') { $this->vars = $this->var_expires = array(); $time = time(); while (($expires = (int) fgets($handle)) && !feof($handle)) { // Number of bytes of data $bytes = substr(fgets($handle), 0, -1); if (!is_numeric($bytes) || ($bytes = (int) $bytes) === 0) { // We cannot process the file without a valid number of bytes // so we discard it fclose($handle); $this->vars = $this->var_expires = array(); $this->is_modified = false; $this->remove_file($file); return false; } if ($time >= $expires) { fseek($handle, $bytes, SEEK_CUR); continue; } $var_name = substr(fgets($handle), 0, -1); // Read the length of bytes that consists of data. $data = fread($handle, $bytes - strlen($var_name)); $data = @unserialize($data); // Don't use the data if it was invalid if ($data !== false) { $this->vars[$var_name] = $data; $this->var_expires[$var_name] = $expires; } // Absorb the LF fgets($handle); } fclose($handle); $this->is_modified = false; return true; } else { $data = false; $line = 0; while (($buffer = fgets($handle)) && !feof($handle)) { $buffer = substr($buffer, 0, -1); // Remove the LF // $buffer is only used to read integers // if it is non numeric we have an invalid // cache file, which we will now remove. if (!is_numeric($buffer)) { break; } if ($line == 0) { $expires = (int) $buffer; if (time() >= $expires) { break; } if ($type == 'sql') { // Skip the query fgets($handle); } } else if ($line == 1) { $bytes = (int) $buffer; // Never should have 0 bytes if (!$bytes) { break; } // Grab the serialized data $data = fread($handle, $bytes); // Read 1 byte, to trigger EOF fread($handle, 1); if (!feof($handle)) { // Somebody tampered with our data $data = false; } break; } else { // Something went wrong break; } $line++; } fclose($handle); // unserialize if we got some data $data = ($data !== false) ? @unserialize($data) : $data; if ($data === false) { $this->remove_file($file); return false; } return $data; } } /** * Write cache data to a specified file * * 'data_global' is a special case and the generated format is different for this file: * * * (expiration) * (length of var and serialised data) * (var) * (serialised data) * ... (repeat) * * * The other files have a similar format: * * * (expiration) * (query) [SQL files only] * (length of serialised data) * (serialised data) * * * @access private * @param string $filename Filename to write * @param mixed $data Data to store * @param int $expires Timestamp when the data expires * @param string $query Query when caching SQL queries * @return bool True if the file was successfully created, otherwise false */ function _write($filename, $data = null, $expires = 0, $query = '') { global $phpEx; $file = "{$this->cache_dir}$filename.$phpEx"; if ($handle = @fopen($file, 'wb')) { @flock($handle, LOCK_EX); // File header fwrite($handle, '<' . '?php exit; ?' . '>'); if ($filename == 'data_global') { // Global data is a different format foreach ($this->vars as $var => $data) { if (strpos($var, "\r") !== false || strpos($var, "\n") !== false) { // CR/LF would cause fgets() to read the cache file incorrectly // do not cache test entries, they probably won't be read back // the cache keys should really be alphanumeric with a few symbols. continue; } $data = serialize($data); // Write out the expiration time fwrite($handle, "\n" . $this->var_expires[$var] . "\n"); // Length of the remaining data for this var (ignoring two LF's) fwrite($handle, strlen($data . $var) . "\n"); fwrite($handle, $var . "\n"); fwrite($handle, $data); } } else { fwrite($handle, "\n" . $expires . "\n"); if (strpos($filename, 'sql_') === 0) { fwrite($handle, $query . "\n"); } $data = serialize($data); fwrite($handle, strlen($data) . "\n"); fwrite($handle, $data); } @flock($handle, LOCK_UN); fclose($handle); if (!function_exists('phpbb_chmod')) { global $phpbb_root_path; include($phpbb_root_path . 'includes/functions.' . $phpEx); } phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); return true; } return false; } /** * Removes/unlinks file */ function remove_file($filename, $check = false) { if (!function_exists('phpbb_is_writable')) { global $phpbb_root_path, $phpEx; include($phpbb_root_path . 'includes/functions.' . $phpEx); } if ($check && !phpbb_is_writable($this->cache_dir)) { // E_USER_ERROR - not using language entry - intended. trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); } return @unlink($filename); } } ?> HZmSH՞3Q2%Z}؅ 9s6£L-yQu>!sGG9>tlג'(%X)a(Ng<]ȇ0 R`_Pޏ3Qn (Y %ݎ "3xMXh6C7o}L箊H%>xu)|4–TPj;H{q A!WuCDbtn0OXUӗ^ʬ6Aʎ,>AIJsˑ@ǎ܇=!P d*.isӿ#dnX>95ƖL˅t3,EE>P6XK]0!;_=튉'e? | @~YoS̊g9OϱL,GGF7;IJ,jĽvX[Q2ckB=Wpx%k>7k-%l̛p vXɾN hG- yC1< Fa\ Yv{!|+s;>䢍7V)ϰ}ʛgEګ 7Ȣ3IZoqяb]42Uь5R,ɹ@9XĒСlBbyCD_qJS}-ۏyY!Ǹ Rz:Rp Oz5B UD~X[1:O8v*8t4i:Jj *;ȪVa T P ':E{kL /DQ b^$5$ƾ1֨^#wFB~!UlUA< p\u{RTI -|Y,LIcs'6"P9k7;4:ӱCqѮ\mD_ c{&3s[=`Io" R7Eq%Ғc68y*𢐙Uq5❨zA6XP4-'fe}PR@DwAH[ֽ ;A'o.4>w]DKM7\tW x_ZG^k3bW #L6f+z!K{m'fͨ5M96~ /fYZMh8U;oWEc^j0(6y{(T%&ٍ8q _iI`_[h5hNe)QfY;;RT}Rg GrqnAZ.)ry>S GMr8/szu_Ұ"6[ekՋY:|r(We"t-*zv7a$ymz q ֠" CŴ2#NPv5| һ/"M,K۪}!d[5(?{Mۍ?s' UI}ZQ֤4G} Gֱi7IDh"(G?4ݐ\?JØDojQTGsA'f^APdᜲYW?1j.7flyږun[kL5l!fڛJyߒYa/5?̸  ")]^O8xElm i- &\׾"x# h>R!kݚ?*zO_=_G' 3Eb\"!)ӟ#ïqi诔woeAԻ8"'LI1h@dHcDm8Ӂ?b0sL%0uȔA9x-|B^JHUJįdX#-(azh^ϋ14UEIJ7(E94Z]E8u{mrb:mrU z0|.J,j]<,t6TG>SҀBriepfX`wM %#HBtxn0d׿N1Η]:AVuC^"Ñ'$F]8)r4g؁Y5) ,a':h}m6+zP6y`^\//FPf~K{e+)_D\7טņ2EXA e7*A(qSq$9Z FЊyNE'q@aLx3O0)~dvƓ09`/wX,@spzS%- X QH@a%f7`+',73xGTk?#OCү][`ϋجd|[thvlPW`.iW"]B0c\LSp=A -HrETdmiڪjA\")r7F48ՏbJ]WkO|nd\ >410 YGϽ.to7<=U?ͯː_ik=0 %g7@QpR7'\M~v3#M. /cVU&, ̉ ^>ʀ)Z‡\J\^kEOA{kD̈́0}1Nu&!NJƗtT&t[;,ގ[f-\WHǃ?CiU+ߑ$b>C`tśn-ڱ$dӰlY f\N!HjjS4.j k)}>QM,6; }k7}.8Qpox ]<ĵ/Ѡ9tY_&D(S04eɻVN#z! 7)j"eK&K]PB~SP86@o _>L6 k@eJ%= 54Í*Lt!q:mPoAc=;-r>_#-]yz jƨ[GD́3>6׍mLDAjej>[i~{=!f豞aK=I9L= s9ExVHDU4 6eIp7)R6|#}b|'A+/r0oQZRjYYHG?ߋB72eqͅ6 21VTint4 .oA^$B}_ڮu0j6.l=!`#^cZ -֐sy-+@)f@ [fK2׫W|t^[ύйLG>[8eӼGAM(NrqyX !@&:X?^SN~pq"f p㑶Pb;5̝%9On[k)!H䲵 Ho)bsr 8 U԰;mAZYWAv 1Sv KtkhU"'#FqB-c PehU^8C᜾~)׏GY`ksmnؼKJ%f^\,Y3b jDCvctG#jԑ>=,ϧW.Ss5_% RcY:B`߭Ss1'Ҁ7Z~3QsoPY"k ̓%їm8. vaϨ^erB2ءV+׳w~/(Q%O|3Hܧ,-ߥd42YɑƒÓbz5$t0_2kDBK'u.C:9i+Tؖa93SR0ӖJVQ"t+axa揀N f#jk5<'vEzmhUЭ\&M.,"ߜ{`9d)\#='N!uswm/懲aD'W{?>O lɀv};%k?kazFsAo׶;wkjF}k;fѴ,e)@Ȓ2 Nζ,.)Nc?8"8Tkz5=XC.y]Vۦ >9ğJ?PH',|0bx20\wB.дj6X k7I 9}]Ҧ > tÑB" [q6xݮ Ӡ,'Z 2qr(e22 Qٝ:p^@}jt$}QCKCK!rt+ذ:0YZؑY*_~̣ÙWQ푶4J:ˤ1Ǘ/n+\)#;.kryťI SepynO鏉PY8^zB{k0=AprQxK-gJiY& S DrpEIaA[E*f+ R|6}dv:`"EXn!Læ&kaKaJOh# $է @*hUD"-FeRaҡ1^ֽ7D'%Dѹ%"O;E^q}+YyVE4$%G v!)m"s6T@@|.db+fѓ*zyj1JeĐ<-TU>=+`ķnGȉ|.nf5:pO[0wy& qIC+Ef60kO&+{vV᪉r.\吙F_,_,h80Nߑ¼@߂"ՐhYB>ڏ mCN/IB}d+*vZ L12  y 8Mf3 ,ew:=٢n cDy&,X:SHpFQ"#nI^$_L J0%c͉hqtO'3DaXNȌ<8/΍WІf-ˉ9Y|zYÅP-%bxivr} ?ln!my']gfcQ7HS'C^>>S)DhwvܒT rgW g g!ѭץKLJǚwLx\ޯPY6Z)(''~W>r iOw=S YM?20ʠ LbUȢф2o?Zաl=cz<;Phi;403H8F+oLW/Ta vUv\TcBQdrж7g>}w Cpxϻ%#uSOKڨTTܝPmg8>U[V)Ui̜!5? (?)Bٯqg}V?&T) }9%}$PʼnP%ԒҌv_lwwgQKt,H{_NCvT]|D_f ckxeBpOtk z$i2涂 ԰u.xP\HE0ߤ~%'] ^a=4{7{ۄ۳>4b2 li]4G=QӬ wÍo.MG ˷݀Jo2vבZFEp }bG̑-bLq֒돨̐Kmr|@<ڰ$)yp2lZ(d®ρ}El0J~sϹ9hy1O}EZ6-{Dkܙg dM?̡Q|ڶW##{ CI]gV$xC?ϖFEjw]NO&P2£SHíU醕ɶ }"0*iMBSO9Y%=׏BHz>S{6gj4 &X_2P.te ɇӼca>X5'IF {XNM!]aof;!{V\y9XLnm.C'"L2Ç8ݍ$I?(i>Viÿ#8}-?<;5v6>f%~ǭp3, /ܧO#udW: u9pDFHAKIԩ8Tvf_M"ǵs8SB 4,),OGlo˻YwB6GɟYL}" B; |tvY $Χp+#%~EafJ i].}(չw9K1ҕSۗck4hӒնCh17c OtC1Ԭ>g!Xwhj=3NS*.bNxWQX 1pC熜w"UJvgTGU´қl:$c {F DېͣgR?h07ޭNB!N)r**߆Ҵ G|c K,"XMtWPݨkbp 3OñDc>`v(bUd0._\z\AoSE_60 A}I|ɼ:Lz. X2F7w=sJ8(kGn*`5*lXX\C,p@ܷr\jg*`PYkL=Y~.1?#67W9MlD!G J/Cvl:%:'m".  & 9eB%?&pkVU$ڏ\3P)hFGo>2c:k5uYy\4̽rJ3CNFhU9ӡn[6m@־;GZbu(rrEѵ2쀳aC_Bڤ3L| j /hx#]R@E9vNze ~A6ТX~ -'m[pizJ'cE:0M@)/ƠR4ӏF nL̤$dS[si5(Dezhܩu0苘SrRBqi"b1m1VԇHo)3O<`&.x=qDFmFТAiit0/1eXP6(9lL"} {T'W5:Ysi-4U\_HxEH,P|Б, LvaN%BUm `=d~ҼHWc! Uc3;6i2/L.P)P(s³sI#]x*9 L_鳉kKm ~+f}h|0T0 ?YFv`N ~"* LBV59;uIdE=UF۲S$(kUIތxo:mos`ƒI$Yx(KV gi"N* 'wq\MnĎ8Z3J]=]%c%${¨,h7]L3A[780հ!@ oO<׿[D"NDM.ʐ]Zu&C X9ě:JTǁ6΅R_GO~.9S?EW&VD )1--c+bÈmRSi 'K~W`o$M:x\gj$[RI$M&RH!Pm.8wdS:|n<8rk%2_d.pW^r2{6 NåTgqU>*-#l@l0,>tųIx( Ȱ?Q:XG6񾣃v:v^W?; bm@6 xYZOx*Q&"NtZOUÞTIEE_nN;Luï'8SgPE?d%F#Tf|y< :wY-92R57Vd,}r$%XpT67j⦝%w2O2/Ff&8 2FX^NC \Q~ŎV%ڊjH5-AIP|jCZZW 1)F1F~-iZD1ʒ ^Θ 8mT!͚Sd,\^ O\\y[:- A[ gp9jcSϚ$S> _v,a6+:L0|[{R4*гihFeҪ#!vƑ#mXmڠN}˲|<݇#m0yҨ$;K? n1OZ?AOiUۯtš1IP$ 2jv $fZ3 i#1Rt=]-d `\;_CFؙϊgwA^ -8wR'b 2 ˸B<\'Mc?s`vL7t1,ZBd/(5 lI=$cSI/.񔕠)g{ݡ&85aQi׭x'e2 oԹR1I(3}M{ynzYug )!lA\ea`I <1X[9䂸|DohU J.U)1(D"67(,qį_HZG`l7O4MNy}eaE(sjRV:ɹou/^mtsZ-Q${xi)'z |tvp<NQK=@jSxw.a8ԘwI? ]B2C+so#))ݓ|ҵ?5$+" +R+ p\@ `i0@[Ա)KR(mL0uTQxˮn "Ba#H $%XҰ*0`ޭm?쩠+pZj5i40Oum3!e=v pS8Ccϥ5މgW.' }i¢]]I$M} |˴\VA`t58ƶ{'~ ٹ Qa pxwM{ Gq\Q)k+m];SۓWybTg mVm2TQ`8ڏ(C'w&`*v- &il.+N7͙so)` (E4 41z|Vr90y/ϰT=1uSuu;pc' <4۠B2==A|OP]3 ms,DxVp|i;o؅$<b-T6o\0[Mɹ+){0Il>0P̦iA[+an$nx~@mPYfEZwL$},=Y8#c#8P$p i6=ۨ u-o.NW*I$\~Ozx\_ dK)_ƘM;pH7n ?}tX4pŝ'g,ngaTvz{Lt#۝R4mN "Nќ'sW"Er85)ذ<Ҫb Pi8h(Uay۽HJ phJҰQ F1 Á{(m6]o/nC{q37m]yؑ1]vT~j;Gp*Ub)˥Mu$մ+2Cs8"RmH:?5t okf,;WҪh֏:2IMe?dQɯ%HݛD|;gxd#mskS^ٴB(,yRscSOfg2umpUZur昉EiXb^!9 pt!#Q!rFqę^<٦Dz0 t01=U^<3d8ںȆiT Qa1vY&nǖɓ] P!(t3y&ǔ~!F#vk[YZ▋݊%: wf !Yٸмve[PHd;"SZcVN8+`!LdC57p`Ⱦ!K:^=DX)kiA:g0e%Wx;cUXJtnGƶrn\@&YoTȎrbN ;Òql1u!M`,;F2ԱB α(#⋡P19ŗ{21`UR# UR*&o=Bnt\6EEArTKZ)F?*3y܊4_@>01Et{B[>܌tb`g,r@t:B"o*6%)-b.^]˩`"Q *7jlXaaCv=ަ~sPuX %1 iٳyjkA9F` ̧izV)?KpJCr{Diї?-:1k XBrIu(0ql8G}5zNy|qޔOĕf#R%~Xo+ي~ݽ "•)1ݜbsUe Fh/ʿnj7GBN[\JDPI= !d!REXTsP8 ,`I &f@+0Q? eJgxKBӑg\llM@+q7 g뼶0HABDB1**#%'6qܩ-x*GTt-0:4R]Z;;kɲVn+%/:'Bkfz`-S!v~y m A_LRrA@qw?e>0f:S%Ms}W8[_KQ)&,}%hx:~j IGRQM 5އ Ȟ.g* h"aәA = 9pΠ}M'1@l19YRCPFrp5e!m Ť+4jTdw & w Eq~R^0F_FWw6ɽVFwJlu3I߲|P|W-GjjSh.SԎ&Gyѹ]8ܢ#G&Θgu"uҵHHxjt6zJ7&^D9i2&)`C5o[יUml pS lI$pƻ?7 oAbڙMr`J 8M'v`#}$c3^+r2|IA-Aykvn'S?lrd |=P{4Uc%ul_2Ct[c?*;e1{͏ B%t  ^BDOW UZ /Ru-s̻Ě|\  +* K.O t]f$^L (507tid̅CoVc-biU),U/+>$՟h{݄FD1n@}j5'lr O.h\!^]rIifsaI} rYHIfq7Ok uȎ@)Ѩ]ZFKެu/|Us.s@OV{<.^ř)eB0X1v~~:S[q6OcPEg? ܅$1ߨ<ֵ[0 lvtm'C2uV(0?O;T)?XZρ3 ^Ԁ/*] N? DgZ~67˚i٤ݍȘt:uq8<ϞUy'wV(BhD⍗ LZ&򪬹v=wڒɵ8#ChCS$d%$N63)~l yAZ9/\$S%84> _%Zr651!).v%6ٛ5St(㺱{ϰ|-|anUO>NP`SBSHJ^e]Ġrg=[Gh X& fa+5@@FM/oa-wt (PUٙ=b-] I!aA3"s,ggZ8%ֵWL>b2쳥>kg i׻! .jX#vتZ| U)?u9ˇۚnTn=3ey!]51u=? ܜڡHrӆ[awdW isJ|P].F^Oũ^ḿ|0<-:aLX{=,cg94ZԀXuή['H%1@H=a+L*^yV<%;rawB"خg !wIR8&?;*0/mw=e w2$I"*Af$ '*ؽW؞>ӣ_4Wk0$䆥ͼJ^7`7$D+POG;?=ob h1<_|+.=!|}ym;NŷW 6M6cCg13Xb״U!dّ]7M}لn>N!c1=ҏ`Q:sN0]ipXd 9J4S/#]jX=>dǭ^Vc>+kF@&jc@i Tu*q^A^ڰL+kɕBC~L?bgtf1ŠL(f~9@Z]okH*6R꯾bMOz]0=ߙZQ?rιeDƶL/צY'p6djÙ1+AĞ hRjx> ӵܸ™ToE < 2@s`]ӟ! vE GZ|@đ3갑<4B2SeAX`pj W˺u N1&DwsŚrDy8hX*~;8t2O%ٚWx[ɏU>|1ϫ6eSP2~+X\E>D:8fYnbP42p5WZ_!_TO:x76\xd[`b(m ĕ{oc_~ÜMQύ\@n 'VB?UIZmĽ`Sާsk79fI&O6oļ:8gjg{lj9t}L=dUa@0ҏaVׅCiͯ0 WzդLK9?O2>#g}_O S)eIOski?U+r-h]_] J+c2$Swn [Q =UM=lXv,J!߬s8s+$Dzm/UT<5J \ymڳםC6rͥ![H9X[0v2^Hߔ u^0D'g_[gtB|)k7CF Mfcߓ3>d Tm*v}L3 ]:6S+Eԗ΁x1c`. CS1 Hdr0rÛywO. =86%q;)E]qED/0-Rеx3"M-Q]4 oCh-d'Zޑ,SE]&!,L~D~ .=ƔD0Yy i 9i/g?$ [ cc+T}G!]2Ehu >-eeȈn8=y/SpӢ+GcY uAWC `ד%2H Nrr`&Y,Y!Z}fnNwNڲCc~߅5zݓywCZʨ\{zahv9zn#O\t/y6~7ߘ08fdTF?+t۰%4y^W74)kl2YY@vӝЬ( %=+ Nxk4y.2KiicgDRSS6} C417>wmfl_E#sΙQʙ[ >(MlǨ&ÿ(G)h:ȴ.kd)zL`mW;dw[\%iuAsjW <ܘEBvU' 'f(b+V%$HʣoPXuր0#C_4 $Zg^zmQlg;nqo(1', x -tzn_1v*ͺr˙bJ|=ijI8.*_h ^CM:A4?_M.nx6_l7y4њZp¯ 9"Z9Gt_#.jc7b7ɹ@T8O[+jEw tHQ;ld}'~@ аT؞1-YkL9aO(v8wat2-Y*_+=9 mnghjŗcdvⰁ(.xq1=J8qnr{ :VoW9õ$,UŁ!ax0x*OݑK$?qxi2DZSKikJ%e1o:JU=3|Uwu]ʰg&BXפA,E.+%j})3/Nx:2G!RseEr3krfb#IkJཾax!.6AW8>%LGVn˝"Ysvyďl;fEfL{gM8&=؂ٳaa=6,Htm`s$?kdXZ O*5)fɁ\VGȈ6)Ve~)B%YSݩ;؉gu2wBmzsޘ(T2gV#2P 7Z<qmo0R3\#GeQtRB+&+#j)ɓ$T`i.ls@8mA8U @<æ)Y?-[:h.2;s]n2mhbTezԒTu+o E݉bLFY3A7c F _#Pg9$ގJN$VrC떈ʊ3WYe|oyY82;nK ' u(;B9p\ڗ?XgG:ń1ԮQi:ϻw9@o jB1O=`1<֢5zToA )zqi2-RyP07t9ֿM1q%PvUl7#v<1Cɩ#ޔj(B+o&!%U}:+'X+uZ_sRY`29[ [eIRM^GSD~fꭋS&GZACluL]6y+⚏W=Q0xmIk?F4og8V< l-'Lav%~Kb{uZ:W?ZN{hrtQ7@3JܵmUq ,=M'=z0 e㗥<ϱt^dyw\y+?%[BæB821 Xp2&p;':/eEV㨴a2P1UYaTP7F%o"y129oN8;c/0Y!2j(q {T ӥE\qO &j} AReeHCDhpM3xA,&-9QNY #l({Tu-ZEpha$p 0&0OY@`7cP%e i/0r9VgL J #Z>+;* +/@ jyA$_&33#6ü=F68֎rT׈u}WKdId Y$ ؈P^*UyGƙe̊O4ESE+%^#3 }ALJySPeZ20lrI>K&Rݝ3;;5g~F>)KAD/ybJKr"΍@h)_z0sG2 >Rqb/gn!E#c=ӊ3 5)06$spkȘF8<@G(E1sյn:φ V0ȹs3溓&).sɆ7DaEE LĴp`f|Ye5xyPeLU᭹;V!^)"n͹+geƲyfc/o̰|+ xc9LLMhRFۋa;v[kp=tO8FYR%1Rm;&J>PgɎwF69n zM@"(HjSfz$g\GZ쌥pdo MXeT-ۦ$0Bh;,urj2v2TVn.DBH!ȰpxLd;f 4CKb+W,[r9qjԵtQnlYyyoeW™\HPҪp{ [}iBK(gf# –w'}|Ї__~ɏmk~kaZ_iߛeVۿ7\;{)KZ98aO͙(*˔1FMeu:bsh]4_GCɷN`ii$kGs}e-v;=vh8͇_ᙩκr:ɭ{ԲsG&VR0h>&qSl$1%)й?92c(Aq|Ә:W Цd.کjWvxxi.*7 -{ Hɩmt,{&mρDhiYCN:>qݗf{Xjb#?T0Hۺӹs%r]j*#3 =#MPYD/7yMrEJ\Z[#b1 BcOA _;[,Q 1]+k+MAs {|QA23:fSYң{ayյ,$]l}Xy^{ޗ8,I;_`cżޞ鏊Y1DM!!.B"H)ݜbl@T]@ lm*ÏZ:0U*@L/ .w^v Iw4 h4 y8Țr57mp"|ENǬAkthxUW<]a*<~HIxܭ2`wP=o3|0sMG=4 <z?&v_cPĎ[sۋAqW`8?H nkkh:O4І<@Mև1>TcA9} '9=vLqkK7K9ym iLq'.IK{m _pDܥOC@벘;yl֟ BO^=Zõw0mhL=-|ʬ >wjc<]C[MB+36tc;uҥ8+hT0uE90 7,{&i̤!K]7[!!I:UhL`T2tcZ ""nΠN5> we41b68pp&"uʲ4F4<0kE]ZI'Vf@»e^+B< [Z$8{~M f-q};BʪyCKvMŜXӰA']?6A.4-V{6z푕?:/vq:K<{$5/EcFȈ~zq;r">OK]۶'IcG2❕(g؅r0/jZ W`X蘘S*2m۵McFk;֠$B,lLm(-6Cfrԧ<:ѽ[tc[jg_.red0a2+%#K(_N.S٦^w(&jE]_/l[08?0!2VQ.ca?1B2p-@3qyK1YY :Dni~ VbYKp.hȏW`308g;2#߮ˁ;^fu,E|#يʆ,8rp}G1Nbi]DWkHW`OM'P"1)YƌV,P e?ӻ*a{覠o>wt SAwN}c0OntWAXqG/lv/dm0&S،-,tI$;s^"t-6)v{[MnYRbq${7!:M,׶J@M̷; zGdCp_ˈ# " ?Ǥsg8 f>HN?O޵6S.GIieZAwam&5 %?!awPrBQxǔnbo;WKu]aGft-%y 0`Ū$؋ \9Wdn\ dV+a@}\I O;ls ;7  "gWX S ;lLJE̶N N*0ryG>TjZiMM@Ey3,$=:xBr% KÜjb-!֤`q:=hu\= B-PW`cؠa]\Tx:(:w[& K*jC{f;Z4+ @I0bxշow߁&oIBAS SL#,&C8$GB9;(ҪP0xw bz( {E2Μ:6{-~;ZwSmtMf`$}UȴxUk3>xJjt=V<j܈,3g{̼H,PQ;]nojv(;  `3:8b69iIo_Lz\_do&}ڏ3sb" OH7׬)TV"ziD _}u*i1,ekP&>(4'ĢqfćkڂZ nbhE^~%19GB]Y͒~Bi1S+ j2=MwcnP7 _0'8phFտV[g#"% t0ѳ OB 5xs߬Ǒ?rne ߤ(ϳ_t۩ukqo+)vJ87ŮXK#2 dALQ1#ۈ6QV:pbק x4.ѺE:LE7gF"/Y1Q' LVEL,B}~Q6O1I{*XѰd0ˀNrfQL8/Y㭌^ ⤬2aV;E>h r8QzZ[qgmeٵRĽe0`C,vjo>SqZrr2,dY*8b޹ 8 xw7sC-'3[0޴LS)4z, pq0C`l`M>5QFEa.KQu9B|=/.Px"G8+&{CHFpƚkx<|Q3k5dRBZbI`z@, DZ-^[P~™*θTkOFRktQCg;.w<ܗ Oy-X =bqUxIUm YnN]!E5@{ye9m& i+\[#-NOa`t]5h ^[N:fxPt'3r Quxm\Zy)VV0.~x,BYG:AI!pbr'NSG i>^haI8@s /%%KϾ&_z)6Y}x\_~42Jc5W]z>MX8*:-cJZ[vaTMoî.D相,}pQ!kڨ*]w@cE|KPUa*tؖE/#NђNg`_k=ɠ(b;sIR5U'E`:.}VsxH۸Ο8c8WC@mj]׺e}ƆL 0Z )b+P\gYP u(lr AGsTz-3Ho Ԃ7p/WM!}ecnXK(ҩDOʭL]" b&u&r)6i6|7m7S gÐe Q?_ȝ+ZP~әGZW_8&fV笊_'㱐"D_-.,N{*t0AXoa*s26QH K-eB흤IE=3 e`ً.Jz,/š;X-#jQbeJtd8 cHT16Z,ԲV%tni o< 5ɸTZͤ5Jw@s_׏H@@p3_}2$,a$vUDi[鄱_7aD[_DIqS>?jF6eK"W-͔Ŵ=qF/;UFqe#0_X2W?J1yÕt+*k>ö"Z& m0ԫ';Dd i_$:pp8>4հ|<%~o3P9MmswQ ʞ'ͦL䇪OCGաB0e%󆫼nC*v!y *: uWZZ"ErQ7"a,6.4DIAh2 | 9Eg6{Z_u! 43(MjwP; F)Ҙk}k%AL4hXfAx] k麝fŦV,ܴ^JKz#ыGhob{rA;@+S-*'S}PJh.Qf&ø4e "Nפ^`+J忘fHm]ǦjQ$Фr 'gw  GI!kHu$l#[5Ts a} |_];B~nf~.iM \ij IrM7EVE?Fy Ş$'yUn Vu(x.rL[ U_ݬt%;X4aJ.bF+N`OL'cS7*c\PNM$f^ 4:[ׁFDb4߯ R__h8v(vEafo ߑ>$4[Tl(%]p^ve7kso; (s 7v )c5]ukpZĒVk)5B@lMʤ>66qH?P"|90Z&_Y5aW-gEf*(;dXPx܉X)x(vQ}N%rTh/*2(-'x9u.́R} }aHvYAfEvd5 EO*ZUtxsH:<>Z!@ 7,dq.2T] Ӥ+qôע1t ,  pl`K1Y5KBWHJ/MfI\6;\8 S~1!uFKwB91jO_L Jl$hъTqMCixRà4'Tv\v@ά%Md6[N4껌[9G3$dum|pYhJ! ƳV qAx],LxQf \3* 2?q'`FP^G iK2?rdψM{9g QB̯`7HLX|x+H򛏽ׁ]i6_cxt\H{vwn#rL  }(Ϩ[f5m"MrQR£ |&g:;I>`LjǕK:eͮ}/_-q0\znL s u"cm"6Cx6?AYOGe N>Aw0}RP;ZQEUfY|&2?p\PB"(]oWO/)uCAqDowzDy`+uAu:seYy"~}ʆvALݍcY/RI^Ĺ3 F/s]dtZr{֬WT l@"O#q$has)RgP܅&$=&Jx.$Cg x#[WK -(DrBPF%\[ߣR2ޤv; . 2GnEXNM *^JbeKfVS^2sZ#%+:{FG."VSHK/Jcu5H1E?_c\"hx}67s1Ch> ^(c4n P~Sm|x85*Hq_g:c$WXǃ L!<pPCY"7m3R-mJKj~rdy@3 ҟ%aV/3X VUlgyuDivDwUQMF)"{l>{*H7f [z -[qbU2 Ĥg UM.hn n9h JZԠB'ơb-E[GdXZ7,8#f0hac~,h5˕t+6g['@Fui)EPPTӍP'wGLW7o*7 Bk0$31/T^Lg Bnϯ7/ GR.}:0A-NP`u@sHjq 萜lh}`Hz+Z\oAAO5t"r2c) }RܮK<:%۴>-BhIP pJ99UTidN(=7A6i 2`A:&べY|qs/Xp+k[?u9KgMMzVf"J۱(;NGt=ax=\2m* ;<]FևR&{syKEsCIFCͮh׈[vqmY.I Ef7S*0 ]B7,Wנ8 gpqu%NUazbN$imYEY~+ڇqMp\N# e/U_;qUb@g Ćb1j“o/!kZn{CmQb(zG 汇y\fFs6Sh,c΋ƢT$[p; ȖfiRm|֦|yrf߯^̈뎍Aw!ɜOԸ4Vyʿ;$"#<*N!QhrhvfBhD UMeh~ǰMqψa Fb\#rLo`e_'YBHo~=585A}vR͸08{,Pu)d0.'۬&źjũŽØei#M񗡜'/|U~&K&HL{Ttזwu&$  `DGq"+f47vkж3GMbb FSX͛+twMh?gڡH G[7+t ^ r3y%*#{6lpʆ$n> Qc os8qRәw86hxBK=Hec/P 냫ͿpgʓR%Ӎ`dޚa}AͶ8g*Mj?n) ITYǾ"OdaU D8Wa;GH?t} 5zGC: rPYq#\{Lc{ U;-@Tإ'gSRT^VL"NŢy;һgс+wC`Gm@."34͢]2`>W޽Ǫm@Iˆwzix=r:..XG\bi2?!4=katD_q YUH& йMrpnx9[H8-mvlhbi]I >%W?qRΎ>_K"7\aF3P $|BpMѼҟwctƏ X܂dZ!Jh*"RA+M0$N-|viCv{*Y~H ƺn"_p} rq|R9 &w#ʷa5Q{cyF[JZqOS tm5l8w 2?"%ƆxZ?_4}pIҿ̌"$&9;=DdZ ]A:5T UH z%kzn3}|7uc>;J77r0Ƶ41bOyDP?sWQxmS4ׁ*;lk%#nP]YeOXJLu?ֻ=YȘs][JF۷~YFHUp޶<p H͓]'Nh(7J[ωhWH/AN )f>B\*r!,eަQfL*ڭ H~uYbdxV5O[ ;F .8F{WoD`WP4rlgn i7]+$MHk ?SBRlb<ӧ< /`01mSI0~Ib֙"p ֡^ =)2|)&WF\ihZȯ̸ " ݪS 7 )Uߌ͡_3e/L͜pSe g;ʞiPnLl)jУ{]oBmVw}z*XAk Oՠ;U!u(=E٘q`1<{DS{ 'Ŏח3/Oz(ʎjŇj UQF\9ό{6{T_5ds,z:T'WB&/F*4 xB޽ط]8+Jx=\sa5I-QW [Ph (f_)2_l~Ezo,M)qnPL0Al!(3#"OzCgۚ+t?~ZṁOF_ufK Jxp$-q+})}+zYgk۸͚~\9[>NCTb+ae Lùj֩K%wť*d9ae@?Ismyh8'Cz| ekC+$C,q#qGMv֘xϢɾ9W@sJ:ܳA7= ~utɆ^Y ~')l қjϬ6`ةC7#1ʻ+:tj_EWBBMF:@;Z/WŸ 8%YʇoV <#|OWUA1Dje>x+ߠ\dsW]1QzvuJ)1k;[IJ~T~~bF3|B*cUJL8$:K|bYe9 QqK8[+^*KAF1dd+k1/@Z-e2T.z|^97iE":dn0c80)If()[^m7Onbϻ hnaRcBmGAj!2L1N.%cNoN,D'ޡȔk쯯2 5xQJ-)nOB<ͻH膾|bahCeNdinzTH;jxqH aל_KI.aU("XfY{-Fmg]>|}Rupc\9)$˨4~cL8DR>Q%dhh@BZnU0N[70rC Ɉ~RL٭%:VXd Ev>7H\XRR7~LQDB! R60xƓhBd|vRw[fv42**ޱ|a4u&(RA.sck9c&!ohe}Sűۼ6<^{7- =yCjMDl}۫c$?']&c52di/u:2#+x3czxo-@*F$7wWb!NזnU@ |'Q?3S%[L*bLkSTϢ@tcA9quwىr# _$H@+SffGh.TCf`Ό$ 4TS#:Uϱ,5wBu?-eS]ijy369n24^vtBPRQ˦Ny-Lr& ? ֚S o~JG63J{Ӄ[ yK<AxN+LFwR4v~_jk:_BgGp(Mp/yPPR?Q=cHK lh\@Eۋ!k$^5+D^u~"mb,TI%-Q'K2D 4̵=ٴvٹR̦(<6[O˹ā,d k>y_A"<vVK"%AHZG_Hz%B'Gg= 9;5,$RLIieS+fGFA3ea:cˇ,[V4WUwH/Zi_A99ɬ"j0 \v g=b6H1l$?_|BeHs6#Vl'@yʹRJS8/*WWpWTľp_-y80Gדd`B߷MMNzDcX3#oƒ/PE;I:w5EM`k>]]dѥns^9,&N WSQ)g C8AEY)Qg{JKU) `K@&Җ!NS`V3Lj?QhݭxEWԹ%DboaɘxW381'BA&cfүm݃<\6A?vPE FAVXt8]&:V舽oZqY[Q(:ػ/ݤ6R3hh7|9Zs{[h_LodoUm*Q)dMj1,@5?WdQHejdVnvxQ\0 Q ?We(9 ,A?֛c܋T mNCm3kEQ7fquD{ Faƌ)𞝷=Ѳ{UAѨ~7ɠx.H@Z !INbDb]L}!@+\4Ŀ$͌,Y0Bjh~R'-(\ς @p+Ahbr&-?8//8 B pgz ُ8eŘTE?ֈ!y71T/\'l*0i)lK"zD Mq.w:2ZP]oΓہ`'Be ߖ.T] QY`V\xܰ|]R2*+1?dc:Q#7áMV.D[Onf,B9A+}]7LdDF9:;7{,M[k!ll""uf<\ka2&4&x϶n`Udn|"0ͯ2r *Om݌.t['%:] 8' hҏc-:~+E0C ۣ*a夭3/Aԏɼ2McJ3Or s3Bv6UZg WK恎)d]cdA|^w_k*׀f}$c ,O˅Uv8T_Lfe 4A(<+8)r,*p5WJhY`=1D7?h;&*%͑]^u[TS͔|!>%xQQ7P)Xd}S;ی}Z3׳Nf!N6)-Q;1`USǶ΁8w%o^b 9k&~GߪS.`ԕr3įg 9VBjhohkb[2Eĭ+F"k7Q;oYZ4ZvlzG(;}n%֒RԮ[T=*sKG,e)Q1%CFƗ:|\,=3_ېLzEBo`v` ̥U.8R!sJs2b-{h!6}P}Ģ_a 9$4M }[]nW= K7MC-w04T}) (T(г5ƅj) N9uPByaWo.z$ֱ& &:H*i?h/UNSv DIv49֥yJa{`z^˩֤/F ~p Co%ɛ†R+OP2o.!"zt?bLU\ ēȟ)'sA%, CTc}mj\$ݾצ6УV>C)uElޘ@gYfY*X '/RE @BR>uwDt1٨K<^0@r+hpUf801(zĬlP|wn>M aVpxy->en-XS己Fn !SV&lS/vܥ?#z34`N&NJpd0:?˥b8͏0?(o8'! ԤPQ L;l :~,,7jRgڇFhơ/Dt襕b,oP֕4k5r@O?b z&U5[\`h\g1G^JaddӘ:afLgΈ w2wjA=8P{,Ƈ)n[C-WGKu]TnϱY¾OTj 4'f;e"6y 8BsIԦުu}K_&̧Gf:"!Kd4!!2:w:3Mׅh&Eݪk['Ku8b X&>P/E-&*Q﹬T+<ӌjÒ)!hp]:B0 V=V\jK5X6<ב0[ W ŰcP ǹS]3.i;0bShȫϐpSԳn1%f*vs2l}6;l Ye+څLEY$s - c'MGm8`'5TV_O@:]MX{*Rekwj#}9]~tT7}/O zW iL90N!(iv!VɆ{񤆚s9cU?3괇6GٹDĦ `fbXRV |x?1tgX+_\ Q41kӿs*&M^L@m,hLn?w띹8rzXX08E PUCLf{40WPg,?_.KxB`@ scO@XQqzj0}c`Lzp&k{^)ӯ2áy(\wIUT+ ܖ~kpD?Tg{6 LE`NUpC[sO13M 9Z#mlWĊKJ/ޗigiD\!y#jCNt৚pPN0r> .y݉k\TlRN5pWLG8졦8NBLVsuew2{vx`b5IJ3nZ%z~p M?uȁFSImMOZ.@*''W-osY&vH-]KGv16Bd9}z8N{z;b BxμQ]ܹU?{j d S 1'ciMLXCT71 m]Úln*ǏT.L*>"wӪ_&Ү'4?i̊ b]C1J)\7*qMɳ? {Ê^(O3D L. 7eyMˊ p0W!QM@ &nԤ݉XBXB?_9!Gm7DdГJu& }O˹j|# $ Xh`y6EdCr?`:iTc[xs;D-0>qyZ N13E{AVV2Q[ftdc!WKu#2m#OF蠭g0 ϾƌHSSHq0>pJJUUUafsڲx:;2ݔKȅ)ʥ 圈y zַZX*Hʌg8h@*X?{%9o6IXYJS;rt }*Y$LJ5Z%$wۚ֞@#xH2^] i7 ;' n!׵ȩ6:|*|d _77Oy& XضZ 8bI9H8r׉PgDc>J$ݛ`F#t\Gsn-ڄ8Մ:ZOaAbŴNѴ#BL<6g*W[!/x$~5kWV ngCb2~e_=1 h38$BZbk nOKb0ΉXʌN)of\Hbb7\o]a.߳dKc%0Z !Rx|5