sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); $user->setup('posting', (int) $row['forum_style']); } else { $user->setup('posting'); } page_header($user->lang['SMILIES']); $sql = 'SELECT COUNT(smiley_id) AS item_count FROM ' . SMILIES_TABLE . ' GROUP BY smiley_url'; $result = $db->sql_query($sql, 3600); $smiley_count = 0; while ($row = $db->sql_fetchrow($result)) { ++$smiley_count; } $db->sql_freeresult($result); $template->set_filenames(array( 'body' => 'posting_smilies.html') ); generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), $smiley_count, $config['smilies_per_page'], $start); } $display_link = false; if ($mode == 'inline') { $sql = 'SELECT smiley_id FROM ' . SMILIES_TABLE . ' WHERE display_on_posting = 0'; $result = $db->sql_query_limit($sql, 1, 0, 3600); if ($row = $db->sql_fetchrow($result)) { $display_link = true; } $db->sql_freeresult($result); } if ($mode == 'window') { $sql = 'SELECT smiley_url, MIN(emotion) as emotion, MIN(code) AS code, smiley_width, smiley_height, MIN(smiley_order) AS min_smiley_order FROM ' . SMILIES_TABLE . ' GROUP BY smiley_url, smiley_width, smiley_height ORDER BY min_smiley_order'; $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600); } else { $sql = 'SELECT * FROM ' . SMILIES_TABLE . ' WHERE display_on_posting = 1 ORDER BY smiley_order'; $result = $db->sql_query($sql, 3600); } $smilies = array(); while ($row = $db->sql_fetchrow($result)) { if (empty($smilies[$row['smiley_url']])) { $smilies[$row['smiley_url']] = $row; } } $db->sql_freeresult($result); if (sizeof($smilies)) { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; foreach ($smilies as $row) { $template->assign_block_vars('smiley', array( 'SMILEY_CODE' => $row['code'], 'A_SMILEY_CODE' => addslashes($row['code']), 'SMILEY_IMG' => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'], 'SMILEY_WIDTH' => $row['smiley_width'], 'SMILEY_HEIGHT' => $row['smiley_height'], 'SMILEY_DESC' => $row['emotion']) ); } } /** * This event is called after the smilies are populated * * @event core.generate_smilies_after * @var string mode Mode of the smilies: window|inline * @var int forum_id The forum ID we are currently in * @var bool display_link Shall we display the "more smilies" link? * @since 3.1-A1 */ $vars = array('mode', 'forum_id', 'display_link'); extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars))); if ($mode == 'inline' && $display_link) { $template->assign_vars(array( 'S_SHOW_SMILEY_LINK' => true, 'U_MORE_SMILIES' => append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id)) ); } if ($mode == 'window') { page_footer(); } } /** * Update last post information * Should be used instead of sync() if only the last post information are out of sync... faster * * @param string $type Can be forum|topic * @param mixed $ids topic/forum ids * @param bool $return_update_sql true: SQL query shall be returned, false: execute SQL */ function update_post_information($type, $ids, $return_update_sql = false) { global $db; if (empty($ids)) { return; } if (!is_array($ids)) { $ids = array($ids); } $update_sql = $empty_forums = $not_empty_forums = array(); if ($type != 'topic') { $topic_join = ', ' . TOPICS_TABLE . ' t'; $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_visibility = ' . ITEM_APPROVED; } else { $topic_join = ''; $topic_condition = ''; } if (sizeof($ids) == 1) { $sql = 'SELECT MAX(p.post_id) as last_post_id FROM ' . POSTS_TABLE . " p $topic_join WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " $topic_condition AND p.post_visibility = " . ITEM_APPROVED; } else { $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id FROM ' . POSTS_TABLE . " p $topic_join WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " $topic_condition AND p.post_visibility = " . ITEM_APPROVED . " GROUP BY p.{$type}_id"; } $result = $db->sql_query($sql); $last_post_ids = array(); while ($row = $db->sql_fetchrow($result)) { if (sizeof($ids) == 1) { $row[$type . '_id'] = $ids[0]; } if ($type == 'forum') { $not_empty_forums[] = $row['forum_id']; if (empty($row['last_post_id'])) { $empty_forums[] = $row['forum_id']; } } $last_post_ids[] = $row['last_post_id']; } $db->sql_freeresult($result); if ($type == 'forum') { $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums)); foreach ($empty_forums as $void => $forum_id) { $update_sql[$forum_id][] = 'forum_last_post_id = 0'; $update_sql[$forum_id][] = "forum_last_post_subject = ''"; $update_sql[$forum_id][] = 'forum_last_post_time = 0'; $update_sql[$forum_id][] = 'forum_last_poster_id = 0'; $update_sql[$forum_id][] = "forum_last_poster_name = ''"; $update_sql[$forum_id][] = "forum_last_poster_colour = ''"; } } if (sizeof($last_post_ids)) { $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id AND ' . $db->sql_in_set('p.post_id', $last_post_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id']; $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time']; $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id']; $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; } $db->sql_freeresult($result); } unset($empty_forums, $ids, $last_post_ids); if ($return_update_sql || !sizeof($update_sql)) { return $update_sql; } $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE; foreach ($update_sql as $update_id => $update_sql_ary) { $sql = "UPDATE $table SET " . implode(', ', $update_sql_ary) . " WHERE {$type}_id = $update_id"; $db->sql_query($sql); } return; } /** * Generate Topic Icons for display */ function posting_gen_topic_icons($mode, $icon_id) { global $phpbb_root_path, $config, $template, $cache; // Grab icons $icons = $cache->obtain_icons(); if (!$icon_id) { $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"'); } if (sizeof($icons)) { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; foreach ($icons as $id => $data) { if ($data['display']) { $template->assign_block_vars('topic_icon', array( 'ICON_ID' => $id, 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'], 'ICON_WIDTH' => $data['width'], 'ICON_HEIGHT' => $data['height'], 'S_CHECKED' => ($id == $icon_id) ? true : false, 'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '') ); } } return true; } return false; } /** * Build topic types able to be selected */ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) { global $auth, $user, $template, $topic_type; $toggle = false; $topic_types = array( 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') ); $topic_type_array = array(); foreach ($topic_types as $auth_key => $topic_value) { // We do not have a special post global announcement permission $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key; if ($auth->acl_get('f_' . $auth_key, $forum_id)) { $toggle = true; $topic_type_array[] = array( 'VALUE' => $topic_value['const'], 'S_CHECKED' => ($cur_topic_type == $topic_value['const']) ? ' checked="checked"' : '', 'L_TOPIC_TYPE' => $user->lang[$topic_value['lang']] ); } } if ($toggle) { $topic_type_array = array_merge(array(0 => array( 'VALUE' => POST_NORMAL, 'S_CHECKED' => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '', 'L_TOPIC_TYPE' => $user->lang['POST_NORMAL'])), $topic_type_array ); foreach ($topic_type_array as $array) { $template->assign_block_vars('topic_type', $array); } $template->assign_vars(array( 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)), 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_get('f_announce', $forum_id))) ); } return $toggle; } // // Attachment related functions // /** * Upload Attachment - filedata is generated here * Uses upload class * * @param string $form_name The form name of the file upload input * @param int $forum_id The id of the forum * @param bool $local Whether the file is local or not * @param string $local_storage The path to the local file * @param bool $is_message Whether it is a PM or not * @param \filespec $local_filedata A filespec object created for the local file * @param \phpbb\plupload\plupload $plupload The plupload object if one is being used * * @return object filespec */ function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\plupload\plupload $plupload = null) { global $auth, $user, $config, $db, $cache; global $phpbb_root_path, $phpEx; $filedata = array( 'error' => array() ); include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); $upload = new fileupload(); if ($config['check_attachment_content'] && isset($config['mime_triggers'])) { $upload->set_disallowed_content(explode('|', $config['mime_triggers'])); } $filedata['post_attach'] = $local || $upload->is_valid($form_name); if (!$filedata['post_attach']) { $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND']; return $filedata; } $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id)); $upload->set_allowed_extensions(array_keys($extensions['_allowed_'])); $file = ($local) ? $upload->local_upload($local_storage, $local_filedata) : $upload->form_upload($form_name, $plupload); if ($file->init_error) { $filedata['post_attach'] = false; return $filedata; } // Whether the uploaded file is in the image category $is_image = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false; if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id)) { // Check Image Size, if it is an image if ($is_image) { $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']); } // Admins and mods are allowed to exceed the allowed filesize if (!empty($extensions[$file->get('extension')]['max_filesize'])) { $allowed_filesize = $extensions[$file->get('extension')]['max_filesize']; } else { $allowed_filesize = ($is_message) ? $config['max_filesize_pm'] : $config['max_filesize']; } $file->upload->set_max_filesize($allowed_filesize); } $file->clean_filename('unique', $user->data['user_id'] . '_'); // Are we uploading an image *and* this image being within the image category? // Only then perform additional image checks. $file->move_file($config['upload_path'], false, !$is_image); // Do we have to create a thumbnail? $filedata['thumbnail'] = ($is_image && $config['img_create_thumbnail']) ? 1 : 0; if (sizeof($file->error)) { $file->remove(); $filedata['error'] = array_merge($filedata['error'], $file->error); $filedata['post_attach'] = false; return $filedata; } // Make sure the image category only holds valid images... if ($is_image && !$file->is_image()) { $file->remove(); if ($plupload && $plupload->is_active()) { $plupload->emit_error(104, 'ATTACHED_IMAGE_NOT_IMAGE'); } // If this error occurs a user tried to exploit an IE Bug by renaming extensions // Since the image category is displaying content inline we need to catch this. trigger_error($user->lang['ATTACHED_IMAGE_NOT_IMAGE']); } $filedata['filesize'] = $file->get('filesize'); $filedata['mimetype'] = $file->get('mimetype'); $filedata['extension'] = $file->get('extension'); $filedata['physical_filename'] = $file->get('realname'); $filedata['real_filename'] = $file->get('uploadname'); $filedata['filetime'] = time(); // Check our complete quota if ($config['attachment_quota']) { if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota']) { $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; $filedata['post_attach'] = false; $file->remove(); return $filedata; } } // Check free disk space if ($free_space = @disk_free_space($phpbb_root_path . $config['upload_path'])) { if ($free_space <= $file->get('filesize')) { if ($auth->acl_get('a_')) { $filedata['error'][] = $user->lang['ATTACH_DISK_FULL']; } else { $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; } $filedata['post_attach'] = false; $file->remove(); return $filedata; } } // Create Thumbnail if ($filedata['thumbnail']) { $source = $file->get('destination_file'); $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname'); if (!create_thumbnail($source, $destination, $file->get('mimetype'))) { $filedata['thumbnail'] = 0; } } return $filedata; } /** * Calculate the needed size for Thumbnail */ function get_img_size_format($width, $height) { global $config; // Maximum Width the Image can take $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400; if ($width > $height) { return array( round($width * ($max_width / $width)), round($height * ($max_width / $width)) ); } else { return array( round($width * ($max_width / $height)), round($height * ($max_width / $height)) ); } } /** * Return supported image types */ function get_supported_image_types($type = false) { if (@extension_loaded('gd')) { $format = imagetypes(); $new_type = 0; if ($type !== false) { // Type is one of the IMAGETYPE constants - it is fetched from getimagesize() switch ($type) { // GIF case IMAGETYPE_GIF: $new_type = ($format & IMG_GIF) ? IMG_GIF : false; break; // JPG, JPC, JP2 case IMAGETYPE_JPEG: case IMAGETYPE_JPC: case IMAGETYPE_JPEG2000: case IMAGETYPE_JP2: case IMAGETYPE_JPX: case IMAGETYPE_JB2: $new_type = ($format & IMG_JPG) ? IMG_JPG : false; break; // PNG case IMAGETYPE_PNG: $new_type = ($format & IMG_PNG) ? IMG_PNG : false; break; // WBMP case IMAGETYPE_WBMP: $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false; break; } } else { $new_type = array(); $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP); foreach ($go_through_types as $check_type) { if ($format & $check_type) { $new_type[] = $check_type; } } } return array( 'gd' => ($new_type) ? true : false, 'format' => $new_type, 'version' => (function_exists('imagecreatetruecolor')) ? 2 : 1 ); } return array('gd' => false); } /** * Create Thumbnail */ function create_thumbnail($source, $destination, $mimetype) { global $config; $min_filesize = (int) $config['img_min_thumb_filesize']; $img_filesize = (file_exists($source)) ? @filesize($source) : false; if (!$img_filesize || $img_filesize <= $min_filesize) { return false; } $dimension = @getimagesize($source); if ($dimension === false) { return false; } list($width, $height, $type, ) = $dimension; if (empty($width) || empty($height)) { return false; } list($new_width, $new_height) = get_img_size_format($width, $height); // Do not create a thumbnail if the resulting width/height is bigger than the original one if ($new_width >= $width && $new_height >= $height) { return false; } $used_imagick = false; // Only use imagemagick if defined and the passthru function not disabled if ($config['img_imagick'] && function_exists('passthru')) { if (substr($config['img_imagick'], -1) !== '/') { $config['img_imagick'] .= '/'; } @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"'); if (file_exists($destination)) { $used_imagick = true; } } if (!$used_imagick) { $type = get_supported_image_types($type); if ($type['gd']) { // If the type is not supported, we are not able to create a thumbnail if ($type['format'] === false) { return false; } switch ($type['format']) { case IMG_GIF: $image = @imagecreatefromgif($source); break; case IMG_JPG: @ini_set('gd.jpeg_ignore_warning', 1); $image = @imagecreatefromjpeg($source); break; case IMG_PNG: $image = @imagecreatefrompng($source); break; case IMG_WBMP: $image = @imagecreatefromwbmp($source); break; } if (empty($image)) { return false; } if ($type['version'] == 1) { $new_image = imagecreate($new_width, $new_height); if ($new_image === false) { return false; } imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } else { $new_image = imagecreatetruecolor($new_width, $new_height); if ($new_image === false) { return false; } // Preserve alpha transparency (png for example) @imagealphablending($new_image, false); @imagesavealpha($new_image, true); imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on') { @touch($destination); } switch ($type['format']) { case IMG_GIF: imagegif($new_image, $destination); break; case IMG_JPG: imagejpeg($new_image, $destination, 90); break; case IMG_PNG: imagepng($new_image, $destination); break; case IMG_WBMP: imagewbmp($new_image, $destination); break; } imagedestroy($new_image); } else { return false; } } if (!file_exists($destination)) { return false; } phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); return true; } /** * Assign Inline attachments (build option fields) */ function posting_gen_inline_attachments(&$attachment_data) { global $template; if (sizeof($attachment_data)) { $s_inline_attachment_options = ''; foreach ($attachment_data as $i => $attachment) { $s_inline_attachment_options .= ''; } $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options); return true; } return false; } /** * Generate inline attachment entry */ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true) { global $template, $config, $phpbb_root_path, $phpEx, $user; // Some default template variables $template->assign_vars(array( 'S_SHOW_ATTACH_BOX' => $show_attach_box, 'S_HAS_ATTACHMENTS' => sizeof($attachment_data), 'FILESIZE' => $config['max_filesize'], 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '', )); if (sizeof($attachment_data)) { // We display the posted attachments within the desired order. ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); foreach ($attachment_data as $count => $attach_row) { $hidden = ''; $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']); foreach ($attach_row as $key => $value) { $hidden .= ''; } $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false); $template->assign_block_vars('attach_row', array( 'FILENAME' => utf8_basename($attach_row['real_filename']), 'A_FILENAME' => addslashes(utf8_basename($attach_row['real_filename'])), 'FILE_COMMENT' => $attach_row['attach_comment'], 'ATTACH_ID' => $attach_row['attach_id'], 'S_IS_ORPHAN' => $attach_row['is_orphan'], 'ASSOC_INDEX' => $count, 'U_VIEW_ATTACHMENT' => $download_link, 'S_HIDDEN' => $hidden) ); } } return sizeof($attachment_data); } // // General Post functions // /** * Load Drafts */ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0) { global $user, $db, $template, $auth; global $phpbb_root_path, $phpEx; $topic_ids = $forum_ids = $draft_rows = array(); // Load those drafts not connected to forums/topics // If forum_id == 0 AND topic_id == 0 then this is a PM draft if (!$topic_id && !$forum_id) { $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0'; } else { $sql_and = ''; $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : ''; $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : ''; } $sql = 'SELECT d.*, f.forum_id, f.forum_name FROM ' . DRAFTS_TABLE . ' d LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id) WHERE d.user_id = ' . $user->data['user_id'] . " $sql_and ORDER BY d.save_time DESC"; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { if ($row['topic_id']) { $topic_ids[] = (int) $row['topic_id']; } $draft_rows[] = $row; } $db->sql_freeresult($result); if (!sizeof($draft_rows)) { return; } $topic_rows = array(); if (sizeof($topic_ids)) { $sql = 'SELECT topic_id, forum_id, topic_title FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $topic_rows[$row['topic_id']] = $row; } $db->sql_freeresult($result); } unset($topic_ids); $template->assign_var('S_SHOW_DRAFTS', true); foreach ($draft_rows as $draft) { $link_topic = $link_forum = $link_pm = false; $insert_url = $view_url = $title = ''; if (isset($topic_rows[$draft['topic_id']]) && ( ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) || (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read')) )) { $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id; $link_topic = true; $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id']); $title = $topic_rows[$draft['topic_id']]['topic_title']; $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); } else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id'])) { $link_forum = true; $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']); $title = $draft['forum_name']; $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']); } else { // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards... $link_pm = true; $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d={$draft['draft_id']}" . (($pm_action) ? "&action=$pm_action" : '') . (($msg_id) ? "&p=$msg_id" : '')); } $template->assign_block_vars('draftrow', array( 'DRAFT_ID' => $draft['draft_id'], 'DATE' => $user->format_date($draft['save_time']), 'DRAFT_SUBJECT' => $draft['draft_subject'], 'TITLE' => $title, 'U_VIEW' => $view_url, 'U_INSERT' => $insert_url, 'S_LINK_PM' => $link_pm, 'S_LINK_TOPIC' => $link_topic, 'S_LINK_FORUM' => $link_forum) ); } } /** * Topic Review */ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true) { global $user, $auth, $db, $template, $bbcode, $cache; global $config, $phpbb_root_path, $phpEx, $phpbb_container; $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // Go ahead and pull all data for this topic $sql = 'SELECT p.post_id FROM ' . POSTS_TABLE . ' p' . " WHERE p.topic_id = $topic_id AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . ' ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . ' ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . ' ORDER BY p.post_time '; $sql .= ($mode == 'post_review') ? 'ASC' : 'DESC'; $result = $db->sql_query_limit($sql, $config['posts_per_page']); $post_list = array(); while ($row = $db->sql_fetchrow($result)) { $post_list[] = $row['post_id']; } $db->sql_freeresult($result); if (!sizeof($post_list)) { return false; } // Handle 'post_review_edit' like 'post_review' from now on if ($mode == 'post_review_edit') { $mode = 'post_review'; } $sql_ary = array( 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe', 'FROM' => array( USERS_TABLE => 'u', POSTS_TABLE => 'p', ), 'LEFT_JOIN' => array( array( 'FROM' => array(ZEBRA_TABLE => 'z'), 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id', ), ), 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' AND u.user_id = p.poster_id', ); $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $bbcode_bitfield = ''; $rowset = array(); $has_attachments = false; while ($row = $db->sql_fetchrow($result)) { $rowset[$row['post_id']] = $row; $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); if ($row['post_attachment']) { $has_attachments = true; } } $db->sql_freeresult($result); // Instantiate BBCode class if (!isset($bbcode) && $bbcode_bitfield !== '') { include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); $bbcode = new bbcode(base64_encode($bbcode_bitfield)); } // Grab extensions $extensions = $attachments = array(); if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) { $extensions = $cache->obtain_attach_extensions($forum_id); // Get attachments... $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . ' AND in_message = 0 ORDER BY filetime DESC, post_msg_id ASC'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $attachments[$row['post_msg_id']][] = $row; } $db->sql_freeresult($result); } for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) { // A non-existing rowset only happens if there was no user present for the entered poster_id // This could be a broken posts table. if (!isset($rowset[$post_list[$i]])) { continue; } $row = $rowset[$post_list[$i]]; $poster_id = $row['user_id']; $post_subject = $row['post_subject']; $decoded_message = false; if ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) { $decoded_message = censor_text($row['post_text']); decode_message($decoded_message, $row['bbcode_uid']); $decoded_message = bbcode_nl2br($decoded_message); } $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0); $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0); $message = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true); if (!empty($attachments[$row['post_id']])) { $update_count = array(); parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count); } $post_subject = censor_text($post_subject); $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); $template->assign_block_vars($mode . '_row', array( 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR' => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'U_POST_AUTHOR' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, 'S_FRIEND' => ($row['friend']) ? true : false, 'S_IGNORE_POST' => ($row['foe']) ? true : false, 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "", '') : '', 'POST_SUBJECT' => $post_subject, 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), 'POST_DATE' => $user->format_date($row['post_time']), 'MESSAGE' => $message, 'DECODED_MESSAGE' => $decoded_message, 'POST_ID' => $row['post_id'], 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'], 'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '') ); // Display not already displayed Attachments for this post, we already parsed them. ;) if (!empty($attachments[$row['post_id']])) { foreach ($attachments[$row['post_id']] as $attachment) { $template->assign_block_vars($mode . '_row.attachment', array( 'DISPLAY_ATTACHMENT' => $attachment) ); } } unset($rowset[$post_list[$i]]); } if ($mode == 'topic_review') { $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE'])); } return true; } // // Post handling functions // /** * Delete Post */ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '') { global $db, $user, $auth, $phpbb_container; global $config, $phpEx, $phpbb_root_path; // Specify our post mode $post_mode = 'delete'; if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1)) { $post_mode = 'delete_topic'; } else if ($data['topic_first_post_id'] == $post_id) { $post_mode = 'delete_first_post'; } else if ($data['topic_last_post_id'] == $post_id) { $post_mode = 'delete_last_post'; } $sql_data = array(); $next_post_id = false; include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); $db->sql_transaction('begin'); // we must make sure to update forums that contain the shadow'd topic if ($post_mode == 'delete_topic') { $shadow_forum_ids = array(); $sql = 'SELECT forum_id FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { if (!isset($shadow_forum_ids[(int) $row['forum_id']])) { $shadow_forum_ids[(int) $row['forum_id']] = 1; } else { $shadow_forum_ids[(int) $row['forum_id']]++; } } $db->sql_freeresult($result); } $phpbb_content_visibility = $phpbb_container->get('content.visibility'); // (Soft) delete the post if ($is_soft && ($post_mode != 'delete_topic')) { $phpbb_content_visibility->set_post_visibility(ITEM_DELETED, $post_id, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason, ($data['topic_first_post_id'] == $post_id), ($data['topic_last_post_id'] == $post_id)); } else if (!$is_soft) { if (!delete_posts('post_id', array($post_id), false, false, false)) { // Try to delete topic, we may had an previous error causing inconsistency if ($post_mode == 'delete_topic') { delete_topics('topic_id', array($topic_id), false); } trigger_error('ALREADY_DELETED'); } } $db->sql_transaction('commit'); // Collect the necessary information for updating the tables $sql_data[FORUMS_TABLE] = $sql_data[TOPICS_TABLE] = ''; switch ($post_mode) { case 'delete_topic': foreach ($shadow_forum_ids as $updated_forum => $topic_count) { // counting is fun! we only have to do sizeof($forum_ids) number of queries, // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum) $sql = 'UPDATE ' . FORUMS_TABLE . ' SET forum_topics_approved = forum_topics_approved - ' . $topic_count . ' WHERE forum_id = ' . $updated_forum; $db->sql_query($sql); update_post_information('forum', $updated_forum); } if ($is_soft) { $topic_row = array(); $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason); } else { delete_topics('topic_id', array($topic_id), false); if ($data['topic_visibility'] == ITEM_APPROVED) { $sql_data[FORUMS_TABLE] .= 'forum_posts_approved = forum_posts_approved - 1, forum_topics_approved = forum_topics_approved - 1'; } else if ($data['topic_visibility'] == ITEM_UNAPPROVED) { $sql_data[FORUMS_TABLE] .= 'forum_posts_unapproved = forum_posts_unapproved - 1, forum_topics_unapproved = forum_topics_unapproved - 1'; } else if ($data['topic_visibility'] == ITEM_DELETED) { $sql_data[FORUMS_TABLE] .= 'forum_posts_softdeleted = forum_posts_softdeleted - 1, forum_topics_softdeleted = forum_topics_softdeleted - 1'; } $update_sql = update_post_information('forum', $forum_id, true); if (sizeof($update_sql)) { $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); } } break; case 'delete_first_post': $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u WHERE p.topic_id = $topic_id AND p.poster_id = u.user_id AND p.post_visibility = " . ITEM_APPROVED . ' ORDER BY p.post_time ASC'; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); if (!$row) { // No approved post, so the first is a not-approved post (unapproved or soft deleted) $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u WHERE p.topic_id = $topic_id AND p.poster_id = u.user_id ORDER BY p.post_time ASC"; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); } $next_post_id = (int) $row['post_id']; $sql_data[TOPICS_TABLE] = $db->sql_build_array('UPDATE', array( 'topic_poster' => (int) $row['poster_id'], 'topic_first_post_id' => (int) $row['post_id'], 'topic_first_poster_colour' => $row['user_colour'], 'topic_first_poster_name' => ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'], 'topic_time' => (int) $row['post_time'], )); break; case 'delete_last_post': if (!$is_soft) { // Update last post information when hard deleting. Soft delete already did that by itself. $update_sql = update_post_information('forum', $forum_id, true); if (sizeof($update_sql)) { $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]); } $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_bumped = 0, topic_bumper = 0'; $update_sql = update_post_information('topic', $topic_id, true); if (!empty($update_sql)) { $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]); $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]); } } if (!$next_post_id) { $sql = 'SELECT MAX(post_id) as last_post_id FROM ' . POSTS_TABLE . " WHERE topic_id = $topic_id AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id); $result = $db->sql_query($sql); $next_post_id = (int) $db->sql_fetchfield('last_post_id'); $db->sql_freeresult($result); } break; case 'delete': $sql = 'SELECT post_id FROM ' . POSTS_TABLE . " WHERE topic_id = $topic_id AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . ' AND post_time > ' . $data['post_time'] . ' ORDER BY post_time ASC'; $result = $db->sql_query_limit($sql, 1); $next_post_id = (int) $db->sql_fetchfield('post_id'); $db->sql_freeresult($result); break; } if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post')) { if (!$is_soft) { if ($data['post_visibility'] == ITEM_APPROVED) { $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data); } else if ($data['post_visibility'] == ITEM_UNAPPROVED) { $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_unapproved = forum_posts_unapproved - 1'; $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_unapproved = topic_posts_unapproved - 1'; } else if ($data['post_visibility'] == ITEM_DELETED) { $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_softdeleted = forum_posts_softdeleted - 1'; $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_softdeleted = topic_posts_softdeleted - 1'; } } $sql = 'SELECT 1 AS has_attachments FROM ' . ATTACHMENTS_TABLE . ' WHERE topic_id = ' . $topic_id; $result = $db->sql_query_limit($sql, 1); $has_attachments = (int) $db->sql_fetchfield('has_attachments'); $db->sql_freeresult($result); if (!$has_attachments) { $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_attachment = 0'; } } $db->sql_transaction('begin'); $where_sql = array( FORUMS_TABLE => "forum_id = $forum_id", TOPICS_TABLE => "topic_id = $topic_id", USERS_TABLE => 'user_id = ' . $data['poster_id'], ); foreach ($sql_data as $table => $update_sql) { if ($update_sql) { $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]); } } // Adjust posted info for this user by looking for a post by him/her within this topic... if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS) { $sql = 'SELECT poster_id FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . $topic_id . ' AND poster_id = ' . $data['poster_id']; $result = $db->sql_query_limit($sql, 1); $poster_id = (int) $db->sql_fetchfield('poster_id'); $db->sql_freeresult($result); // The user is not having any more posts within this topic if (!$poster_id) { $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' WHERE topic_id = ' . $topic_id . ' AND user_id = ' . $data['poster_id']; $db->sql_query($sql); } } $db->sql_transaction('commit'); if ($data['post_reported'] && ($post_mode != 'delete_topic')) { sync('topic_reported', 'topic_id', array($topic_id)); } return $next_post_id; } /** * Submit Post * @todo Split up and create lightweight, simple API for this. */ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) { global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher; // We do not handle erasing posts here if ($mode == 'delete') { return false; } $current_time = time(); if ($mode == 'post') { $post_mode = 'post'; $update_message = true; } else if ($mode != 'edit') { $post_mode = 'reply'; $update_message = true; } else if ($mode == 'edit') { $post_mode = ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit')); } // First of all make sure the subject and topic title are having the correct length. // To achieve this without cutting off between special chars we convert to an array and then count the elements. $subject = truncate_string($subject, 120); $data['topic_title'] = truncate_string($data['topic_title'], 120); // Collect some basic information about which tables and which rows to update/insert $sql_data = $topic_row = array(); $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id']; // Retrieve some additional information if not present if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false)) { $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p WHERE t.topic_id = p.topic_id AND p.post_id = ' . $data['post_id']; $result = $db->sql_query($sql); $topic_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); $data['topic_visibility'] = $topic_row['topic_visibility']; $data['post_visibility'] = $topic_row['post_visibility']; } // This variable indicates if the user is able to post or put into the queue $post_visibility = ITEM_APPROVED; // Check the permissions for post approval. // Moderators must go through post approval like ordinary users. if (!$auth->acl_get('f_noapprove', $data['forum_id'])) { // Post not approved, but in queue $post_visibility = ITEM_UNAPPROVED; } // MODs/Extensions are able to force any visibility on posts if (isset($data['force_approved_state'])) { $post_visibility = (in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED))) ? (int) $data['force_approved_state'] : $post_visibility; } if (isset($data['force_visibility'])) { $post_visibility = (in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED))) ? (int) $data['force_visibility'] : $post_visibility; } // Start the transaction here $db->sql_transaction('begin'); // Collect Information switch ($post_mode) { case 'post': case 'reply': $sql_data[POSTS_TABLE]['sql'] = array( 'forum_id' => $data['forum_id'], 'poster_id' => (int) $user->data['user_id'], 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_visibility' => $post_visibility, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => (!$user->data['is_registered']) ? $username : '', 'post_subject' => $subject, 'post_text' => $data['message'], 'post_checksum' => $data['message_md5'], 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0, 'post_edit_locked' => $data['post_edit_locked'] ); break; case 'edit_first_post': case 'edit': case 'edit_last_post': case 'edit_topic': // If edit reason is given always display edit info // If editing last post then display no edit info // If m_edit permission then display no edit info // If normal edit display edit info // Display edit info if edit reason given or user is editing his post, which is not the last within the topic. if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post'))) { $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false); $sql_data[POSTS_TABLE]['sql'] = array( 'post_edit_time' => $current_time, 'post_edit_reason' => $data['post_edit_reason'], 'post_edit_user' => (int) $data['post_edit_user'], ); $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1'; } else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id'])) { $sql_data[POSTS_TABLE]['sql'] = array( 'post_edit_reason' => '', ); } // If the person editing this post is different to the one having posted then we will add a log entry stating the edit // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods if ($user->data['user_id'] != $poster_id) { $log_subject = ($subject) ? $subject : $data['topic_title']; add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST']); } if (!isset($sql_data[POSTS_TABLE]['sql'])) { $sql_data[POSTS_TABLE]['sql'] = array(); } $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 'forum_id' => $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], // We will change the visibility later //'post_visibility' => $post_visibility, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '', 'post_subject' => $subject, 'post_checksum' => $data['message_md5'], 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_edit_locked' => $data['post_edit_locked']) ); if ($update_message) { $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message']; } break; } $topic_row = array(); // And the topic ladies and gentlemen switch ($post_mode) { case 'post': $sql_data[TOPICS_TABLE]['sql'] = array( 'topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, 'forum_id' => $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_posts_approved' => ($post_visibility == ITEM_APPROVED) ? 1 : 0, 'topic_posts_softdeleted' => ($post_visibility == ITEM_DELETED) ? 1 : 0, 'topic_posts_unapproved' => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0, 'topic_visibility' => $post_visibility, 'topic_delete_user' => ($post_visibility != ITEM_APPROVED) ? (int) $user->data['user_id'] : 0, 'topic_title' => $subject, 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, ); if (isset($poll['poll_options']) && !empty($poll['poll_options'])) { $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; $poll_length = $poll['poll_length'] * 86400; if ($poll_length < 0) { $poll_start = $poll_start + $poll_length; if ($poll_start < 0) { $poll_start = 0; } $poll_length = 1; } $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array( 'poll_title' => $poll['poll_title'], 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']) ); } $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); if ($post_visibility == ITEM_APPROVED) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1'; } else if ($post_visibility == ITEM_UNAPPROVED) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1'; } else if ($post_visibility == ITEM_DELETED) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1'; } break; case 'reply': $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ', topic_bumped = 0, topic_bumper = 0' . (($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') . (($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') . (($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') . ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); if ($post_visibility == ITEM_APPROVED) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1'; } else if ($post_visibility == ITEM_UNAPPROVED) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1'; } else if ($post_visibility == ITEM_DELETED) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1'; } break; case 'edit_topic': case 'edit_first_post': if (isset($poll['poll_options'])) { $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time; $poll_length = $poll['poll_length'] * 86400; if ($poll_length < 0) { $poll_start = $poll_start + $poll_length; if ($poll_start < 0) { $poll_start = 0; } $poll_length = 1; } } $sql_data[TOPICS_TABLE]['sql'] = array( 'forum_id' => $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '', 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0, 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1, 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0, 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0), ); break; } // Submit new topic if ($post_mode == 'post') { $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']); $db->sql_query($sql); $data['topic_id'] = $db->sql_nextid(); $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 'topic_id' => $data['topic_id']) ); unset($sql_data[TOPICS_TABLE]['sql']); } // Submit new post if ($post_mode == 'post' || $post_mode == 'reply') { if ($post_mode == 'reply') { $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 'topic_id' => $data['topic_id'], )); } $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); $db->sql_query($sql); $data['post_id'] = $db->sql_nextid(); if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED) { $sql_data[TOPICS_TABLE]['sql'] = array( 'topic_last_post_id' => $data['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'], 'topic_last_poster_name' => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'], 'topic_last_poster_colour' => $user->data['user_colour'], 'topic_last_post_subject' => (string) $subject, ); } if ($post_mode == 'post') { $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id']; } // Update total post count and forum information if ($post_visibility == ITEM_APPROVED) { if ($post_mode == 'post') { set_config_count('num_topics', 1, true); } set_config_count('num_posts', 1, true); $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'"; } unset($sql_data[POSTS_TABLE]['sql']); } // Update the topics table if (isset($sql_data[TOPICS_TABLE]['sql'])) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . ' WHERE topic_id = ' . $data['topic_id']; $db->sql_query($sql); unset($sql_data[TOPICS_TABLE]['sql']); } // Update the posts table if (isset($sql_data[POSTS_TABLE]['sql'])) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . ' WHERE post_id = ' . $data['post_id']; $db->sql_query($sql); unset($sql_data[POSTS_TABLE]['sql']); } // Update Poll Tables if (isset($poll['poll_options'])) { $cur_poll_options = array(); if ($mode == 'edit') { $sql = 'SELECT * FROM ' . POLL_OPTIONS_TABLE . ' WHERE topic_id = ' . $data['topic_id'] . ' ORDER BY poll_option_id'; $result = $db->sql_query($sql); $cur_poll_options = array(); while ($row = $db->sql_fetchrow($result)) { $cur_poll_options[] = $row; } $db->sql_freeresult($result); } $sql_insert_ary = array(); for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) { if (strlen(trim($poll['poll_options'][$i]))) { if (empty($cur_poll_options[$i])) { // If we add options we need to put them to the end to be able to preserve votes... $sql_insert_ary[] = array( 'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), 'topic_id' => (int) $data['topic_id'], 'poll_option_text' => (string) $poll['poll_options'][$i] ); } else if ($poll['poll_options'][$i] != $cur_poll_options[$i]) { $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . " SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "' WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . ' AND topic_id = ' . $data['topic_id']; $db->sql_query($sql); } } } $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary); if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) { $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . ' WHERE poll_option_id > ' . sizeof($poll['poll_options']) . ' AND topic_id = ' . $data['topic_id']; $db->sql_query($sql); } // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) { $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']); $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']); } } // Submit Attachments if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) { $space_taken = $files_added = 0; $orphan_rows = array(); foreach ($data['attachment_data'] as $pos => $attach_row) { $orphan_rows[(int) $attach_row['attach_id']] = array(); } if (sizeof($orphan_rows)) { $sql = 'SELECT attach_id, filesize, physical_filename FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' AND is_orphan = 1 AND poster_id = ' . $user->data['user_id']; $result = $db->sql_query($sql); $orphan_rows = array(); while ($row = $db->sql_fetchrow($result)) { $orphan_rows[$row['attach_id']] = $row; } $db->sql_freeresult($result); } foreach ($data['attachment_data'] as $pos => $attach_row) { if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) { continue; } if (!$attach_row['is_orphan']) { // update entry in db if attachment already stored in db and filespace $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' WHERE attach_id = " . (int) $attach_row['attach_id'] . ' AND is_orphan = 0'; $db->sql_query($sql); } else { // insert attachment into db if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) { continue; } $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; $files_added++; $attach_sql = array( 'post_msg_id' => $data['post_id'], 'topic_id' => $data['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment'], ); $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . ' WHERE attach_id = ' . $attach_row['attach_id'] . ' AND is_orphan = 1 AND poster_id = ' . $user->data['user_id']; $db->sql_query($sql); } } if ($space_taken && $files_added) { set_config_count('upload_dir_size', $space_taken, true); set_config_count('num_files', $files_added, true); } } $first_post_has_topic_info = ($post_mode == 'edit_first_post' && (($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1) || ($post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1) || ($post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1))); // Fix the post's and topic's visibility and first/last post information, when the post is edited if (($post_mode != 'post' && $post_mode != 'reply') && $data['post_visibility'] != $post_visibility) { // If the post was not approved, it could also be the starter, // so we sync the starter after approving/restoring, to ensure that the stats are correct // Same applies for the last post $is_starter = ($post_mode == 'edit_first_post' || $data['post_visibility'] != ITEM_APPROVED); $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED); $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest); } else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info) { if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility) { // only the subject can be changed from edit $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; // Maybe not only the subject, but also changing anonymous usernames. ;) if ($data['poster_id'] == ANONYMOUS) { $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'"; } if ($post_visibility == ITEM_APPROVED) { // this does not _necessarily_ mean that we must update the info again, // it just means that we might have to $sql = 'SELECT forum_last_post_id, forum_last_post_subject FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . (int) $data['forum_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // this post is the latest post in the forum, better update if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) { // the post's subject changed if ($row['forum_last_post_subject'] !== $subject) { $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; } // Update the user name if poster is anonymous... just in case a moderator changed it if ($data['poster_id'] == ANONYMOUS) { $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; } } } } } // Update forum stats $where_sql = array( POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id ); foreach ($sql_data as $table => $update_ary) { if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) { $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table]; $db->sql_query($sql); } } // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement if ($topic_type == POST_GLOBAL) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' WHERE topic_moved_id = ' . $data['topic_id']; $db->sql_query($sql); } // Committing the transaction before updating search index $db->sql_transaction('commit'); // Delete draft if post was loaded... $draft_id = request_var('draft_loaded', 0); if ($draft_id) { $sql = 'DELETE FROM ' . DRAFTS_TABLE . " WHERE draft_id = $draft_id AND user_id = {$user->data['user_id']}"; $db->sql_query($sql); } // Index message contents if ($update_search_index && $data['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised $search_type = $config['search_type']; if (!class_exists($search_type)) { trigger_error('NO_SUCH_SEARCH_MODULE'); } $error = false; $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); if ($error) { trigger_error($error); } $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']); } // Topic Notification, do not change if moderator is changing other users posts... if ($user->data['user_id'] == $poster_id) { if (!$data['notify_set'] && $data['notify']) { $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id) VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')'; $db->sql_query($sql); } else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify']) { $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' AND topic_id = ' . $data['topic_id']; $db->sql_query($sql); } } if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') { // Mark this topic as posted to markread('post', $data['forum_id'], $data['topic_id']); } // Mark this topic as read // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message) markread('topic', $data['forum_id'], $data['topic_id'], time()); // if ($config['load_db_lastread'] && $user->data['is_registered']) { $sql = 'SELECT mark_time FROM ' . FORUMS_TRACK_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' AND forum_id = ' . $data['forum_id']; $result = $db->sql_query($sql); $f_mark_time = (int) $db->sql_fetchfield('mark_time'); $db->sql_freeresult($result); } else if ($config['load_anon_lastread'] || $user->data['is_registered']) { $f_mark_time = false; } if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) { // Update forum info $sql = 'SELECT forum_last_post_time FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . $data['forum_id']; $result = $db->sql_query($sql); $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); $db->sql_freeresult($result); update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false); } // If a username was supplied or the poster is a guest, we will use the supplied username. // Doing it this way we can use "...post by guest-username..." in notifications when // "guest-username" is supplied or ommit the username if it is not. $username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username']; // Send Notifications $notification_data = array_merge($data, array( 'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject, 'post_username' => $username, 'poster_id' => $poster_id, 'post_text' => $data['message'], 'post_time' => $current_time, 'post_subject' => $subject, )); $phpbb_notifications = $phpbb_container->get('notification_manager'); if ($post_visibility == ITEM_APPROVED) { switch ($mode) { case 'post': $phpbb_notifications->add_notifications(array( 'quote', 'topic', ), $notification_data); break; case 'reply': case 'quote': $phpbb_notifications->add_notifications(array( 'quote', 'bookmark', 'post', ), $notification_data); break; case 'edit_topic': case 'edit_first_post': case 'edit': case 'edit_last_post': $phpbb_notifications->update_notifications(array( 'quote', 'bookmark', 'topic', 'post', ), $notification_data); break; } } else if ($post_visibility == ITEM_UNAPPROVED) { switch ($mode) { case 'post': $phpbb_notifications->add_notifications('topic_in_queue', $notification_data); break; case 'reply': case 'quote': $phpbb_notifications->add_notifications('post_in_queue', $notification_data); break; case 'edit_topic': case 'edit_first_post': case 'edit': case 'edit_last_post': // @todo: Check whether these notification deletions are correct $phpbb_notifications->delete_notifications('topic', $data['topic_id']); $phpbb_notifications->delete_notifications(array( 'quote', 'bookmark', 'post', ), $data['post_id']); break; } } else if ($post_visibility == ITEM_DELETED) { switch ($mode) { case 'post': case 'reply': case 'quote': // Nothing to do here break; case 'edit_topic': case 'edit_first_post': case 'edit': case 'edit_last_post': // @todo: Check whether these notification deletions are correct $phpbb_notifications->delete_notifications('topic', $data['topic_id']); $phpbb_notifications->delete_notifications(array( 'quote', 'bookmark', 'post', ), $data['post_id']); break; } } $params = $add_anchor = ''; if ($post_visibility == ITEM_APPROVED) { $params .= '&t=' . $data['topic_id']; if ($mode != 'post') { $params .= '&p=' . $data['post_id']; $add_anchor = '#p' . $data['post_id']; } } else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') { $params .= '&t=' . $data['topic_id']; } $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx"; $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor; /** * This event is used for performing actions directly after a post or topic * has been submitted. When a new topic is posted, the topic ID is * available in the $data array. * * The only action that can be done by altering data made available to this * event is to modify the return URL ($url). * * @event core.submit_post_end * @var string url The "Return to topic" URL * @var array data Array of post data about the * submitted post * @since 3.1-A3 */ $vars = array('url', 'data'); extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars))); return $url; } /** * Handle topic bumping * @param int $forum_id The ID of the forum the topic is being bumped belongs to * @param int $topic_id The ID of the topic is being bumping * @param array $post_data Passes some topic parameters: * - 'topic_title' * - 'topic_last_post_id' * - 'topic_last_poster_id' * - 'topic_last_post_subject' * - 'topic_last_poster_name' * - 'topic_last_poster_colour' * @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time(). * @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&topic_id=2&p=3#p3 */ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) { global $config, $db, $user, $phpEx, $phpbb_root_path; if ($bump_time === false) { $bump_time = time(); } // Begin bumping $db->sql_transaction('begin'); // Update the topic's last post post_time $sql = 'UPDATE ' . POSTS_TABLE . " SET post_time = $bump_time WHERE post_id = {$post_data['topic_last_post_id']} AND topic_id = $topic_id"; $db->sql_query($sql); // Sync the topic's last post time, the rest of the topic's last post data isn't changed $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_post_time = $bump_time, topic_bumped = 1, topic_bumper = " . $user->data['user_id'] . " WHERE topic_id = $topic_id"; $db->sql_query($sql); // Update the forum's last post info $sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ", forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ", forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "', forum_last_post_time = $bump_time, forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "', forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "' WHERE forum_id = $forum_id"; $db->sql_query($sql); // Update bumper's time of the last posting to prevent flood $sql = 'UPDATE ' . USERS_TABLE . " SET user_lastpost_time = $bump_time WHERE user_id = " . $user->data['user_id']; $db->sql_query($sql); $db->sql_transaction('commit'); // Mark this topic as posted to markread('post', $forum_id, $topic_id, $bump_time); // Mark this topic as read markread('topic', $forum_id, $topic_id, $bump_time); // Update forum tracking info if ($config['load_db_lastread'] && $user->data['is_registered']) { $sql = 'SELECT mark_time FROM ' . FORUMS_TRACK_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' AND forum_id = ' . $forum_id; $result = $db->sql_query($sql); $f_mark_time = (int) $db->sql_fetchfield('mark_time'); $db->sql_freeresult($result); } else if ($config['load_anon_lastread'] || $user->data['is_registered']) { $f_mark_time = false; } if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) { // Update forum info $sql = 'SELECT forum_last_post_time FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . $forum_id; $result = $db->sql_query($sql); $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); $db->sql_freeresult($result); update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false); } add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']); $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}"; return $url; } wŁ"`E~mP2FBs+7 4d_ wɇ03I x"]~׈)!_ \8Hd0 6ܜvMtV\V7ي[Vg%z2ןݩK ?^l(޽;wƫǨ}S=SZF $o?=m֍+l/7lbظp9)x^9 1[>DsLˀtK%Kųk[:!xS]DkO@5pI 4n. K zyt`8O ٞD8 1X1qp<շ/ 1-&A+0 2@Lg -$-_*Ւ3S)MA-+*<2ӕt'Uuy[Oڲ*~ wv;\<& 5W碋z#fc/<*LL*73i ]%I+7<'euuٿ>r ^7?"B0]URCT4ALbD*v"j1O~pC:2{a2f<;C2|=zݕNѣ rO>%H4nP,PjG'0l&Nlr BH`@;ұ;m“?TZ`gz) }.03ֻD5ǏEmT:6W9qgYΒ3qcw&6n>kh;QR\P?RTFWpMS n[Jrf@R[}M%v@aҳHXz Z7.|^GLlm0hBRܸџYO:a[4k>AKOwHD pFp !yDB~)>VϠ2`3`ĊP0LA:nyy,^QV'-AnnH<+xYj +pEU!ܱ!Cf @hwxo;v*0!Vެm*NSuUZ$X)+4$Lh+d*ڦIg>%=ײomj w-ކ>[#гu+ߊ<\Qa:FL3i8u2mX9*,t[^f!>')B4.k2Sj% U)$4oˮ^4o\)KdDMw\GK/OT~[X'aR }I^V8SyKws_YZrra<;0"6݊ #E6N+kʭu !CGˆ7X]L2Uzto]jތHz`uPW 6-Gk})7p\OONRj!UE63u}Mդe4׶dM@ibY:Ah tB oF/SΊ-RjoΔQ[;{&9+23 e6 k+޵[5VR1 ⭜(4^xJĔe&G ̉㞴H;r ؍Tyn60\@1A:a_%o$( l.P@IXc2\;VנHIj-%E I軇Mԃ| =C#fյZ1!b<5:)KR؋EgmjʞiUr~OTܚ.!2DȁZB!$'ج!L%uG;9Koi" oKgciV˩hՃDO95f/}j:c2.8]٦4w3IbVd" eI/wӢNa6H .̲ ^*̔SMje7]jKuLwuwQp 0nl$j)Yx($pœ_{Zc`e6ZTBNw n Wɏ f@|)/c' : _挋BNWPW1ޒM.71}Y_֕g6O4ƇgS!9cP=ջ `dfg#HKJY(ʗs{Mb8ԈcHta ^_N_:@!wU`*ve_ׅO>lfH )n:^Ə[5u@n˻UdŔ+zVfb„\& R9i+&20u eT\9rZo Rhn]~x-7-؋|i`<~)l40B'KQ)v;OŖ)k4hߚڲ\H -ko^H^˄pݕ[<2(*+z/K+hCݽ+͟;809zDw$<Fi H[<8S-RaR@RHƏlagE[8 qY'|5/h׵rx?_aiwo*Ne ۰M3aZ9"?&q(W+"2#*Lt55@K%@R #Bt-գKd~~<5?BLC3Zt!13-HOf|8 Agr}oB`*;>j[މ IǯR~ Qb7ࡶ늒/"4f;`g~{|d{uS;H7)AC%m琨Un& _ƾ|`EIGӂiPT5]׹}nͽG")Piv;lFrwnVZq5%2Q[(@*`וx?uKr<}_L[7 *~B{NVƠP[YQ"WMK[&{;9(wؚYޭmu!0uyw={}\\ִ~[] #ڜSff[W1)%c.o"ﳨ@!P8>^yNL>2{0DKKRnzsys?b;8S9%I&q]c,jS])`U=zfŵj(zE6 G19CG;>n$ޞV8hՆ:v{a iBNqb]ևqx%;CҘ(yʝUS?(>udFt6YwW3uА1OHm:? R]bĈ/!$tG(N%98+#C!lo8%r$NB3ZBf E*.}ȟX!nA2]ПaRfh4kÖ:` kVwUy06N<ؙvFm:|#'ŏdQe,­bݶ,N47SZ"lSQ30q`["bt$=s2:J4XߩfǼ @U>f V/!b:ŎBڠ3nPQ_bN5 10MIAJiD- .EOKMF~ݹ0i6y t Q6=x^hS4gZ3X%=.}z?,]ˆ*V(K{^G*/XK.RcPUnS"iY< Dm)?XH V:+'q 9r3B;z!U;!VW5445i})l-oN4oBpLRg- !4zju^Mgaz.$h!8*iG\9>0ea#p5tSX@[IrCם[ 6(r5H%gqAWQ ċΏȁJmE'>t?Ӑ氢* Qyp3cA%.573(l1OV")X2;N e]D"nι@t_8b`1-njSU;oNwrWv X]29XgOо4<&BJ*Z?I^n>N+LlKեybW8s/+YvA(\jT _䫒@2 W IG#i.?j9q[xrVWiX:ssԉ;4 >EҤNw cEݭV1!!4}Dxv_xrOEeq۞G?9O:wL{q&(/L P)W<ÞTpo`}pWx䁤l3E? ސbT`v <ј]Cʵq!E$6ÁOj\rEb`*PӐ|$ŏ?+e`-ڒ#86U%T fRp߮7F&V^܇x;AF8q}L[1߈+?_=:I/ ƄE`LJ:|˽/q!zSWib63{e~v2\81Y&Ac𨝢"g>͞GPpZ)'ۧ7w.u}꼮Ӂџ!X $krfp20̓Gš*aq`Og%*=Tv˸ɖXͦ$iSzdtmd~˰iG&%>b-ht±gd+a–:$a(Nuۃh ЙD_<.`y lU؋Wyl"Gl\S,T'g1n'Fd^uLJ@+`v4wRܼKB{Di f i*|6!yaS!lύ@Ze`;+:Y3kݻ#/ @9y:.SsQd3l4SR4[UJ(5"iV^ϋM<~,B_ҿ Qohw7ao}Ev8rL)UUW*3_:5 >J@mv|2Ƿ*:f;ts^.AMk ]} xcLy Vl0&3מJ,L3YyQnZ(ck, `tZ/b@jLC<LO;Y7Q&D +Ya& ɧh'=VPaD!59cSOYV鰆] 8me fռ_cD\?$HKDoL1{ǸFZp (%SI1|MPɉZxW3}po 8Pq})h27JKAOLP3JE;XL]e%:F%PeF!ÒFXUM1'kqwN*T%}ZpE2MAi*l oV2e2U>T~M*OºY{#3>`ʔ-FVJKF8xKMYՆŶ˵Jس*~ʭweb K2y/ 8!1߆haDlx۩ג6 _ .<rp:3ޘqлIC.4MԕUzK)gjԦJsWH^."*Ml9?-!Е|mzYETrOB5&NƨGM7Q*͹gݘnXtR~V8LA.-?N**j'`}aq WZյŻJ-I' {QH>7VibU!lVs;Gma~N}mZs'Z,q[g{ny 1c 9DL:'6dUO'Ӫo1et]JGE7#sx\=,JVTE/&~5{b85_ݲ+4znuE<{# cLg=搐_49oxW=J o0pv.ʠUfdΨYL⓺H/8cM3E윶rB4Ӹb`JX:$vQDyy /D@ SX֜s+H =ԎAR֕]Vº%C>LrBs+wxCMÖr_`ws*Kd# ߏɜ6({ך5#k]Hg*M=nZތ5QI:}@=,CfΙ+Nro,esMr^cU}hحEAS r0)cSDBX>)YU#VXU  03Afp.XɭPB =K#t?TGY.xY#f^ƀ8oM,W3%+P(UW"QP5nk=D]= *)ӡêyv1qhoTRߵcb;-᜛Oo~Fu6sdas0%z}Ӂ:h4sHKIZ!et6 s]g7G\ 1!*_f+U{;t+vvӽՉ`;8FCm>ߺy- N4Z4I}\qip-6յȺ4֘A_ec?NsPW9 3 0Pߵ:@H^#˻h -> $rTS" FS"Y:PWzinPFR# s5 ޺Bacz&ߊRRي*NqP'?+܎Z>r9m=#^ٝs^ Fi݆jʠ/*flK]* n|8.** t%>-ڔWR[dG{@Ʒ9ЯA_@S޴Co0]ӏUfFea>5b{9YMOSV#a/9&l0(($:t#=cPX/,:dG&XFn:$诒4.Ѻ2;Qz\1';U[K$4Z5V~fttʾE!kD gy_*gƖ,J(\?{gr&iXG_'t?*e,Il5ELH/<'7bÁ C!jGKmJn~nyLB x?9Vi *pYGIjPav?^H[Mp;,,h HI!G:+&vE)cͯm3~"~!Lq˕gr7uԍl%ٿoݰUꮼaD" }l0H&C!W~TUtHš!y\p@䨛Łҍ& GO/^/I)hy!)ʒSuxvb'm]վduq mjbjݏa'(9k4(Nqwa]&lZ Մ 㟱ocK=!d.~SLy˼B x4b֔كXr&mkXlI}σ h,T\}t^nv7)ßE{6W\ڇ .y5*RO&V%bvTp 4+b wP&Ql}atc)"t;+/FgDU:Kk<Ri6"=,o+*vTc͚=vc@QGg[,& w`1+im T&حP[>h0&}9?Lyx M#v]ZFi&{NϜqo`⩌QNP'^a)V) {zU;pcui>f{iDjt%%S!{>y{CBb O9:J8>'^Һ]Z)T̝6ի!vʁ^23p~XV**>_ТB(s|G\m& Ɓ,Kq;A$&\B9 u<BǦVBʌ⌺-#"jO9qׯaiZ[MRi'ZRQg@Z3:v؆%-Q6z538GNzuHև3#Q#&>EQvֶ]0c.OVVs=tpա1 M4oxʃ_ B Iђmք+$/OM5NKWy!ao{ ED1}Of&λ_$In[4bHp@R삦j̑dJ17M Sn)`~fz #!|8"X3ɷO}΁(HmG&;Zw7OGp'J zݳ( x7w=4dl>T`?[/Ŋֿ 0PK ]L(LMw],~E2ɐ=9|sew Z˙>) sC7L)p2g7cvdd$!bFAJ:Wzl)bs&I*L`ynQ¿Ӱ ^]~c|RtssvBv\ZNjߪӜ=E"D~e2'l-|2%QFܧ2Ȗf/6<5xi(p4P:EUz2&x;Ax~?׆"V7HI;aZ0HUG (9 ^*LE WK!+)5^tO׿|G髡2w vD M(%֎pBC{wuҬv!|M!%ez!P߽ OpFN$H-REq߸ 2jQ䴌^B--+f"eԅF:k6L+vYeuoy揪{he_ә$yD6#17RVME<='S,xvbv&87K/X(UEW͹"fU't6ȢC\>-f7Us.}%X~OMG*q)Sԣ3tɷG4[8@O*sRvkTIV ӥ@f+&MCil='-b?FN~,=Ig5|)wjW=6 `ݵ 7qJ.o'h 8A׏Ȯ{9ut^@>fgfy_3&]Kơ[6\OѴ 'US"9ˈbK֥vwwA]CK/Y(2TV2k;ݯ"w~;BZEFOgp3M2jͷUKzD?^naOni9J]8}м69 h=[?AAH&c\N頋g-}yzэ8)& A[`QQ9>`7WZ};)f^wkr7cdɟoM 8ȇ!KL}|MIiigv_%auwпODq-%^Ի&L,\ߒӇ)-rNVCFZt_MyIK2Ǡ!V ]NvYlz[G|[OM{3srlȏJXƙhA,h64ͽ &B37ϼ|CXn&q5U(IrU9|_v>pyIaٮ7s@Zjnmrf  N_5H RN1Tˀ],ߪvn[fcD#*cѓ |uxppQ?3bv N *1{8{ i\YG̕.6Pk'{S5/YjC_Y@z6bŬ$Ξ^YnS.M%GtAcKؑ[LFtw֌G mR_.$[,fNl4{RyW޹xlla_.uFhsnje 8lCWq(ld?eD+lZ3z|p)=8!2>ςXm63<yI!% pbGZEoG0iCX6QF#D1]Q=> 4k H;uORK&RY HzG^QĒW C6Ϭxfݭ1 z~EH9n77"Ya.X=lIyqA)  4oGwt7Xh}j5y6g TyM2jO#fT3YDAHKhZL_?@%#gQ3fg1N0b;FOK uA֔x2PnQDC "CXZL$܊unT&k쯠{]UOsHNO"[$7)s Ƃ 11+)0"1[%>ʽAKv3, Ŋ. BIO-ĸug8+I*+ku /5PK/{mifU%5Yt-}%Y:iݾLRGÒx&(A'+@\8"g>8*iF4ljtct=`+wt^-*ݛ-r'\92aiGwѼZ0ZaEF˘_:\3ˇ_BŪ+Q7G 2$SB3ei @7̐(f`׏6xwyv*WDS5.K$9DݰÚ_3"}=lE\۞e$M-oC#7Ew.8#v#S"aNĬ .Ju[qoA A gd*-a{C)\9=jy$hvT|GK{4+Xu+[j0џ﮴$]idK`rJ6qpM/NS>vhU0 3J062.{ 6OvPV=e wU0@ \ϽD|^{ƈ3+kTRXR(DpeW¬c){(yg} kf5/)$|!AS\l` GΔl( \#GУaB媸,)" S|ڕ䰺O5Et;LQ4O 7kMCՂ;S]4:l[uViB@d3m}h@ /pkْoPixaſܴy[B5\ דҘ{({h1gQɬr I3 e;iQ`}1g BX& 'wNXRGq|0:j~v+p8q?TwQ9v2S&)d&ٹRIJ+/"m-/,z\$}kZw (F12uQ6Й0ekA {GA,oւ7;p:}\ėܑU)b.3˱'#5N f cUe8>~zQD4~UtݍY9&[̀As[Ug1fJw %o(Q 2j䞱AI,GE/5|}NTB OC".ʐX7biNO 骛7* bFoWG~ot;zJ:(2?_ qTG{%!fuH!B +AJx:%`2 ~{XFf|;(W,\b?> ۫w4E8n 7OrqE&aRYMrQwm ~̼ Fh,=R4a{L)zCzz5M$ x)Gl[XpUGR9ku1PӞ iAZOLes6`mz ΋r1*ծxe.dى{`mcxHka{DjڑF́~t?u0:C+Ts~q`d?s16ׁx_l,$tI7i˿q):\8SK;p?ROOeL*t YXm?{I x4۾luS2"2ӧz^1% vЯh%4<[:~`5OV5;wiQ/lp+ݶsCkxt (A"I6n}ݷ%㫿f|ctJ㒬:C̜pfO**ܻCSl!K*!'|;I+h3~hNX맂l#g1{k+_Rv(?p|C BR_dvqR$T'zpfO̗BpK͝<Sͳ%9Ë=$+z c)C[kSN5iؕdt)mC$ Ob3W,z!RXk>Ӊ3鉐 p`蹖4u5`}G/ӟ5|Q9h ] 8;X䷑Yhr| T>=!K|Y*T.{}p-jXwN[Q" e+# $B̢H&fWL3-PC&)3Bpn ejNJEf 65ϪںYԂUqluj)|ࣧʄwn~v}5eCYgkn]3Z\ycI#QuNӢ)j`tr;?z a(csk+ʑKĈ ޕ/(n 7Jq5wSɲVb0lXAC2Z 3U Wq&0&Hqy|M]#Te%>H07!f߶&6)Q[ H( }'gk޺1̤F_nia]WiP.. m ݿPb=fKk14Kd%R~61^q0+E;ݻVCT;D8.Un=-YJGA2&gK/6t.g*ț%Vm9aL ^{P>{3idhl> Kv ̖ĉ0iyVIRpѾ뚀¾ 4Ttr|f%Tڪf9.DV!s坜Hx%EDwk /0f'Z8bitEYY-6pw@pS\Ϡ t %fvBd؀SJA cy6L،yhmsDJş>1,^F|TEǠRuFA$tW`@iBqV+4pNvxh]{-4aM 64V]7X}i)+~Z?^R< 1T- {{L-JTHQ~ǟ2qnmP2Cw4ǣ2%tݦzMAR{{ GKY⟚V oqbL$b8VwH*ˉNFlB@y Ur0;Ϩ=O}xpZ^X,׌j|}ӿ3 `} Y6Uf9q{4ӃW7KGRe?dQc>EdI|O_˯mT=\5д ~q8:qGI(XgK {at7hQle{pIs9#i},\(ΈVh4>(c9iE`-ϱ0Y9f RVb X]̅oȁc5bn+v},QfEP3zSTwn<#)iq0MV`RTj12_EC'k&a>-(BY`~gx^1K!=v7y%=Bн֖avf[V0.;D,-f1G}d?kxel-S՘ jUX:IϹ[_nw &"_݋@*OŽ˼?0Rjr~ Phne6ޫ{ u:Eo_={p|V5r"? y% L˭;tHXtGYӾ8{gkF%PibN 6F+OU*2NpRe55<ӰATe>2sD{^?Cb3m~PUY%dU/|CP^g:˛ Mgw\%}%#?S+nf89ucRp8e:ίdo%x,Y1i|mċםKTOs}{W&^c&dpSW w YǤ@!Ǽ/FhZv5mJ:GO]la3!JaOa=z/'Jh'y4!r(\iPRq& X0^HZn |L]x[L/7"|V/0%Jy0s.RY8&!yS '"ǧ lL090|YZeZ7(}q$%8Fϐd}ǃ%:_eryf'/e8=ͯL8 :@J(UUݟT~ +6z]f4i ۽n`w*mwY63)`^ۇB54>7VpS^\xXK#_va=ypȑcg5Ÿ bc,qX#v䃊Y;֮ BT X@&/+b>4FB.suxR)syqVtVnǼK]9* G<(rBOB8s  X8I~,2hrZZ_XO&wR!&)oPC鮑l._6p!+VVߕq]K[u1j[5 5 ~Xч$'yBqMQ̏\3슜5P\a?Sh,;U&3ſkGʣ`9B+5ZBrfWϣ8s0gc*u%9^Qrmyp[ UxGEϺ5t=+A$NuulܽNJHZϿ8XWֹk* x%.+ 3-[nq&:֥X}Mh5 ~Q htU co/s=:6h"k:R_ M\kNЅ?Kw0Aļ$ Cl|-pְ.*+Cr߿-.LܪO$aGFKl*m.zxb $ ʵ ~[tʩXYim_jb#Z#[z(.A}I0ʨ'rZ\iw:԰iL~qzsEO%{Zp(˹ӿntC TT3Q" NUdk᪞p%$iLjbЛ8kvLw/oN$y/*I 8;w(tuX8ђJJX=qzhH#BIꪊ]v1NhL' _=_̔d$!igdͷ^d8lqYI Z$Mbb=aOj4ܷ2 d'UgkXsnf`/֥OˁH=ݜ@z?vSay IsI9d u=iaP(\ɔ4[PYpާdߢrM9x6N}(zGb<@ZVY™BQ21Ne*dgLאDx @9F|T4?2XcB;Ōh]肚w.E)"]( -n[eDE.t ?"J@F)P" R@d!$]XG5r KZwH9\h4hsxꑰq.]1oR<o 3S3-,<)fp6lWsxQ!}.$ "aRR9HK`k\3inn:)Os4(ܹ Nb˱'34Ew%꺅j ZT1xW wi2qoAj& Se,y*W >5eg*"#_q7`5śls\;?OAp9CSPs)%^Fi GT# ,mп]^={4<Ƅ?ߜpsqUOIvԏ,FĘ^1Բ,1 _c Ty }H#HԠDVsΎ+= uCO{5nPY-AgYxpƴ-YV3]קYLj$|}pAԅe@v1ʅ9GK }CoE`km͐*r)6F.dJx*%aoHtMdzT>Ty:1DDM>o:ZxՇѥ>*Zk:LٹZ߱i@aҊ^½ڵKbNjZԧZ/;hM@ک ݻl>̹%ʱ[ʹ,}E>W]'mJ2%98ws>VԕLMPl0O+ ޙؠwX\gN\O6$Qe?Nc!{ 5Ls0;c wϛ79M4 o)?mB o/85CTj!qQdw8//gAWE%%׌TC2Fx8[[×î+iu+iҤŬo2 a~{5\*d($'1t~-D:B [IA8M(:ݪy )t |ը؁ʆ0.#&V'[maJwfKF rټ;) N2G [_Po_nH ꛫ@:!nO/fK i!uykH R)rsE 43R#$#z@Ac=2Y]J2 |5v+ OiratiEhYHA`*'yCvzI m͌s8<UY*tA^aC-5X%CM~\%[Tiw8L{U Szhx.,"߿±ZPS ɄO(w<`F|L, ppOjPWi]UթԳ@ɡh;F練泴٘S0BrS{ "&[ZFXrQ??!騧a7Zpnk֠8z##sl3rR.ӯpUk%|R}$3gSM2 Yc +g!.M[ R0f 1͋ "u&f< cԆ^Цe{0"A^َz MSi*Z1[a 36ZǹfS%[cVANiC&KQ/jt)C-H~!,lM{ 9z&Tƪ2^qc l;uQ̘-ojrGБϰ^6&?!ƃw]M?͔Bޢ)`JqPёo{>"Up#QrLQ_aߌyTY񺸶/o>޺¿ڂRcb]<eS eՎ83| -IEˌ@e.Usm:)TfڐꎯTN3$<?$))lJjCF/OX3PXB# |:@(2\]chn[p'!5[r{b.g.@^qd\&nFboS2.\^˃RSV'IxFna6Z#"e'ASKTvTJuY ϜNsg!`=?o }XT.pBoէuԀz_pϡrS74_IFE~ƹr]}'v2G1˦xSO[{_RSn@Ub&hEu[M'RFZR|O\@]GK" l*#&D>^͏ L858XnvGg X8EXeiֈVܝ\_Ax[:eX meIPcO(fȐ祤S\#;~C| u!j]l |q6;U \'>d3P.;?NԢD3}NVZYtT?:/kP٥v\YTCį^25/ 7'[oup?SG݄SYEMآavMkZm:"K@Y|7l>=Y;~`ZThJH`#z]/t+.N$]^VؙS`u[3'טQ2/3r\fգ ]4!ct{ :<`LQg{޻Kn^ Xxʘ`SY[ds lF b6(C X2Sj#xlڴ1U}Af:F'?ozy!ONd s?3s Q:b=و?gBykR܌eFHKxnnu.eb|>R!6;P4KPڧYm'$<ԧ v&4Іs;>(%)z5{S (pO\6oA v zT3Tܥ`Rqݪ=8A2]@[aeC]`y,هJ~ROB呓y"`&ٗǥ୺s&[hIU]gAޠa@?._)~6uD F3Kb 9bz !hΌ(CSu,wgQE2k/fktυv!^_ U߾ʫJq8iDLJA ^3EԓZ̦N4&oFS}0I)*dWšjBo ܎hUJAV]=ʢ'B.`gf@#LbFe:P ɻZ=ŸM[ D{M"F9";O lѢD2bԌPѩ SzQ!J1jpV83W2"3BH~%`f:] I`̼j͕h1h3m9UWx%ʵ8ՔDrL1qj{94)l0UqP/oĈhgi[T!GX ӊwg;Y.MNNI dMLY_Śz_-{HV}mwN`&5);?"mje>~ /F$9z!BMb"B)&yZVGeRL#Hv3N~@ʃ?^?Ƕ]0D]rGI*\U{R;%nЩWҸ%1"|>aTve<Ȟ.~DvK:.U])ͼB!-&ȫ\zS'NjG]͉mt䚛}_`F$Z|,Ӕ}{SKT){*JHdj3N{ W5}I49_+OTd?E."ҏ2/,UftȜE z>k zc>㏎ ;ڗzϰf)B \FDdC M5oc0w.qG.X :yy{3lſ޳q_)}ĕ^C|X3-j C-PҲ^}]uG4gt7"b71Q\>}iQuCrKx[rC=<0%s5pvP<`8Ũ(Т/L[#@0skRo +K59<}G2*Ol)Z5яzɈO?\m! y{:G|o6h &6ի:|+Z~ FC0_DC2y]|gk:fI6`# ?/|M#BP#?V^ӈ?YW]ؼ7WޜX* Da~h0]`P:Q@^3h2+dЀǍ y%24I^R|KU9O-~|ٷӂGfrAMdB۾_7G~D^΄,$2)=:N\ OԪj,A.\dcJ-1U2 &YwB~XhdRu8\qpTg~ ($e &6D,2-tGS'5K!zd\%9hZᰄ$cږ.3gK8-xuAXa]]S1Gc2d\Kt€3%97zMJ>c!7s?DLZGpnhY>CB_"?p@-r6G'#3t)<=}b$ ͡b5kqkЂ^SYV &{EFKd;Mή0d<)ZFFB-}NNX3^t)9M[kdsQ ̅);>>Xː9t@*y;r+/l [ ܶN S J ?PrRE4=,лx*p/Rz m3/f:"5/|@R e-<0UT֪wLTmkMu2Yw}s,ɧi5@ʬ{R(y7Ҁ/O ".'Άvү #rV$ ETt^*<`M=pVI+&Dz[ψuH5>ꂕ(Xua}=cbM!OΚaQ =)DNK8 ѼH|\"TR_$Ł";q?̓Pݢ7fKr>iR`v_m 7HZ6K`!UJ>T<6L1 ? ᯩ)P6d@C޽'Z p8j}itE$6 X`ضs|6̦_st]2 zF0ċш补(+6mR'ž sogDP*UYIl/$l٩>iK1Y}:ߴL#@t_zBm_cmt~}HvZ`\j# ǭ?CMRj$&m-ע clrb,LR;Q9ZFPڴ8)hJ"(3̬mM4k,":22f*fz΍-7ތuU`~!"L ? dy`3X@hHje/[sK? 3e.Q07c-T~r4TWeUEj)QpJ%5y>VTa &M|~aM^%&\g%F F^%(#F7e X!}E0們 ¥iT7g>GiBs\nߤJ#= xZY$ϋ?Sx[ c44oJ/~,8kB3r K+h$dNxbp[CzDm؁ڭ:sX&w`7V^h?&;Vnn&d9[pھF?} AQO5𩓰ir / zha]'OMSMY`A甯f;ͫO+z0\g>*IRMdeS/#}M[n4aȲqJQ xi,7!KCgfEVr+| d&a@ADYϨ~$ͫN miw(ɳcC}7|`;b,/&?P圠3;E 0*zGm{OsX}pp:6AWY'9 LJqN0ØRᚣtE9e .7/} ,K!/c\Ǩ0Tb(Rzy,51z2=M穣iVH-s%Xf\1{*oo_Kw| 뫉m ?k}>}bJ"Nz-!j/HUȳ'T^,"Ի_Wywv8`5LPKdMgv@ aO[+`4]4|PϾl,2ɡ[գz}|q McuOh*w;yN`vHBȦ ,?4`SBI/렬K/ܨw+o9o8ɺ2ta.)"=zrqś{\[@򲧜4=~O˨yFQ>YcY3:ugIu3sK[+Q峐%s>*u"+ˬ/Wt׉2O]61BMt>TPBح6<_psR܁L1 s{8At~Z#43tAW{/՜<~?.ڧ&=uz .L:mg%TI`G:E&G}ut\#dU QwHtosIB {9jOg/injtYS2.> ,:xݮzhRrcq5^I RTUK܌GqO:c-zjMEtsm2C-:mi%&UK0e-jcۗ훝A" WYQ*ϴfU 9 aCwÒ Vu}%XQWʦ]訶# #QRRf+z`f@IӜ#TzrFM* I~_Gml|-tpȈ/J;1R;[D\2_Rk>_h\wfC9b`$|^լO<*Ґig'""꜠9o_Pywu@s)5iAQ_0i~V y7ϊƾ {3qqY$6 VL,'vJsO% .@"iuN!a$bݯ.8 põ|"޳E~o/L]g`H7 Z 1su;ao]'g öt93*]Ag+\^<!'z妣h%6K}ye"$f Eg@ɁR开CKd Ņs1'CY8ݕ+FJa\sϷ$srLVZn# -}dAa>Z{e1<%3Q*Py'#>NڄBhRF(5⭽ЧmN}0 KW*!w7P;U)VMٱO^/ 8p1xBt%1ߋMDuM۪&k N|c{Z92zZҨ1de e$Nv "h^R}io7՞D0W7"VNWCy }6;ٌƣ 9٨Bɫn~!GFZjaEs0 y7(ޚy&TǨГYڟ2XGkL~`knqZ+ pU5ﭜ17??"e[o73B !56ڵ/` jupp{Tcł$%n T*a۞f^[oVu'N;⦮#(2&*q`8ݮmbRYB$ۻZqzV?#hHNL nn>̻/y@zuCœB,nFFbJIŷ/&wS=v."KDGQd3!GN4RWq; "w RH pbڐamB[ĐL-BnU c"yiҴT[p#2;qv?ǻAx5YIJ7ZO:[Z{jT O|U0#Cβ)lwLaT| 8eñS-~S=KuA{جR̎˿hY siCC)Eom +> (d[Dr {K;(7[] v#O'_n{w3~,F Vr ;_Ra)uHAzDh.:U|( Fˏ&/FMC nMYJ>]*X0YaUq׺yHSs7^z| îo:GMG)3\2)?. 9ܴlziw]# zё}+ #qb,!_ wAS&gLL\{ڳHk I); 9#8ks>/{>lc"m%::Op-F~wY2TVy TY`[>rpuc@niO O݄9`)84'5>cg-c8ࣝ;*Qϸm}?}ᜋ*?)e'Q?!W4pbsl{8Ҝu)S?$0k&lDBtg*tQ-T2x:@?e3HXyLo6y'vjRuaGP=Ӭ}(=mPMfv7v&Ԓ[-^v|M6ӇHR\6,nٮQ,' Gʱv2ujjGFGE;/)I5M'*@˨m0kO{'uԘQLhB7a J%_l9Y u#N+ӊk1bb wu7dO~i|AM lG=l;&)8['rW*5B:`pAj2 <4 ( 1(2G$!Ft]Ӣ"ɀ\e--Q.}OQFO"3Vh s؍j_w*ygq"Nnϳ&y0qZD oU9$)Y#5ki fƎsG/}'í,o?jxT*A -nRii |Tlw6hL*֦+T1q6yIp:"Rcq˂nlf~>{u%T6֤*+]h|_gNDY[) tfv(bޖI!7Bn KywaǑ>X_۳kmË'thH_Бxr#R*b]hv;zfe,`C CўTCM>~*RS%:ΊCM* FMˋDv*WùyɃ|HZYg% Gubˣn.M a4Le|.g4NiD_&R$h{A bÏ`U>~㓘_/ =mzd9\yoWi$3d&M )u5ѿۗd9~cYSá-(u\rYaqpn}675*e4N70h Aai ^+fr5u);-hQ q 6L ܲx"կusNwؼwP@˪>7zڂ0P͔ݱs- oZZ {#G`28 P8qJ7S=i6P:CC?amG9x sgWϋ勪YpDT$c/Ƽ{U'x=Vch4t_ Xx?]-RlݤS]0p&uvޑ!ȑ9 TQ"e1g8NmpM3缲씧zk!<5[)|㙰-☧-+<`ܗVw \;\n/, %p~mwV~ ّBYf`d^ӬѺ?ˣL:::"-NvƓLkMgchM]`UZ4"b AaslAo{QN,d?0udptĭ\pX@ +sNU07zP͎'_"}7G]+JQ*z,Ipx_IAHLt`˞Hu ,gzCF#(q|@L\&:~keH^SŹc4F'O?2J3\KsӲ"Ƕ9G)uJQaf /R%Vv,CD WA"vٔPQ16E@B@*ec^JȐ҇*Uf߆M@Sۋ,J0~"nAr8cΙ$:#UDڋ!ߋ:w6XK4b;8h$BHL~ `k;xjceL'XBUMj5%#s4pE5K42US=4]#G2o~/"TD=4}S܊ eiهm@Has)E&0Hk6^;5`"8zBj zKؗX y&ñ y:9ckI}|3PXBYbF%_0X8FۚO}OpZ.䡦0rb3^orRvoE$?'>g{١(_L"-Ch`҄#&R p?<͒0ON@ =TZ R5VCa{;fWW@)"<*>]Q8,K2vH~~A?.q؍?d!)y6tW#zFbE.(c&гnBgIWGՖN!*#{RӝofL&è\7Nч$阍8pC>Ct71G2뛽 ~)6^U>| M +uvf!WIAvyI=Rr36*[iWy!ҹ% 6myh::t A]VsfV rH?_H҈W>F,VvUc<˚O7Z0Ju÷ٌ &I~z|&EqQ O5}F/c *XnpOu d&vYsK_WZ*i F2kHjsBSp% +Bw*x*fmY?|\=ߗؓrPհ6ܹY|wBt}bu Ic}ro1d8BkSxP=yB8nz.].Ưx*Lu^N<&jFuѕ8ZӄĢ!r-蒳WM&4樄!q𿉴b~<Y 'x0h<Wts(TMA jv}DT]rŃkOxn%ZȘ ,H4VrY!uʼn{Ib9_ԢY[j߽ڝ! _GGq,O%\?jNY\T"q9"ʣOLs5:࠳u+LA I5I/ 㝇pU WNY3EW[߭ f@S;)TT-vV|*zQU=cEPqce45ok(gΥm`L5 BP/miHzMv<5yyT~oV,0+_0eyk4IBWjVTYY>)zi?Cɮz1|dwӶx2D7ǞWKI3 oЖ*$1%|JeP {r)$@.{d{C(`__~ ًOG-QI gfDc CL\Lh߭p,Iy% tu9) ?8;k|I쯸,E  a)n&Q`K7Ewn,WшIVȧKmO,>/ ڋ׻"%H 60 OOHx MflyxV4490bY {m,b BO~l*J޾N}C/7Kc'O.&ѽ͸ο U!)¸kO[!%c>pzX;j+N"Qm%~aIż&ǻ{X/!޷ښTF}^W|s>FGrP9NoebltF%Dѯa9>+Mp@8TDO[H*[pFV锼ކhXNĥ2휅Ѡ=dڭ<FiPՊItbT9m n[`sVOr% RZ9ۓ#l'>(=B\؋]L \2m5 |-!Jm?%vu-edcõrW>X?bxDiLB{Nh\Lz'rIPƀY ͊x%d8=(#\X.фFRCl {\{}"j0p0{2?vܣg W\&<8@hJ)dAN]`4CUG.\RaC J`T3~s"h"B4 yp~Aܔ1BonH#>f\̶訽F3DuUӳ¤X>N› k;9kq+t QW̟&d6.A0vիE[SVَh^𭨅LD3S.(UAqB>OM jE!ucUA= I^ F* `[`:g*4GmXMYF ҬXO[ k@!I=QA`Ӷn|A.4ˆ ulmO j ;Wߥ!'O87jKCRhY_1{ j\/Pڣ,cHmҵf)h-4V4/Iq$YVތJ7C s_{igQ8X|.}oXn OINtQ#mE=2qoX 8qG m>t@&TL֡jlQ}؟!:j,EK?9PWH%2g=O%sFK=hPuWM[U<`{#S%cDiBk;a.<_;̒C%z)-sCmrkdh:t?PsvY 2{  ^.ƞ |IWuyϫ[vn``P<R׼Q#fFgH9n/.}S,ReI&!lN1zvVreՏI2YP)W^jRp$leZ&} ;@E2ßL)_&١tl%ܝN~aҾ:?l&gfIf>VSdy,ٱh9#"pUR,öTN[WV99T=n'Hzb(+UKxUkb)kψHCFcAA\U|If*V&WIB S-3 68耒N Sjǂv)c&ix߳SmuZkq' ghU|Ef\2s+'sM2zy_UܱܶkMI:"&Xp~XUb!y1BCw&IxiBL;m$LiH-<Îw r\NuI>PMd.>F̈nlbp ^KuAQO$7& YXn']ڐ pe~ݼ]+58ܟӘQ쥥E㸸V1JlLΧoteѫO+ξ L,Oo Mpc$'X_#=ݦطȬg }\DV K[8BBXH[ @iWiɢ${x DggsdXV{5|DN~iCiSr$'ͷ4ڀ7iWb\r3ͪUB}$-9}eUlh%9ϰh&w'|_6@~{ԍ2 2M|@bҬ]6hc`^}NzR)Էl%=>]~ͼMw`gIl&vF{x3)'<ߕ.$&R6mձjXq kWq U$ kPGԬ ¸#\GT" .Qivc6 o6LjgPmY,,vGN6dhs!<jh Ld}_ TB%?x՞ x&@U;G# rtORV+o~e!Ċ+:ݵD'-EQ9- o@7_n=QJ@{Vfj_SM%&V>e g>tOj]'{%rw)Kz6^H~.UX| tnr<)>i05-k\b)&'. U7^PJphXBG[Y(aԺ#~}!;P?SW2#so{"~P?6A^UJAL}W0CukuwV`A9อ{_bŋLSgr 9Geݗ[@X;@ݻb~Q[BQZI4OBݒP: ?䏶YEWqOj7-&\*`ޘhU7-{@u0/Ja*a4dhb?ԬJJү SB&Uݍ(t=:CǮ|6rQqgRi˦`X H07˖bof# JU2򟍄h߃8Lz@B z܊/w:!BH 1rs+ ToĠ@\ b ވ Aa$NARژx|Dd7\Մš~։M 5/_oqi /XF ō=knWzUn{C8iX!IV -$j=KOTӽ&9ld#v 68 'LF6^%)c gv`pcc-!;A彰 'GT0k }Ay U%$t9_0rl)8gA ˥ RWML~ZvڶT!_I!MLe0򋷅HRٌ0XvqP"KY#=Mh"Vߌ?[|F-FN$$:?2[A.4"J#sj_2) Ex9!. @WyE,!6Yc?(*az dZ@Dl5^ k XyN3i Ќs7Pˆ >A!冞S(6;|8afĈz~{JkGo: tQp;viC37ny] R( enTXA;Wem/=wn!6O5ǻ'L"rCƋ3hmHdUh2 $W7tIMسw(+̭O?|Uˆqo] P6mE;VDcXSUB#:Ĝ!i & 6kZYelT#I4Ui 8}'& xB{lDP ڶw b6n]gv r #عԯ K H8W)Z٧6qͤ>| /񀿤V*|u::t pD߻M@P|pi  `\A̸W~|kbP'K`P!{ apX{ia 8Q-@J$z~GO Ub݄Tl߿} G|,޵wg\0`5"c]Fky0!*f禳Cf Ғ$.f㘌 rq5*19MX(K5)t¤l#8R'SJ?qk0ݙV ob*"jդhP C4Х0JB"=+wSl?kMwKgz1E'O^e'9o(]A{y1YgW(Nd)g?UuZ0\ۛT? UyU=^ƭoUhg9*7(ZG(uHN]WsdsajĜcLj @g(˅Z&4Ռu_Q*;S㇝6@v1F x+N0fq>iZDXbh4)>PqgAVҲ``=F'j*U`j] HbS=˿ `m 9x## /_3VhzJa>OWGnՂ;UsS#,{<6䨃!DbO%iԾ:~l@֑hы hkQ}'U fNW}[Z*Z&{ˢkSUArN>rsNխ 51wk[zT>i!g9IϢ0lu;f#\:{+nۤ5հ5[ާ5MQ$&xzJkpiB1"6PXD5m =h+eN']KcjJE'c$ZtNۢ;8ߴr k헚*$ lIC`>`:.O:mAbB`HPԐNLmaߔ( `0poy .A~>Tr$$c yg i#^4Y_y]8F:x}Ȗ"/ '?F/Aa[&6%eeJmhaH=²%1 _.Q."'87Ng4|؂z6mdW?0y4L^uXYW^ꃿ 7]UB"79hUiĖ(yqOz &XǖqZ w3cN&&g(U'D>pN&;}^VW H8,1%';@Iܶ]3-I?m6^ۗLAQ8H ּU D,AօU{r~ q$^B#`|WA5Oo nŎ\L^6-U5q2Yϫ%ѶBM2|qwpԜ^zyfJz"@: -!a up3YU?d#Oݣ lɄnN<)\5L`n<&jM,5@(Zd*p-b~6죀U79z5tbЂ>NvFW. q۴~u`'Qy*㒈,M>FTtw>m1"ѝ.D`GrбBFx#&yb3wlhߋJ5,eWc~Mұh.*B+Vqh^gnD|" <1Ԣ.ǢINйD,7M1pS,1C.ˠ(vnj!hpȝҒeA^׬ĀmxC?S 3 P]\^G) 3/?H!´q@^~Fs :M_jyӀ[_Yd" !_PM~B.(ASt cA"TGeS(N E81p?&zC۟_ۋEU iR4i6r0ģ RJY>=K/ mPJm*[?רu Z0gcd_1fen~o'ʃm{C6ӶqM872/Mk =5:/cώ md`dKW0y9sPU^z潘Cz"ݟ hʿ h;ob'̉$:H$Z.2'9$6R2|+82=|&'ɰ.\#GMnix6cBAe;,eRupLfڊH]JЈ9KR?Pa44kV2Pmca*Ac^xζ];YuGGΐ.RT X t9!4=S@諉Ν iJ Bڡr'Vz[%gVX.al#x䄕\ɇI`_ F\vHH]heФ:-<[OȬ[Y;=iZǧ+=˵%K#˕q| J.Kދ}〘ACBB\e[GlJۓ]RZr7tBI,"*ZSy=ޠ.'B>tϰ``i.)+Vtƫ:Q 8jW.I82L\hdAMr6 [UrwZDc3 MDM *CJNnn^&Y@6=|Ȉ\Z!EBΰ!A[w|܅D 떛Bji'$g_gK|j&U% G=XϘC3ī8+]#ս-Jz?CPRO-SM؏IPf>k+ĭCL3%͠f7]]-{ȗElQj89g -<ٹϚ-Ql,i>kNi_1ЩWޮ+zFy6[ Be'1&F3C {ɠ,Lo[,\V]'oq-q ,ļ;']A=n8gf&z%cIUv{Q#oslept F<:kwT,#3l{sQib'3.̮%C:?ƒJyq$$_ϟWw>5GAAffϩ Z?l\gE$襢8Ba6ܝnYB#SJ3ujZ̭#_ac9ܗ ˌlf3c7j?ZbbSs\RB>ym/v#|ļlߔb^w)\:FN*?%ѡQRitS$VIȸ!R0ZyJZMɐ3Kth+.i#> VmȀR-p׃0e(X4#  '_ O ›3Ӧa刹.bxNj)ZVdڎl[@. Ham`Oߗøw4X9u^_ћ0o6zĩ ޜkdf0Ϝyl-kLhQ35,y5_L Qt,qb{oʢ6e^Qˑ]1ZZD&, ,Տ!? K_9Tl6<*%*Gw,aE'f Δ1 gViXrzE^ٛ,_QyΈ|" ^E$xFسez0)ӴXi f3qU8vRh;3 grb^>D [W`^3{5O61&] )sp#n[{"~.0fSr|*MQ BlZWǤ$eכd7ա}iAuĹQ]2d:zq*k\UpLwp̾-.J$`=>اY̅uN5co9XAH2;@#Y0PY3!I?ckEo_cbmPI*He˔ ?ٕ /E@ۆ#(-$Gn|h]MW#ԋ>x.X͂'ÜňSJJH/Xqw^e |E}kLgSvE19go9M`2™ӰGV#vr ,*Λӹ^ >}E[Fb׎\V~Oك\6_a0Z$Çܸ/H1.G1N}eh+BJDW&GY4CqR% d)̏F̪XYww= f}NxS܇#ϙ>"F39[[*|d1@P3NcVFhР,"֞u9%PZڧ"@_uv>N͈:RPHaV/(wWx@3/MCwnYf&h3PJLڋ"+ 4PKy@؉jvsx;!濘n5<[{ 7E'_P.ڵ_Q+hՏAKKHa"fDѝp@mp(ɣ{He"H,,~cy 8ȆI0<ߺI5cDiQrd'3zkSIrGc% )}ZGW7i /=vĺ0c"ꕽρt0)2`k6sA%8, \1'}RDJM)yF-/햘ieYPn0 bΌ>YS `8*=a{nx8sxl$/Z{2pڱ^7;yQ GQrZ,UuV $8ѢErȃ|/So42 MA]bD]A9RY(S1M#.=ڪk\@cv{'YAmۤWBV-^tW|4Jv2Z?9ӣ *jUS]~A=*}ր22꛼3=7K!*N,;Bp?APduAМ'N5+}s?x[0pc%b Dbz/m8: n4? ;A)L ;=@R 0J`3qf fk_#$J=uiZ\%}[x`ןb΃R&Z +ɻp4T!?T^U@RyqA@Hl:*cm-^4k KRmc`&ΕcMXhF !(J 3>R}3P8 L$͜QZM漻F*5\eDWmol hg&9fZ60´Wl\sZL|o2ay9(Xeí|MIpxf$.Ƙvy%)e<=M+b3Vf,E_Lxp n4ԥc;Z,h%\V g`tĈ#缈#K¹YR?9 SqnV51 $1lҕ{^Kבּ+ ,ƚ08HȢkc Y0c#ݝgrܥ;[*Z1=uMn؏V(4PY\͋|ّ?NB?_"1=((rLjxWrČ3?S[,&NR4~*hY5f>9,[^mO7c)[瞖b2g$o)NS_5݊-\8{#RCSG`8RPN+vazښ(H5E_A$qPqht&tQY^~| Z#Zg<RpT*0Ǡ5 ti-zFr'aRM|h{%t-v+;BhVV-\h"OZ(fqNXUt-H$ۺxS93uk:Qy[ J\xIڒ{) + }N$Xps @VYeq€>ZC Nb6#~GEeSpzCį9EelW6f/D[=ٻA 3rP*3'Ujӈs1뼫rRCE)8m,v`X\W jp➸o/GPҟ)aPH&ݗX%d&d~/}@b:7$'$巩?XqafA$gl~ÚQ~&U 8 }n},._NkɌx/(B4\y-;pU::0_cbUvIm l,eCڮ> 30=GkrmB9qsZr °dˮ:iH]g Z}dJU٩˝Ȑk"m }fZ:mɎ >^Rftq;&x0F{ZL_YHxqZY]ce{c+R =g_4%v*Re2n9ӡ;Pup:5\/o$ [\o_խ/26쨈~|Jcl4ho3Jj7L<źFWء @Pva+*fjʣy5ǜؠ\Qje9>sE|=Qr[ϘJ*:Fmcڞ,D/h4t:>w?w_-;7.LpBCՌ W&ܤS?I8 nO>[ K! |5+iVFrHx"')-ta[G[53!Pٻe@xDk6'D%5'rvƙ\v7\Gǁ ^ ^؁qG'h}s%Q Wͩ)IzM^bdCsIח0٣|Բ7H1hXixG\ОJ|g:m;,lL# +d$hzFL^_GTnN Xȕx ^NP *Z8"VeV?~5n>D]kZ |6q,<S t@I˖YlOsU|#_ә-T.qL]"yl4)Y =c(y[Ò.WV>-i+pUꔐxR SHΠ/:*zm3(~tr <~zTaJR# CAB,cE -,ihlgKi:'yrgd_t˱)bQ~s΅V*?b@'|mxqutd˸.I -38wK"B[8T *{YکpPY }bpMbu1C ˭#7s%oHCd")n*P[ElyMo{q9dHՏՀENjen":i#8 <tNA8MH+Tx5I@ʁau/v[ G hWKuPXj+A)`Oj.'QRNϼĵR*^ֶ0[Y0~¼VwΊ9, ,t/$v RNsk/ n׌. RE 'Q%V\+aUJ~ӲLb!!J1bV0+ $xKѢإ̡. T:AA8GآKk?VZtJU)1>52w^ʘYO Zې"VzݵV!k2XJ=Bj:!.WNbL=f&01AkӚuA7T }c`x^ 1y` zmf)= [ Etp bOx˅9hq{ѬTnĆ%T(Us=֟#¿Uvnwqk 842Mx:qOyWѣ|V <~E,dȤאV"̶AQ?H $0i!gM0C,ڴ,?UY>TW.őOM"' i(Uĺ|@+ Gyz~}RY@ B } rD+}dPs>-Y$.0'V] W>FRa)rB(~XޟLYn5i*JYdP#qC[Վ5ƥ^n9 LÕb6mS&ˌpkmCPnDwawdcdc&eS :Z6/ۢ$8ފR9v`fyߤ6ƬMJ\-gbHd[u-ԏfw6+eUgPG_7 j;}wʿ괿uݜ oC'Q ){qK 1 WT-q)4\}eD$A n:^zT<Ϗg1 5O1X5ՇCꌉdSR.H"Y'F1X󾺹]_J.  x\@>֑JJAi`?{+sԒ7Cf94I BM&Wo"Mpj $K yO <%ӱG;h(| ցLs4)'u'؜/6CN jyYncADur:wZU$ߝJ,8c2Ǡai{Z;bǫr%xh_̽+_lMk 2=7j 6$gqxi { ߷=bؠe7w008n l .۳X?cJ.Da+$ 3?@9-:ǧ`i21J29 eXTeL`M$ 3sӗfL6bl9K#A==|9;Weoj7Ժq:5jn:p,Jx rM]3c;韎yr,(k`@.)2cYe#jlRnJ¡Wrh@*ߡhE֎p&.Q$c_hpwdM?'&BN#ñPmX@ M[}S gX@,gGrI G[Vg4qt"'O.7#xea )J!g(Ս&iR/cHFk>uL_XfK[~']nu`Jޛ2M'|e7 ]1̟Ur 斵&P{0QnxG"BH=+YjCf$jNLeqե@"Fh6\^s{~Z(u%H^( !*c^bO7/4q>_R)iNJ4^1my>M*#gq/`@GAI8yUX6.dg耳tsAOm!NEɗGuЙfE: 0,PS8%-_+ W\\e)Md8JLF 1o!/].Vύhtjv?d\Rx KȐdxJ6siҤMy`9%7OuhѠǡt0yv۾`sT|K(mkpl2i 7K4R;%LrT|k,:E ;3BW^fvfclM49Z,J}ye ͚oyVhj%%:4 s\޽KCkRBei)UgݦH3`req kk`lt #دA]R"Vwz,NlYl]yH¯;Gۚ\8/ J\Mtu݈Pe `6e55_n.s*0M?psED_C&f3I5%t][,Tl}h@{NB"B0wėO>[Okڀ3v3@qO 3Vm8߁`h 1ݠNWZYۼϣՎS"T0ȹb F')v 9l-&}\|U;da,tqjsU.iNkqVqs[hyMIN:+W^"4ٜ#&(yk],aCXԫݗbf^vB1]YųݛsTa5`Nc.צH&! avWwWI\J׾ifM$W1bŽ$r p&o]Q u|qLm\ilkgm`CW &KR%%*mARՂ#CҩIʦUW =A7&" :V~&?}G@Žtյ޼ szM(<51mxyzt^'8޸T7mCp*1wDka'Da KYoʈq^)Բ jV=S7b.k6E[0Du)noM?)f rC$"9\ jȈLwfw zD&- W_8\ŹTz_, ^jlv ֲd0>c w@$)Y1$k{Z(Lj MD?kb -Y{eXMq'*X:PqU-͛*>=*w@}!Ow>4fO:_l刼$A2ٌ W6߿)T]0fS^ˎ擶Mp ֨^gF,B{iUŽIc~O"؃E;EL}i{1V 4ܠ`?Kxۂ/4v`K對}SV<ݳse.^EBܦ,, vY+OBfҤN?SD#mv/p V %>(@{0B]ik\^='gP̽ ͍wMѺqT 1mX{-D[S`Tbv`fDÎƇËO q\D+{{7|CS}bynʓ(r.ܑEZhH</R:gJ_W&+NoyȈsy睸 ;M8Y@l]Q= R)|h]yBPuyqo.:dwQGm܆H5ŒHi=H6 ήp %m P fL!irӡ>@Uq#:'!}DoіSl r_r`KiwӅ~h`hb[X~Ò}dĥ^mpp{̚#vC<k_ٰӊ:8r.9D-.Hdqn6w GL(\(L^~&o:aI\o΅ϰJ[4O 9{S%G?;S8jSM2+0cƾ,*2M@w.gktrWRr=c$8j[5:㌼(CxbfdI] (<o[fZ|^0mkUԭԫ6ݴF_SjЕdy"D@4|_xֹGKO .렯@ hT.=729!W)izUa:n 9zTg#lM6Ռ 5BbUt˷]҃d\E8_=6k4{meWN>'o{&NCU5DZ ^WY$ Q w׭3J>ho F!v@s.E JLUFUȢ2<Ճu,#IwLG/ >Jk.ɟ(iM<{d?KE&~8Ƚm@cn@2A-)~@ 5ۆޙ`ڲv+NDVrv! gDڪG4Xs_;!)̪A ɆOJ `C8E[yI4LhٔقK2r 3!m0еEpsv++ eEfW_! 7΂frU--#Kc`^&dE=rs3q^e)jأ4>}ym7M@u@6JRw(R^hZ[-JeN?8\E> XOia&$_sz~lMAmtmΫWI.}/U1abwy8xGGw>^o u .Yl7)?Jߜ П*ʾjIë+5S OT @hlahQL*SHlzIQD %d>½$d?^IbީN"LWhۖh;͟=.E@uށ nwLNXkqz*ʇw[PȓjX^$;ˈ0URal{a~]}R㥛 }Ŵhx:VAwzAn8K3]M!"SK e/kMTP&(9֭sg[~'(h?Vm[*&n:Zw\Z|CϮ+udK}0>-{SAG$kYd瘍+!&2Ul)典8N-|T5 DESo@p"A;J zt1ɂX[4Tygz_WIy@so;WԞE %*w{M)7nNz :lJ>A8 qלﭸ Atez~Hun@Ur0!=ʑʏVJ"дWz{[H"O5!54Wa[9k5u7`Rd{)m}3{,O7`?0zwe,~ 27Iz馈9bF\yҵij-cC uƫc~޽u #J.'38:0g`q,۶R 2￴vE~GXZokq)[-GiJNNAob'큫PCρCKKYu[|ο>X_3Cw1J MXiE⣭/ԝ\sB)> u-BJ,-6",h ZlStL(?k#~QŠבꀠTmv{/"T˕16KG|M ˠ |X5Nfx* U TO0z~I0plLr'^鱰1]10\yba;}7?oc$  T x;ZQwM.2Ȅց,=?xXۏ5%:)|D7})Wh`+@W*ݶ+=$ uyS?\A)!+A8}u8˃9KdN'lҁy? K#VefZR| [0hl VX'CL!ETE`ʱ ?=(0N@,3gTG (!W&?dv΅oj7encCE\Bm`YN@n 1AV`Ep Z x>})O5ܺƆ|!<{hc+xK$' q%T \\b*C|] \7*3c) d}X 'ሮGTm=4Ȑ9O JYZLGK Ң]z$j/$b vPj&bD>nasWu8tqRԜdߣ Sk1MfWoOqײ)CߡmEMN<R$x=t58E(iR , sMe焦^kEh6Wh;%L@c;HCaTip~ Zns$e OЖ`Y;`W:p'AtFv)0rlu( vw5:u?4KCeZ茵}9( !ΊS6uU ]*b & 1N PI {٘ 6 "@_iZ7!:m#Җ@G73F:VrHXFf7yZ˩VI}|wيW5FJLhELRJ ]ЏOO׶9̯h4<t4 ߱Pc1#爓*lW]>0Id_NKPNb_ZOАv4j\C o(g08@A yuj4PZͮy:Hf%%/*`K4?RXYI0oIP4p߉doZHON/ O}&>2ܭ #{:_3 6OtMy~yz0+$ ݘ\=ɉ/~ >ɳ9I_]:eEmwن:WE1: נD P#*naR )R=+N'1l\dռ,ʗ~"-M5#W .ۭ@If&lye|b~9Ҵ}0齼;5P2[`trT"Џde 2j-=T K~rsmHt.|!˘}HWѴmD3 יFBdֱ|xaRZPy5dYԙc_ZG9_2^@95PA~~ʾ= nN'>>7⠟:PFs+F+VUC&5b+@pU\!st0[3)7ނTk&S(u*xt 28ޕN<"].]V,(uLm?Eftm[r6<v}:/4D0;<o{Y/I{sPw~j98cޚ8Es^D݆Yp!D&˛AYfK+ -˟&^z915MCE@TJwq<9P%IU?~}Q$y"a%䌃s/L\8qXPngS, q֤Ea .XlM ݜoJpǙp ~S۰ب4R7:l#-+;aH{SD7ؿ>BE$\>btvbM PTd%/ {K;#asdۨآ[6tDZcW&U.Wuc&{{V薸tC"H9O3)d S CƝ'xLK߽f3ޘՃlj[@֊d-}[OC/ ^|NwAGO%$P¼~ӌRxv᧓~~X$3Q /d:iJhq:բ9gCF4o|>Y; @&Ó :v*7ιH1 P3oN;Y#H/O>xq:aBCC껇ߑfѼ-3 v=&*?d-2 3g7l .tdBV+l,~d'q20M]Rkq݌MZ^xc*)sld*UjF2Osm 4@l:#EQ}E<5 2|O~Enwy2MQ59_!wxh,D@J|yqg G9{uf]v i!u+{%9M"3[!1dLt-y63GtKiϪ4~:e0SՆnRSu$^ndA.m7_Zq`@PvRޱ ޺U)ӂYyN8NZR]:Q eՇ"WWlT#úo+CKiw"HPæ5N_(4|Aޚ5q*3miCZ>e";!/K+ D ?. %as,o r9 c X~%.=!_ KsAKKc|!kHZsXtj:?@-x so\ʦ&v& jzMnHW`KXBmHyJ)2&S+4ôĕ8׀~nh>CX߈!=_ 4@0^el(|ƍ ӻ`M(EY?Z#_"_Q:° D|Y9fnKn>.$wa&P7> hjy\|YGxI)  +FI3sY{MGu<^QAV.~ڬL3gQ"`OJI7TYPo~<('tvC=S+ŮȵzV[﬊\i5xmɐ&f'diKrΚN{_lWW Hmu1)yD,sX7Q7Lz wʕ~C넉U^s{)%## rL ۥ'ܹH B)?ŦAF6ե?>Q8~~Q+>PS|܀ GkA"M0EY<0;׉;=z6s~1fl`HlTXj:qw!_ L*0khB)}ZB["D6>?Bi. CZ$ Zg.Iu2E @$YD4I_~b2Z9$ nۧE`eK'mGT6 ]2\-O:įD Su` 592t@kNMhJ3ͼH4eUb[C|=8g;eq]̝ayB@'%3*@~;kY<\q tOyrgvQrǙ6 a`tR1 ,vH`r:,r|_<}25_n u..ݧ~\Z,>YmRӵvwz*\3WME-!4V9&҉.J6P׎.mTUцI2y:oב"9: Cb MfE׀b {NO"'CZ3E?Xר 6} I[}9٣$emNFfjfUfhw[/<aįy ÁRjV6;#lLYޫy$gU;1Y~gփuϖ9Pk Sg3y='l^wè%R<#FUsR̈́5wjIG =uIK哟B{i&~Hbv!\H*P廉=x aw_$:P1]7SlڌɏUeCֆoSі |\fa$D)yL{hԴJzQTS\aHqE!$z2x~Q&f sѼ ({6jk 9=o)d$X*Sb~&s}$ VJCD<7$ ߆hVBux:7O!^%42ḃvL"'aױ}I&}吃Qu2B~V6#N0 8,&.~L&OjdeX xaAl(YQL?gI-}xEzFC>]VǁylB7*+D91(e/D!D$ߏ$EdXt#ɷD]e ~H`Y>l=WzoNrfĺj8&yrЬAy4"<*(^Wv7!#<܉"tr;1QXlm_ӆnXL= 4~K/U2%sѻb!tQ3Լu**jlXVSKT&Cilm׈V )RNЂ L@kP8hXi0P :YGXe zR Mg.]x8uDC@As"ݐCқlkGy㒙K[/cHŘ]DcK2Y)mw Z|p ƭ2 5҉N%YŨ u:~=mU`7hF!B)CYX pז&$Rƹ8h(5w %ĉ1"9#D2 2J]UfY}á.b@]n>X|EP>%pGV}cxy7|xkD6 R< &>dE~R&9DT(̒ՌI QKX!ut Mž1tpњ)pi+˷EӠ ̿hu;:pE#Yh\O(l'fFW"GyQ9D&T#lK` pYOn©y|5&7"/'ow>1% dX8 הQx tX?0z8adwt&uP,EW-FfgjTnVc`nA~ЋYSceM8ګ&`"uAKi^E"W7ZZ8*'r$y؎K&RDG&Saɕ&OiO*)8WkhY`W*#~4V0=W:|m୆q {`\H /&o@#= 6Xfac/M0!p,2+aN]z0?UǩnJJ8 oleme uF3duhs~ RzJS\]?l^d25G_WmMC4!ZꆽQ40bxO\ ceBǎsx ]^~#,acF ջJS]K`s®O' v+NqF<]Ù̡ƞ%67`߸ INBGy94r*[AeӪ exm V=AE&0"K&ob4\1hSLS iʏ~~WG sfP-"󱜇&/?@ׂ$B{S|Yo<3abYh,(E ҿ*XԷCtk.fyߎhLH;6"TM@s@ ,e M Qn,oO80Mi-;2'N9`20 11WBHBWV8RިzZlCȽ2ұp`HMr[IԻDhҼ;g.ě) ٺ NNJޑuB! j`a L3Y1f w~~JJcd Y{%Λ:@@%gyoY%bGHRgԬP*1e6ro;#E~ R"dR-n`,BD-am&2[f1!ZbIh~u]bx^zQ()j5_$hc>hlo鍵+pw1^zD?SƑ x+i/5of[>7Ul 95Z}V=a! >&۫|0SsLX3TfGhHJIm,}r /jm,V $1#ֈݼ5$I1 |CeG1!]6FjN4{H:u{c@cʃ![Uou+nSzp?`@T8%1ܴ.9_ HLj+I`#-*q$ ?M?E|Aj~0MMÜl##'y89epT'T sfQjXbo[7)QYS@izH!*&C0sנ^p U<.FeBx-"-E2}q h $Kni-Qei׏+ ~ oN]Ɋ㖥ђ8* Xr\{A;gf}'B0K7@2/!C!թQCK1)d-7YBլ;n6A[/OkDOPs` GQU4ﲳ>5&η5إDy"5M=w(w>.S#ʹx-`Dlxѽ7$%V .VJ6P4ڄQ[V:Iu)q .&Ӓ_ǃ\ԝc;NP[@1Kh|K;0"cMYmazĄRߟϖ{X3U\S1*H<ьO;9Ɣ`̈́_.>Yu$2- `nb^HC:S5 и!^_A6K{PIԛTok_viYm2oK πB@_%=^zAUԏC/@~hExa{>~W` L.& "̄iՅV {IF~[[Jd$1|(-^32aDX]S5yw򴹅Z&DVo_L & \t!av Hcme_qn١g 0y.Z/^(n T{+廬@ãCBtbAD vSYgYۤt&KC4m*ɱ?>\p!) ; BxS}dJg 3`T6MX}Ee+vKk*,1fo *tWu8' (_wU߁W_N;/O=bivn4e`bTι:g}x!HsƋqprUa>&g鬝| ErBӄbPist?bꝉ(^H@5A.hæx˓|P*sDr*X^y6gZgq`l`m7FF˙~]Y_S!TN[|2eNޟ/筑!ebe2(@dy߾שxzc~H'yA?=Qlz\hX@.hXP&&V:a .eEҙx:Ԋ.mߜ0GZ+tdR<&EH4<"vN+NbT:l5H pv,bK5:ae* gvKݶt+@(iyFn M}46&DudH @9Zףps򜒾SH}yGE鞄є,%a\=Z2Ty웴F?bz'@<\/{3v`05-l:rACI8 {dޯ AW?_ Rsh6P4H {+EB8;,]$F^E{}\ͦ;4M̈Z.&0E/['-|~\-W!%d/7B(_+{铇$NT51ddBnA.,2q(Ac{^OAΥ4 sI2**{jgHjXbQ̓󱉧tFPk+oRh,'*?JJӖy4E)]A[ҫ\";` "kwQbஃ,(&!]Yz!~w\볲KX614mclPL)?z %X[ÎpOrS DܰU!0R5E?ElpJ u;:+eUe)KM:ZRd'I%@s S(~j/x7'-Ks7W5UUBBʱ`m!mMO̸ڻ`!QI/ȏZN[;۱i(ˮ@~Msx3Mof_]IKOK@;1YT^ֶ}<)RD'௼Rޤ<2<eI&)%P4ls,vVnYet3Ѡ}u4,v5MTߦ ^Jy0"F0I';аܡ\; sR8A y}|Lت_'oKd`ʗՆ0RQDUeFBbibJCvċTXܾQ顜[3b8cjwEUFwE xX%D Rx돩bLf.ްԼ-B1-g\Fٰ'<´4Fh[\;>@b#/|`htX5S9g񔁙>?]7ԣ %܃?JHy:Ywwᛲ[sN+>5$.&I-`vkхF?ug%7eH4m?p1-4&ɧb^oI GhAbY/؇֋K?|Y>|Y!gLgk^#kJ8 bwq72tK<{rWx~氌q)V,;1(Bsд^\ &z.dCdI'Wl`_gI2LL+f=6Df`ݒ_a |Avuee>꼵-{ۇLZ;DriS6}Oްtle%o\3[C pq=E e(&*,o}|fZxn:}f1cJ VDpA1F6~i' i yO "Ȃi5 "犂l,QxΝ&-+^Y%;ML`!I#g~L#>甘@l͝0{[чno-KiTN5, tlLU0azNs)@PJKcTAWQWwۖG-DRvue]Ǽީ( %0rB|UR1Yb?2c 0KR*I<2Ljʠ<[LD5 iyaSԨr%x o؝\#4]RS"Epia~ݹcq;G5};bYYr#% z9 $q_C[:(& ω`VEbbL XƏSymkaM[͐T6 TY6Kću=Va'G@x<^+PV~Hi9(N7ߨ.{Q^yg^G#MH8I@; ^: Yn)OF(~. >7+=MюH 6 _08F x˽lIl#^JCЧ @5J k{j)~W}Ŀ0p2&&JC1L~-γ265wUl^YҋsI@vewq' 8HC~JHBn=S]^tp, 6_7Ih%Qb- @P٫Qd0 [;"X=cСY6PT+WbO=V47Ons "b'\n}?V)%Cb(7Hs:"u9ua&6tl. !̝2TnKQI{ޘyeHʾjxW>{xbܮ"3A-X !?< %߬H yq1`z뢦VPHTԙR=LQI:~ rK%}JP&En+@$*Ƴ!!7/}ED\vq#FymZ6p~^Ai]ZN^D10a4Pmߜ޶u6}(Z7ʗ_Y'Z;/Ctus}-XLƴºdeDUex[/G튺TZ [4F$)D{ǒЀmh-&)7wK o 쎦ǭqG8B}${Wc`c>@]ݶSI=[,Ҩ/fYN7,Z")2+&jm?ג3xk\)K բv|3.DxQM~ms?:*RDU:7>7PM .SNPhS5^7WE8p{-Cpٓ_),n\a< N.̘}T\O^@2+{K҄ʽ .jh ˗\ϥ꺩h}D#FÉE cbwBt\2BHt.|),=碢x~Ύrc%=۬3 JձP߻2c.ۊ־/`E1Y ^n&qTkziFaXIsRkUׅr3uA*̔Rhl\.V@a|d:UfL9_ih!Z@gkrLSA}-Pp쾤[Zh*/Q?}Ÿg~(8ɇJ.]w |0XI__nMes7z jE >Y =Ji션܈cb̬ug)ڱZ$gBڙs@hܦϮ!8;RyգK&{]2]$1t9%[=;rgD8qDߊԖǚ%5RL|)d!V7 7!OАs"mRVz *EƼ4x.'u6Q."0l`VΌ.јP&U, w#sYڦUqMH WnJOh5dZT2fIE/:HhpM6HGO.z(hܭyMgE.AI6u0 tRj*p+JtFϠO ~:` $b2o{حJWpxnG7=,95}mB|Rr;z(qـSӕ(Oܿ KJZxdS9@c &ĬUItr2cz6k7V3)udR֐PdȸHg"@ $6ڍ)z1wa)*7kd˛*b!E? EBJZO6@WŶ}]R4~&sU(7-X1 m}y-"bdn\YUT7t)_'J]s,Gh)={{ݽ<2aNnމ%=b7^/\zyAo{++x7j&GSܫ*zBGN1.~ cӋ6]h(M6d$' d[.j^%Fąbb|<#jͻCK=M^eӋ} ?4(פ)s8J;']a(3D݉~4 ׼k˶7CV&0xMAu_8V\J!|cY{ H } b 09ܬRA a6<*ge!MUQ*x`5Vo^DG 3S`,G>wʓ5G]*2cP1jjqƔz k_ |/¾?j꒮r5zJ(q4`-5o8"~M`%N|0W\XWH]3mc){ vSb׼h6#xr* ~sCN Dԝ } ,O,S=\76g xd?M(G~8w6=-/Bp.Tɖ"nԀP~FN莐!!¿D@`ݎ#؛l3t}nA>Ļ޶fh))d$b(?Cc.2Yvkkp MOΧ/݃PD(s} ψYyHN*hQtDe!g7kl== 0d#p2LEiʹ۵(27\ްAj9 W)$4<^zTb @u#6 ކ΀Oyk-Ge~{Kx|wI^#\l[֧$9ԎYؐVzyҀ@'{T /_llV7H @`(!yE.C.inm1&RaC&_4]B SiZ52)z˘C&}G4FjHJ7i{h  ^:M"3|@Uqxu\#MX7/V] [Oobѣla@Y$2#Ӳa@5ȉE[W@&H˹KСʘ 6ltVe~˳ɉ}k_4R']Pp$+ivV0wC8TB=H7ztDzh]،)wB1ZTр=@ahXz/!ETwt*r*/gf)2jݖpԂjyF?k`3m/~9IsjJ| \Z5ypQuh"`]#H"&G Ja,L7:vJI 2w79iz[Bx4=dAtE,tt^)' tuk _m$/(8W$-8e%z"NLb4ADZAUI] cnQB)y$ "U~b6ނEԖHu5(U܊~p2hknM}ά/@(v0Ptb=S"1IW[j2v8ZlmAFk719O>-x)NJCdqH.aolu2"&,5媩3E4U2qHʹBcc7.e=Jb7{s),%6ُ+]*.ȝkV#NWj:,66eRԺx(?bTrxO]#:ƽ>?VYC)m‚INiĨJ7|vcHsOz{r)!;SW~?m&I_ /=SZNH6$oy'Y۬-܁{a'@^p !FZU'/,/O6hQ.V=Ɨn+KЀayɓ w'U0PˇOFD|xY{bi+!Z]8x7I&ljmiRcmz7v9vz+ή `Z@I84ȃSo` fӇ>/}D#vިwSjЏ%cޥ'h7˽}Iʆ^w?|Yl]U =Ά ٺb(&ڙwd ;ŏMwE/1ZvHr$<6D[ט`@y6([a6gtk4Bwui6uZStn`Yo$Z,QL:TNoF9PPe]=ё ϵta`09s¢ǀ3Aӓ|X &A QwK4K>-F_y1@cY{P=5GYANi'|d{P|Kz`_ǩHbvVfpPZD`9Ff%l"<S kqb`0pt7sm8mŕF!߇ģl2k"T#?W(l'JDm` c( [ V/Uȷexg},K:KHi‡MnW)[ KʟvC r Sb2HH%_$7vy?`R6z/;j$mV쯙VbV6=-݈cp|L4<=8H[/xRg h$x3>%jL(%73h A}k P1q@ vWf*+v2gl\fOtHl':ljfj̯#'eSm[wM~-Pdt|qhaBJ#;Nɺi[;"@oKb/Q+0b\dL"Cw)5!Q}7thQ"mUE=`Îhb?mY^s R_ھi;AE6ۇ(P( Pp%i*ZC2b(I'kaAR^C!(qb680OA*xu/Ndn r1=#\kI/ 0 {xE(WPFˊdԟxhY곖"-P~:|{GbH,+#}uX:ۋ7\xt 5CPd͗:<5̉]E-!M.Z zC,QM#l/|e]cD`FR6("E xYWU[EgZ $~Sd"|Ig# O֭%Ow\땥 vh }7mtr ;#JF_l|yYy!z'Âcoow0 6!} j1ؚ 8Iw>iyJl͐?L.zeF$[0(ocFO]iAp@Fm;1Iw!BwUО6&~+ȑb珜G29a$+gQcꈜnKu0qr ԛE\}EaY7緡zxAetXP~nDI, /1t4ɖ22q2@_K9*Mq2seg1 _ HNλ)Q2T$IG+ǒHdFfI\yѲ'$2 < 30D68 .$zBāa;WAP14?~vd,EHFbryJ%ӁGhyN̫?? Nf EtW#_,IC%ţʴ&נ0wpy'*fh%BBqÓOn Ş4jK /Y):dRc)C`k$'u).+2cwy:Gk5J/nPf :J'=Ԩ} Ը&y39] k;[ׁԄM]'֘vg̶L,~Z`am7SeZ '8`yNVmCG0[|2VQa* Yo[ߨO(Ĝ56!eXXJ#[(Ӫ |Fe(h@$|j>ϴkPP!ll 0(K,M~" eUgdpٱ. =C}$+UTdmᰘ&Ht5EmL#tf:wEa]|>bY3v$K M1%uV}qL.,J>XNռTg‹r=&2FD.IϬ򠏗 Y#γ/@4B@OP^5.'@)IOO2׌'^^4PdP~I;9D+RT%ctv6"j&&Ae 9j")ZTW|[%гIhPҡBBf`ro^U(\ABlo$wWNF4c/Ģ==a7 fnTrxE&$]$Ǫ} WJh ~ښVhʳoqqQTZ e=`dƯ)&Rjᆅ1GPK90:fC>2y.T_s`UDEv( hdq-iOJBA̽RVe >XD}t`όȸ@5Mpm!ےm3C1 }209͏y M/|ʒyP`(3wbrUqw0ͷ;LM,.!x@JC/5#<G&w5s,Dn]M4|0o{2;S|;8է5og p Q&uPdёK=za|?Q\ d 4fT+VnNEC@xҨߜ'ziq Nư-x%̾`V &?JAk# V,dL8nz*f6Mt+sQ(%qDVOF*BAH&BgS! 0N lK$OGP 1Ԟ'!S \]7ŅkI-Ii'^%31"UHKMs̳PYj@֗D] 8ڋ,C=nFPCnIΡYbsnדy lw ŭgyDo_I5We^~Fdx˃ *@̶i,s;u櫖Bn*GǡfGL"`2[.ܢVG׵.n(FyCh+ SHI8C2*"(=ʔ(8DP:L0P-Eͷ6Z@jE1ƿט%ZP*; r錅KشAk+apsBNZӓN,ec@&nDSG"$sYDW6Rbdbpb\5ع̹0wLL[g~*]Z[ńpi)D8DsH |XCQI@ׇ$"+8?4":8 Μk bЪrsNmkcDv4Y't|1)1ɗqEhF+3k=x_NK[yU_~!񘮖uwFaaL o-P_ YE* ʔߩBH)s1BDVT㗖=7#aB1 0~>J(7G^Zabm5Tη< qܙ%v-J3ȱ<o^U S0' .g\6dGm`ME?;~{P8Kjt4 #4njc-!=2ykk`BՂ*i M[Fq0j!3h_73%. vڙ8@õoʙ7r5}HpP[)t1gP'p=ٵȾtWl^["'}>t囱9\l ֙K%5h+K]8:,yHl*I_CЊm;Uޞ x'8F2Ǐ6Qn }KF.` da~7lL_,Nv㏖/Wo4y,k,|BҕƏ."{Uᤂ/%hkT-"P"9F25%5Z|*%0{3EaeK>L [\_ =_/˨w)%A*"flWȳ";/C3~MS;v2ϚfY 0&Mg2sJx &|Z?ǻ-sQ~@Wizr՚a/hƾn xh2=%RiJ! 8iH}mWjNX5IwېNcÎ1ȿu46$o]-ҾQ7}ʀai=MyLM>`4Uf'in^i\E׵ze0x%C޲R G_8wPM{; znV &Hܖ40e5z@We4'}7(ᕦit*74vgܝvL0FpݣM 9D tڮz{ g5:]%, ;Gvh_CK r'x=дT* nbaYFF&} B&;!FǖtlT΀V%ڎq?SIN̋ȩ|V!WC,+uqDbďyj٨G}ߧ1?/unt5"]7f/j\,+ʚ[T:} 60o\Tt~yp0ymKbxΪYQ&YU!n]H6Srضu;jxc'щs!`4NSugP5,Cdx2!}?Tʡ@{ M\_ϹePfdxBծMKO6*=qf=~/piUU6HIqBüM!}c \_`sM,_>JWp7}=PK W[קo0&#Z:c+oY<?6gn.FOc1[G-TkW cJ~/YT'9aiR! Zٖ g'+s\00@4|̳AJewƃ{v뽔GJ(YR+G5?>=irq|MM_V(-wL=Zi3Xl_ =a/=dWLp.dDY6 }_^M #q^d0֣6J2C਑ ̍#Tt7Z䈨wm<\RRnqD9y1d&o[w_ 4b 3B·DZ"7ĽeqZaTlo=%bсoϻ<0G%Mmƺ#d,i"tMs:ǥ@ !ةjd+ -PX\C`u;ҌxIh bzNb+@j]Vy؎II#Kln(&Y;VrͺTEPuiG1Wuhʎ[T׿=@YLdb'lZ<& iP9sJ3vAC^ǭqI<ޗ%T`!-!dp/biRhܒe vcY3e⹏@}Q^nGQȨQ_,v|+uyTb"݃@jև#FoE4 ڱVQ;kMIjGy{֐a2]p}UI'X_"1̝z&/DNV{kMf^I韐dƑ4;_w~3e&G2SA6vSQxlyQ4MU`D{ScfrPiܵg@n2WBXaG$y1%E%? '2U"R;G¡41V@6H:3 AZE#m?geVJ~{i.KhT? n%llϛ=Of2?bEOJPWG:݉5O'To$ܭP&NWUNm/%d~M vN[Z7`Y/ˠu %W# &7Ml)N PXY#w *{+yRj 6۠ k 37,Lt_KkŁ3+hG6ky1{Y TXǼgx 3n[')16Ib @-&61CK)il,hm6}ɜ]gNwإ ; a˖u~āt89$DL*G!nA\Du=׍`j7 ן͏v*u@Ərq޵f %5py@.puC;V YFZ9'"d$VZicGb!l3׫Էp_.p\:kje*^,3PU ×d}_Q+^qmM2/w1G%׎ĬK{ʌIp_ՌљA[,yi;db TBɽ1}]%} ;L4&Kzcr' *o(p1V m]r5 MĒ\*7T+҇MC_t/#gac/վAG*ƀmg"wP4xAL$ZoĜeͤA"z`wEG=Xٗ ({AN޻)?Ą}?C*cUi#(6tdrԄ^cmX.*2`(`9-ޮ?~D"Lp33  hm4jqyZ2h(~2Zkj:SWj{2+dſU׷D4 jشC͆ZOe62z? E^r7үlM4P+]+mR:ӤnC͹/9fF`!w &=p^2鹵'y J&LU1q$i-yeA_s0%&š]~y~<'iCԥb.\1.ϤTNCPa5gBԋh^I8N.- ~'fHmf+5=͏09R`iu5ٔvK%.B翿lJDE]cz;L`1N_1Ȼ_, `CAu$;lߙWTّ6hMb/'AYmޠyYk+2-—)ѩ.c3 .nm Li|vm0řlDNyӻ"QȍF pNc%ZL f.xЀSZݭ3VEѩv3`x(zY /"l" ?z?H(&'qC{DXVKAjIk_3'hbBu /ӽ]XVlA lxA"D:Mup-LR!?Cp dA ! a k]_IiH^"O˄L{UTK4c,Bs9gl+`@/!7|x6$h E-=`-dK=?6Y=Hvb0\sg²Z+@>i[?:э3\uLMl 0;q1Yzr^d!^?Rq^=^gЂS̄#/(qp!.5:= Ea+ C}3$RPa5  }>0ZGi#J0*0b( Y(~/}!Hkˌй9 2x#6$@%"HWwT'y"Z]#QbߖWD&<@cQIX0FOPX'VxkyM;3=.wݏ`[` ak#/s!S# %Rʊ?=Eqm͚Cg<0|4 50ڸ`Mx@$81}TGω >#94HML 1 e^5Hon()&JܯM/"zg$Z8I` YQ@-A= W fBFi yB D;CK 7<6XW ;D=R(#JQ"]K7e*w x>@4YVSLT?@}m ÏBaz{wW a/uz@$v#钡I7)HU[;:V=A?ϭn=9A˘EGx}Q^c1f!EKA+A_"&o_1AHȜ<];^#?J#^ۿ&6Xn@!mҺpb. OW~{X"뭬"(l=icRm=h$PP5[ޓgȻƓEO9ہMurȍ%Pܣ@KHBo붇ı-ږ gs4W8 ~t<|{99);%T ;`My$Z 훅R nA [(~2m,q+2}ا"OؑLHdS u .˹-,ȵt[D{OkϞt.$*)+۪I*|fwLmrx`<%3:%-/-B3VCM~68äJ' YoXI'B Ct,~d3(.S=CX%[)ȕ ^S?Э9,׾v!~iʳR5<"<8g,+3Uk}&4?,fuP=,Θ(G/rSǕ܉]Ťd` }Z`|E n;;Eo>6]Ę0\:ɉO,Zz;T>?[wIpfmglkf?=wa@)yEe߬0)Q{eN1gDZtkܻ|~AnPx%xpK[X qjM6=rgӡoG`H0jZӆ*̼Qpo~gRK;~9QNPLfM~R.> |0d iԻ,"NDU`4'-nuV)I#m>j7I5Cv@0 8t*&8KsN$"bo1_􂪼z}vńOOFopaҹ,A@)hp68'g^ؾ1>amɼX-5Pi[O.f$d P6hEEyӡdH2 f팡1L[8U HG~/hW.AU{9)#lCg#%,6tHw$vhФ@6k$=Ӳ 4n/IX|=\6# N' o @tL/r衯11[Mcq5 BE.4m̈́ db^lIU* 0005m=w'Hʺ"nr:~nkӘ#x`2IJ|_k\6Pj8``l+ 5fl>/(uv '+Oȕ_Gd0Ӑ=;W帷F,Tp RV  Z0 PW-b#1OR?5oX |46Q(|a{<3#M!oP%P3^vӼD4Kv2l]pj2ah$C.Z ɄwFu˗(bwm؋c{1ϻ$;q=!oy~o*HfٞfeGˮ.=Mu"ny 8rLURϷ 1,v.9rv > pʊx`-;ńR|'K b#oԉ`8T2fyPkWLE4DROS(™ʁ0Wf Cz;~u +䚶ĵ"@j$_^xuه,|uXq~r}%kޡh+8}:˱ZΙn΋~_x)|%r)O8ۊLDmC$.fݰC@s8HnfL[2CS58o '뗠2GW)Y aor(B?E$ob8n*E*QyKHǂX#0~(ޒkY bx#$2?oϺ"+" B4ֳwI>:y)DB " t?Un߿A} w<<umW)@*=8Ꝉ$ rw_j> AiVK9A qd +r/[z7ɯ7L20 MQm0YvNϝ5N%`б?4ՎFo[PCPEDE:R4RƜ7inWfz'@8aH-`=% %F/A ]VXIw$2Dax-݌;B҇+F{ow^x+SnNʱ->U,H5N-b0E-p ' ǒpe2g7}7~8ykPtüDzds;z QZ.08﷎@O.<JahIW 5-cMٷ<|^I>}yT=s?unfh07SRX?RRt(%)4K;ծ6WBZfu?`7I[=BnR+*շZXiNU3.~Ǯךr" l(p a? _GF<ڹ<9ZBȭыkGJ;W  ;K~g?WM -V4nj`Sv6_;7uB+g釘"TJ*}e9uctE pQAtl2˞E\gqnQx+l&W=S%/ ybx;6dABp=}ѕG AeN}2l$Y色s S댆QKb`{cmоx14!2/l ShS%SvCrӈq1v -Js6vTT=lMĶ'̊2dsfMQTJZu.bٛ.6 ѣ"bme[?>1qweL_ K_54ʺ@cgf4ŀVN/[y_-p $\>E?wM,B:H0.r4V0'4/7)#Ƅ!dFm݋fR2O *h 2  ^Mf!d1/܌pqĦ9=1YAMCʎ3A<ԯU0xifHׂlFz2zCH]rI60Sv5le%ܥjxX*d6<=e5NJoD %4(U"t4&ht%B0Qdi!^cDw3f,k}~]f~m* zum<ߵ؍7Fv(xV=?_p#  t22>_:PDX蘢Q?ҥèƅ>U| ު\!&cCno4k(RkCoA0M!G-ܪ.^׀@Χs\N3M\/@k l"gO@(+~aʄNzt2ΰyz"uKVꎇՙ1A=D>|3ԡcꘁΧ۵ׇu&Nx j C t0* fW^nD;}*uOK=.%o.L.`4m,ή^2yNx~Nъ(-c azZԊVeblr9٫7Pvv58fV_qL]qJ+mZ!ҟTD`آ._MR|&knjγɑ|u4*WԬ`p2M#HFEۺe &" Ng~\Ml˪"׷KȫdO/8* y{,?d[h-\)i,HC&y@8́SXT*$* ݺ92}qȍ""ѯ1LGe4"i&=ٌ="%f;'b)ԗ3SyӱTREf ѰC ;G"?Εci_=|XKWoL9,Ve0v.I̖cdƉR{FWϝ5f`*ɵ#%e\e;k`-yIM+9[la]l87q:_F>6WRטSGoa%ᆣB&9i"]6dR X"%or?QqUŦSuQRƄ޴4]u+WslȻDW?ඵ@\VD CPdk_ӏ,$ xok: /gu2%%<ׂh2$`ATd:!FIp+Z_E9\-|,Bx?z?t4|UEYnۭ$H?ή"Mp3y$[#mTpMkJ[1Oq?ʼnyFPReG<Mlnt{]K4Y+i_)V8!O5y*WQ( /0WXDzbJ[8HZ 2$ gRq*FvkJ!:8Ompʢ/ǬS,k Sn^E}ĖC`'{F֛\Q)å56˧tTX8NM#sz氝1Tv] v:d$I&qpռ~ƨ_G[q(vMYSPwW$Y%ݏG,"? DS!|ı]2&M׌7aj||sId8o(UG3i6nvЩCC]ȲL 2ɕ O`p㣄h]8j~ ,Ay2A)(Axe+ՆQi|E1[/X*d B$kص-xb2?O5Pm-ENEDulAErq5T<1| ힰQNbj 4wX:G8'3crl`|߂s;6IsA%J`+OJDPj8лNfEn _x#;!SfE1Ӣ68Y~]& hWZ6[՜ŃfGJ iTj'/RZpC >~C`GobC탪}b`8HHPArDxdϰ0)'e #տ:\-]8-Yq^XNr}g.! 9 R]%VnB:Eu6ogϨ ;!>"(WyrlyQcHֽ6Usi$Vr%B&J s,(U FY!(5E@^jA0~*&Juov [4cs`u34[ҠB6$^W aw@hQxYTSɨ=~Oa.s )yctJm$oΐٶm A$ErQh2<|z /m9% qgХQhDb3*,@Ln"ʂk.`Ѵ(ru3Jc 1|wG(D/R2Jf(Zc ;]A{0C8v|0" U"e'"?=U l59ͧܳZ=ZX}mkE5F%Irʫ&rB&i®s 5 ʧntC5(ZN`[ĪIUnA̦:OF px~S &^XY!)gRgIbe~wCKMӳ#s6/_:4t K]kMNƪpDMv= ežЍքC"W]r-9OGzݫėڻwm+ɏbH^YFfW*Y: ז5K1_tGs{ 8v>[vB'1Ey5dIN/aP3'$uCt Vڦ#X].4> A1ly5EHyEUj,}RᢶwǹT$15I0BtI1d.՟CP]3T$ÿk53tU{zjõV7/̉q|nI`Rmqcߓ2*]5(Eu(A($Z\R14CxM(k*Bzn]jGm{p"#FQUJ جa_"I!ؤjՀZ,+ X, Eiκ脫Mqly>?!(nbXQYd\H[iӑ!O[>+7kIv:VJ?TN dMYP fI} &]VeiZ2P|#%8X&.9oMsJœܤW4 0p_t3msx @v$^= +XL ~B0.]m_%DS⎤,FcNztH-|NLV_ ybnyQv!,07svn09?9JO*E424hj>>=8k(&t_yZoqi'{WA&?NV9d9*)2Q79 (Yl۝oUHDZƙ/N3=MZt_mkcIy`ʄvlNhMjF;]11 )jt\ gǃ7x$޾T=nSonHtinul <`n(YC$_JeqM!0n:?.6nDUTq]}fw$QN=}+҆ρiP=L:#L*هywpytmBgMs#pk" ԡitxEi9gKuS9OB+*T& )j:T㉡>6ز6fĐPYߕ4rm=o7iGdʚxE.$?ɌE~G^v\є,t a#Xn{FP= v{m_X[Iw;qEVoy׳'VhHeLg"*"~;nn6"&<ٹ$PDM a{ȦZy I3>7N$-6~>qיOl͹kCm= ªqHQܟ F6g^Gf2F7U4,g#OQUY7cZPpYMxP27 ?)"V+3W}4ָ?)FyJ,IL\vC˵Lws{+ qOBwv74*gkQ#{foT'4Ў>Tؔخ7-O?UYSޏZJ=A}7G Gk.{}uBZ)vs0E8 >@İ;x\&bIOCo/:AD)j7En3R䏀!S&q*Щ]U&!?`Hz"z#WP}M.w} j v!I cL9t'5]x+Ŀ{\o];Zc7(jV/ڀ hN4MR;H_ -KotӾ| r^A!\|~9`)P#[g7Yfn\6:黬r~u ڙ A~!gWؒ7I4Fi}>9̥trSH^Ҍ!yC "q~ҁ+UP "}T'H{J Ţewu,F8Ua%Z*¶433YT#;^PtBR;e΀gf5j,>|~Ev:ic@no$Gss._ Ť]*-Hx}UUH .v 2 "!A0 ; +ajvg-\pCZȶ1#t3&l< RYyKrU(OEQMhb@-OX0N/q5e8+aR #t&RPpf{.E.g!"ѣ4lbb`b@`m>$ڨ`/kl/n_Cm(mp8'~|lzzL< 7p]uiԿB<0GTB렆l ч}Rc\j⯞dD "W(eE愨`4ܯ.||d\dž9} <"xG l̓ dJmhX &1qɶ%I9c׋oe"#v;47;DK<}ݑAwu9^-蘜cKZJt37;rOLoP۰D.3jv{Fu#rP] lSaICKɀr(#%>Ϗ_hG4;"J )}4&(B>? 3nzn̡e͎rbdx@j{˼? DB۩?[Y].A\OFKВqf日 .;C3$bt J|/T12 (iC̣ү|P~̧y1`@#=n?ZTLaP !習DeWi XGЌ9|K^t ?h r |^Ս;*ƮfZ$w"b ף\l I)}OW=jqQ@XvV~X*bTfTܩ>u ʌ ݑjtNT [,20`V%HPyRr Yt I^ZIaiaxhk\WWHJ ʜ) =Fy| afJΈevu?~͌Б s/cCFk^ |4ݰnh^DrネvܪQsaݵcu7m UHhzRS1E+B>@`2?QfqS"`ш[P*<%0+gEu |Z̳wϢmg¸x?3XK0w KpN(`.g߷tLڣqYv{,P|_"F2"YO(AU>0+.JH0;K!7pM( c򺯩Gfc\<4~#q@clJB]#^HU_T5%"(YH$ Ve^o&n 0;vp ( IX-"Dọb |o ثz?P 3$'B0n_\]L:(&ąiH7 y 'g] 84fծf2 Θ;h-+ٯ!խK_R!Ge{oO^)\몘@Y#Tɚmk ň =ܿ"=0h[fw-f } 94U-Zr_CƦ7ҳ)緦#~9c|,r}7w+oK3w gsﱌRGn;+P=| Ķ.Dk=Gs>/XFVnGT^ ֥o,BMR9YxR38G_*8gFbI%(e߲ǨIE޳{3iJGug.ο|U 9 " +5-^9A.Pf<77"9OvytMM]To&z⸎u~FNBAkᙌiB@GL~_F\f^? i;NL!B8d?e q vhD쫟#ѝ5 PjwT9/F~ՙO" ֝ S`&&NåiWT7<o*fOy"5O6&¡؈Zneз4xEH{RNsdd?7;u)mea$Gԝ8w?'w V/S#6&FD;èyN6sY6~x4 M QubWBN/z i@{3FCF ltu`qCOL$NNśH+9F{%ۡh/ 'ƹ$> J\.A'/Jo8єeQK[:LFTY . 8uه,kZjkLJ>͕m,xijO,N{114nk>* زkLWH zYJlSdMo Ȅ ,H]HZV%Z [h@nZukF,V PhzKpzKp\I焙G6WNx~drr>@ cU1:|՚AD0릹E9<$2껀2PDZ:YUE-PDcןB?` )΢lho64ٿ+Ѐlaj/MTZvO|Nz;_3er!V\6ӥ \I̟fgKsN[<+Ÿ X *al_q>u=Lv~8 1PXLH'a i VYE$/:^Pb{M6aQ^sd6hNS¿Ô <Sk<$7n?.UDy)żlFV"ۛ:բ0Is SP]Kg lwXnM 3x rW]c;ex>Jiz8}tE8뛐 [c6B Ru@8̜pYs,®zZgc1[Ej_H ?C/P/h NհE(XVŨ O1Ӧ)ԽIƂqRn۱.R 즽;NE;9/+q"~oY45l铢ruAEL5 |_o2BAx]ZoTYՃ|98Mk "Nt@?zkYǪANi^v,ٽQ!IlֲyZ"LkCR6[)hM+kv3ܣK,x?+)g8ykO6R ~% R^\)]DiT0\Ŕ]%3AE"NAhbv%Q'UZD5ZLaZ,Ocpkg<rYd),M-deΊnQȧLFtۂnH92nN8d["@m~Q!U`15Vkr1 zKq`TeD?L-bY3fX&= ܏Ctοgr<fhxB',+Z5vWD cch wͬCGm#ͫ AaS{q2 @zjtyaY]f+4qPW[Edg^d\:dsJ)mfN%Xޮ K?]OweueY"HRd*Ud^-;;ayT i9ڱHy^8"D:Gʂ9W]C氡zgW9t)cRDrppCܫ(sN QԉX")k| aL HMi!|3Bz>^hdy Y0S)P NJȽ26Nt/0#D@reH5w)KcIE'~%ULOgm -f>l|S#>{`d@E#o6QN>,l46+2;oQ/+ da*N8Qi6D;#E{U?%>8G-D7LPL\O,gHxcnNlC,zU+m`-~JH|Ogx 0Hme]9)v]ކv|:I4J`vi3'X-EYqxx',{Z ijx` ehIaffktG :]ʱz3V죑1uz~;8zVjv>l,}Mo%ݸ}ώ=!G(Rж8^|7//uH9Ϗ$vSVܸ #OfD&1#r ?#K{JGmu#13ݕ3@c~snjPaYccI cpfk4B5X.]ҺUzF% zW9oQ9ǂZCqŪJApE{aE~G\3oXui_WʋtGjm-cN*OԓGI!+'>f>N{ HyHuzr+/fQ41"_e2}jد׉bN1Vq^OO=rf߫ J1EበTnϸS>Tu}Wˎ*@vB3[=!BߨQ|;Y2J{{5'0@P CJ49V1/ayw[3EYC*#5[1b7`_pc][Lª9Ѣ9֐鳄\"{fu:d XeY@2SДNSbLF:L*eCohe"Ux8Xֆ!@9xo#wN {YB\\$4hzcXݩŧK7hMu+Ye_٨قE;npbm4FW=av:zC%N9+R;ex-Lv,_"֟M)|!Idu-%+6DC"PlDb:'^sısn}'@]*V+ +YǘQN+ɡy+.'p_Ԝ>;$uXApΝ_CCj Y˻gkɸRۿѶ3qڟnE*f_Ȼ=8\*ʌ[YV"q\42MYJd0[ 8>t/j^D+CR}7ˀeE͏qߑ9U;Nk@s'0a]63*'ﻇ +w':~ˠ *oz'Ʒ.Y^M> >pr5dzkKe,ɍCi.$i]_`sc!sTZp^pf:@ lTpP.&;_ )Q ]Vܕ4XEM!8㎽RءڬSex4_wFWf}~G(NǼ+a'V 9M=sWe:[oeH5(ʊt>&S&s0&Ixad.1<07>R!!IzUz}g{"Ӯ4ԣ xZ:쇙-\&[ؗXZQ̄#|JAt [[6 ǂ[k8Z%\J"#KYB~MTW6?~ze5>bpqʏf#U;z5]Lח;r`{$ -\ƍ&hҤp^7p ΂hF.h^/O٤zI D$+Δe0 jVQ8{nX wSqԾ:&tN/>S9ѡؾVHf#Ke1bVD^pzDgL%a0d\e;;a໡#"ˈ_I^ U`lJ:}A#Ze Sl-p4#ҡ6 euo%縊 GL^=|`a+SA@mI=z-V yOEmxd>iV5˒h-+9Ie͆;6 O 5 JO1OA-ٙVqtϹ0ZkN@I: LSx4̘ucpaO < ]ݣGx\msM4:0FSB^'\|=1خ!iO+ d?-ʉfS*UEƂDzV HsIe29ıv*V7"hjrI:) DF QU+¿4[v /Rl hb_q/W$:/Uh!jW8Zy4 6wߞ1 pLka/6O dV2ϛ3.d6~"SOJ>Ivr}me7En<\JF))[(޵_8T x2kY^$~Wo š0h+#"Z"i"x?1L$B۹t'Nuhz-vgFZ ;iL6[QK鯛)(Hcy҈Dp[.9|HXٴ4EbHӇᅂ@lڙyL?ʀni SCBO@pUa&=Kg3n(g#tГaJ0C=ĊOXbhei#B8#{gq1!|Dp l-Yvͪ%NK {QS(c7T7>z;?X-]7oi\?S\W΀i_m8:?Z7>w#~(6}f{o;#橈4Wm2" {󅙼.k[m eh΂!!RYdW/y!1͗Ou\ED[Lf P`dٕV.(#A9 q!ix8NalgV4x6aٝZ'$]N2Uͱɤָ7PVt˶NirY H8S]:~gO8Z?)Mq̔|ЩzHӲ]IE2%{QRUhSɽc[/7˥HTCƅR)hw v詟 o"Y*{gaM ;\?P^OUSq" gŠ 'W ]i#F{t]} 6X\I^=QZ,^JK䟔ZNh'8rӧ0tZ9MjYP?j߂up5w`XG,ȳdAW  ߷pX>Di-Kev.ljb^{^)(4xGX7Lj T$T7 B0XÉ9x EPbЪtӓ'J<[:5'ٌk(Q #a2lizނn=IKimgBA]QK9ĺU혬q >~2Ƿ"3T\ƖNC&43X'YsN>nEw# +wrBLBg2'2D뤛]ןn 6 VmYs5C,eM+Cׅir+.j#h q'=I7 , . p;lp͜(!R _ t|o(;3T[JH lo^u-UQhC09RO=].Kn ԮHBТ׈ ﯣ`Hd?q hzx5=6 gEvSS8 1k՗ M-eexL_M k_A&|-I ? Slp„H鲸|zuHP1%$*λr:w\ QIvЈ"NYlt3=?ښ/q98^&/adDVi--pkJofkďHIp"Y"?^ }BhŠf?>:(Eb IJ &ʲ ~Us'5Z]MSU岮M:RW w"NYF|9ǀ 8lR(]2‘FKa&Wiz:FtOQ=Jh.ͤLO$ϜY0a5}M Bh9?7BYzS2_0Iqז94\jls#a] iمxߩLuyMAoi0&W۪:3Cc{-u{mgo"%Bhޙ\O7i3- -Ϡ[`jpJt$o$7S2,G:dxD. b lZ̉7WQw ȳ"zkp^6 e-R,ьKrcspbڅ}qi8_+2F갋ǠtJ Jgvq4yahґ.E]yS*,]a.fh}XbePlߕOYݹlzNzN<>ő'k6qK8:~$R5e5"&l_{dk0Cn?Ź>>oG5Hr˜fމ@)Z2ZIc.,XDLqk=*6Aʒ=tT .'ϼê)Y.P r|?NeEPSesH 58~pWG6:M6 E@=.{e ȷf=6ml@.!ؠ.g|3"CHM_uL>>kޙT?*O`GodLx/ ,8ݡ$| aEi2_D4lOsEM-:l9y'¿ktatl'o6q1*j^mEq-M0 vb|,[[Jq3k܃Tlv+2/ѡג b֓\ҭ .ѲˍR 4EAطR4Ne\di ᧃ]"sl$ϙ|8s؈If*w+qdў Qix%0=;ַX~mA^Bm7RCB|^IQlO&:Qknx]<F➋`rz'pC,~!XB#_?Nw:IO\ }Ϡz%TͮN?CxYQl M#}!>B/+Ze4U׌}utҰ̱Ӌ dמb*QN.5JMLFzD>8W$'_#I2ե_iV{ҰsJTO[o7o44Vt手๺+遆8|>D-,NxAlYk~E=شX,jG 8'A )|)Mc6"`x5Ufy~~@Kc@mWNfN0(˻**c-O2҅ny%zy 7 "YQ]3^D?"G1~(n1o, MVW7Au S I+~;CSqs?tiSac# J< ȸ;ʼnx $9)X ޕ!8[; >&˷d\@Xe\Un+ք#2~7 A>ߏ-/Zn4cdNˡ^@3wg5oJy鞳^8y_! "GQ<]<<zYßy| SbuEw^Z}pזsnqqF:j[o8;T&ћV֬kL3qƳd\mܪ ԧQ ELiPS7!g̬5RG9|aCY}_MNLFrqqy=OTDP/GG~B+ԵzrG&R݄ =C5^v#PiOPmw#^!!_51ygc@\ J;Fep]l£}{ ?N]hCFA]}?3(amRG/xf 8(j|Y+îbfܣL}l($D22{6mbpwRj'鳄[i틯-iR <':ƫ)CV6/יzXӌdD`cW*!7uKbeSB?qQ:꿩3.%nW- GknsRw˪P Eb xբ[а=E$H$ylV(uira3>RP4b$;-|;FѲf-MQ5uko>.2Q|i mW}1O&MiP5o_J[υ!cUa)@7*goa(5J=m ԰~P-tl~"θ:3n_9>Zɱr]e; "ʕ)8kqO YTOJ|1ƔS?f$ݩYdGL 0hT60C3|c ǖˡO@ٙ_PyDYIV@Ǭ(qb9a{Q߄@z^Th HCJo [Kf&Հ+>J'lό1_Q= {۔Pb,?d+JYq7frl̋SMǼ2-ךW!łLV8'p<DHu#, } ┪yT&<oS7HD0yMǐDM)@8H`! ZzWǷȔa}"H7OUs)cbw?io!S[V(ʢJNX2?+Z xv+!E&T_u- 9: ^a[ ]eЊv'Ǔ9o?QzYwyo Ja**:EQf|{r< JJMf6|Px#5x*8yA&2gy3RC]fk>mGݲkpt XdCH|L>`0j- ,_IHH0HM2WvkG>ZPVkz+LsaѢ᫷ay89uhG۬ʿp8 , &sp32>=ǥ:!'OvPRF=<#ְu7-&n2лyO{ZHKhpT.vCI{`O~D?Q>ME3 8n'Ly `+-ND7*g;Fy7x*y{ \jO+?T,K!xݛ:jv{E's3-r9X*;!o Еw-R;Eݽ}{CRNnxI7&k/0CZ!VIQJ $_*@h3.o 2޳sÿr؉Qy9H2LJVXjql&wl'8҇8-'-=`~ajKWh6e$U0_vqquϔ,^T~! PmyJ(Q Dw\'+2`6#$Y6Ê-U׹lKOD>ƀw,B3MH'f,/S}06'`m>s3ƚ Bဟzͯ0tv|8:VuZo><# (U\BR7yn'!^툥']ou^؃zK*HDFUl,\AK:Fr D텠 XU*оR.9zgK vדvyě~E :ֶckYяʷ ea80zS5A6T7ڊ5[V2 Qﻂ#w[KK坸dz !gT\1fFG r'F @G9xKnr 4׀-v]PXA;"!mo:D Ȉ"*㗀y$73?AyP[nFP;SSO;|*ۆ#IM]f <(kK/H%t {8?{p ᰊ ]"?cæ>Uv2!9?sɔ{:ʱJWpR:.̊O?ݳwR`]:dERF !_d痽mXԹnrpazfo 9e4G 7AD4hwr1i%޲#Y^KC"t<2p3:6H[+{ڠ!"|vGx=[՞%\RKCZDbh`CIW'|,6ط1/K j*W '΄uCmҲSmŝ:S{0ͺ6YF4GZ7ayf{2/8g6Hq1ӃՔHFUkrjlf/ 1dwX lWTN;kF}Ydzh(d+X`#gJƠ@V I.f*HK۰z"'틘K*m*-Dת@~bSul &Y%s{ OH4-ǘ9dIP熍βc(넵>~س$DB|lk?Ոwzk* %BVޡSVK,<*cK$pȾ)>P.W\vO̎Ka!ɐk!UXqf*Uy:بh%4R0Pot8kːbpKuM`vnmi@#j:u.fubrgD?WN!w+C:$]:wp}0Զ!Y7Ԙ)8DkLn$Wy D[ù}Me/Z1}T+#Dqf@LC;$DD@`l=+spe,LU1T E\PI*y,VI__>M2;ST|q@1SBD:h>۴(K95: B?q: 1]퍴{kD˻8{= j?!I<Ȓ-IkMSaMQXI@y*ygbq|wpB)Vi) `jqF7O+G,v0D^d?J-.DΦ)z@ʂbw[[2F/j8W ,S^x|5k%`n4e>wOc{~BezF؏뢿4Ow`ⓑl('.29N! q)O= W 'Ǻ@YN_ Lt<Cj-#<8ш2,h-HY]2s@Ӂ ;QE|7MZ^ ;9"F4kYˢsrܾX>|&z<>"l׳4V1)/.Z <#9oGF_$/dT_˜]zUnb6R8~iԀ+CHx@3q5N9[Z=,b1q%z'xdĢՇjZt6Td%<ķZlc'~1$B/ex*뗕=劉ID)I9߳^$[}ҞSzaz~ 7o#u^J'N8q7RLL⬭1+8vv,8سȟ'x10|AlK]!aeN#\ܶ5SM츋fQۮmnEx'tF1liMNj~ i@|+IRwHTvX6Qַ4 zx*nϜͳjnB^{R<^SEkbJ_n>>h[<)Q_kY~6OFdR }{ wCT,n*?T0Ĕ0I&.+Id^b#ؑbZ1y 2*}wUNuFrJg?vcE$_n}t,lUxac*,@kk,!7ztl't+6ZpO A'~G$X)PDB&/.n8(I?KTrfThJ,*LB{B;+%dz:X2xk?LBOʉr˫`0m-z&9!JuD96;;Cì6$w$@INwT= '!1 h=dV*YE=ew?DoŠoӤ;oj -ނJYoTz󢀷|t߀nEVx - ,"禬1>5 &9\C ClMj!B%"f6;^T9]<>_9 YcOV"N\P&z;Ԝ}x6 tIWФNץ-`Ԛxu>jb8ҾhO\H슮m vq_ď9yVak7wa9%fe%yL\}̪'iR-~%4e5URNQE~pu⬨i[ZAԥAdvLjeBٓ~pͣ#~!rIH S'7Iu޴̀6.lXr| ;v-Τ|}Իye|qd|h_3l#wa)2/b?@iH}r eEnTM{s )B)KmCu%,0j PESo%7R;O @~4mN#VD_E3G~;7 XF.Οݟ[[&9氯Iy3A's|BGϫ;Ec&dR}D !7,`~,xAzn5F>bĚ?VKp:y܆p>B[ yjƭ5ɯ$TNc q~pdll2 rNLU-'8[O_0>i908]+풑':kA%ݦ"D@TS3}+'<&xZ>ār~s/!u^E?Mo㴵K~1Ol|UzyuONwu],ap5|f"}7s262Qjj˹ l{ȧ:gUBh>!qgڪN&w Cix+0dzm WztAO؋(Q^A.R6d?/=%Νgӡ[Pzyf_>.md \&⥙1?ro9ACd|O8R&h+`q-4F C, w4i4tNmtJKiyMYdؾyFͽ~V&T~]S1NSC䯢s|BOGlĺ^"+Y.O qK)j} 8ǡ*EL"(L砍,)]؛#ƶAR?cՆf(z[' *4Tś5!6 r0Eop\9*!yl ߋ1FR\UZn5=l+-DLY!2)N2`H v*V&Q3)Sg*iA7\98(yDƽkE|,XH[̈́_H|*q$$ZK>P*`dPz|Ss{#-K<lyRuXADW2Y{N2AװlJhG'_`mh CBE0.\`>c2SEb%:xJR@apc f=QZc pζ +Lc]㈇&86 咿7sGA% qp3[n`m]<{s]lZ+` `rt|&S맦I^RW2n(I fEu`]oUB^*m=?.S1-!  MG%]lPRȫ}˕*DX;hu܂Φ|V\̄1o^FRڙw$|$V z}..H[eϲu!5"7qoUJʩi'-cmȇ}} CT+M0àϢGcrN 2AGxJ>G$OB -Bj1'KaR8#B3vK.lg\:jz8՗\sS?z7Ie5+"`yV_Wy)# 1$ > NW]r&\{E!sUFRLO* 1ҳKkYSs)iˆמ#۶z/ yV _=(Oxճ66el|5wjtIqy/87H1i:4)AA~w\D{>JwdJԆV|m'[gEpk>%GHH%F1>CDMVjԵبUvԯ q-%{˷ې؆$,/H*TuL5t (Uė}`iw9Ui#VQŵ H9r?%t%b<˗qVN㰐{|hi?DZ/j5HuSlW, q5{\SL?1{̧_Z-+Cfpo2E0잶5lxXD\ԥDcS;+Yb YfR/j{ m\=ԋwpR0_Mc_YTQ2yп,YqjQ֒3$ SH_j6t{=zA!P$ p˟8 ` S<.^Yaݡ m:mq9DpE!9 \%R.t\T)Py T\H,]dJSReitYt > eDW_}ij2W*0OH#kSOiP 4 0ZL;~IDQ:/@9pD݅iLݑ+ZǓbEE_k6]6krru% g>o>M{O"R]Z'O*OB%"Uņ y9j~9݈=qOFjn';3}N%;ZĦe{C %yO_hz~uxe;G?ީn!&B]$~AɢVǔbEN 'Pw^ KPugL<[1.b )܎bxޏ?sYj^h{!=*3 )SAP$X /l1#AtGpuQ$s ~R":}Lsd#t@) ~od4H*@tXU?0,Dֱv̟Q y#j7 0Uz;r{֛۫*[V'0Q\_ `=s6|fTr/Ƈ7dna3!Ɋt;f-c _BGF>L/N)s0͡Upء Yjkb.ľ cnDmioATuY-f>pWF+|@>gc`/kf^',?utsHZҖaG\%l9$f-4Uq@y#ࣀa@x1o&w ა= =_g{kKiN9+aj|p=,D7Iw ak E^V>S1OuJ ["9*]I=3̼3V0yʑwL^WTctmKrz+5 x;(XuE4mQtuT4O 7Fټ<̡z0}@z4sW sUb&QɌf3 \p> ("|f1j8 {U.OnpUiD$sak|mּr4_Έ'Hz9Opa>ElPƗAv!j^_r#O1=m͂ϠX.05/&H&Rd0`/S"wN~`Z&/[q(y|?q,"m Zsyb/pw]JUB* G'0Wś> %˯xŚg.s(p5Su~3G\JQFK=BTd-,DkNk`~3Ps5pf,)+0a(Y|Sjk;Lau S77fv۽a'־@Up <ʙfB/=MbJ`q\WKpewc,40ASĮx$6!M|#k5>ia]QbN[@F~1ғ!Ɠ!)C( A'tN?\M` ,+(uNE}3=o9Ir4aDuJ#61MsPr!D?ԗ*E9=$)$ ք:%A\Q?Iq QurGV~zn~ʍ~U>fJ8#.8j~nJ'kjq`v]X8Ɯ wڅ$rD'jS!*{S\uFFp rޗ":06U@> {IOD~_n\)(1+z*!PI5)*vqyF12,IB(~X$8͘B[%FD6ڦ(^STkm,8kt;gs ] t^|S0?u7H< ,\Y!1Өybg_C4#w<ڲ@XC[l>mnϝ5(ê, 1  zS*)<?=+@ϴ@,$pQWC烣h)a#1iz2^j) J/8Ga|5QЕ\sN]!Q]\뽫ʜOԆ*rDq֐AA'qwD2+2(Cv^*>>jlNptoR=agIAu{ZXmŠȃx48 헔gotT1Zmdu3AAE ;c|  ~@HK ;Z Aݼ>φ"Jt W[@7~JY!x8n^5> ,]핗TvSnNܔP 9Vz^Zb,=VF |]56zm._SUZb׶=/< 'PĖZ6~Ӥ( $=oQuׂqÑJU"=D//d3H|AtgS_wyBDK494P#V\X (}XIidc2Q0FYR|(u#ƙ`99DYzpSWa\k6T4IRz~=Xs6q>.Yxŷ HU3 "{rq,gXj{\*=H)P#/6vrt16d] 6ـ7s.%lZE̽/(C'qOCr6KpB |$PNwN=[ NHQXx:`Mqms?>^;E~f&IT}l*ը8yYJ%AipKm&YkqQ$U=juT%U1cuϡ@pPڿH@YzN@U93斿ȣT1jX%ܻIn N8bi?nq¡@D*f/69X* v`x"4"ihBd`B|.k4YET'b1){,8FVd E(@g4s< $Z# lI$JB3f,K\pCrH#jN!pؔ wTt9'~nxBQ>.D4@L>}W&7@!i#/$c!ģ$׫7TntOOg}fcx)-Aϫ `3Sۣԣ邋2bk:D.0>SLetløgRFV,!?Ӂ@z C^ ]w}5%g޴^G^t o9oή7^(FBpwSxnV2pz;PyAhAL-xI" TgⓇ&gZ?,0=VmyWHjm &Q{U.ek<æs˞'׉̔EMsX80J&P,715WDxa{D\Zbu NKH`O4_dyLsOeaa*lgP~č2^7(\҃s E[Wo_hf1oF"<(lڈYcPY$06ŷS4.+DԲWuNDCJ6Z<˙у͜90ʎA b!¶MDI$AA*.5LZpf{Vmΰsx{֩{C>`f2[.nnNŘmpX2IhR/:VK"- _rtp*mZ&0WU<\(q:w87j/p93!BQj^lnE>0 ρ 9ξ*? +)vd 54fHemȐ68TҘ$^aLE΀VmcK!X~wNx^`l@8-AS]Oc ,O~)"+NPS4*zȅ,Mn?\Wh^XTCDLЬxv&^hŹbxX qht/sk=DYBQ!jF;{[l9/:#tQCD(AgemvKIW8] nQWyqd0 0>8gwM~݈VT1\a0:1' oEsp@j7zY9$Ln 4W1e۶߬tP}S?1x Q_BqCf~4ע٢ljM*l3!ika }6eoq#chM}gYHըHȘX'ӰLaAmi{ ;s,5oK_^)(.}^ŮD5vW}`;_tUgp vyJJU}*vWcEaZvmYm~S1( Ў%+qCΥ {' R`^̷ ㏸aMo7{_ oP[ΙavIKЀXB̩]KXJ A$/%VZ}t%#d֯]6Y ~NySqhLzYR b+޲/L; Ҏy\l=GOyJQaO{)r"56;YG\N[Tқ8ڦ|<k!#FixQ6U6e:Ճ۱%oxЇ!nzC|ܘu#Jx,={kN'{7e(G%g#ok@ɥ^[s9y]HlrMqrIdTVr n[e7}C9k8}Ko=$'ZrZTr+5;0*Ka\^U z6={I Dtc{K0u_-?鰫j/`-. nTj>nvsyhpRg-|f#8OD;錢]P>u.JAa\nFL-bٰ&e6DI͒M 7A¡kNhcgzN hT+\ҧDB}h[C|s:g{݋6[h mr+`?#΂:sRhlSK$Xvy0'V9Yfp{],=|T^ "]4sәODGtZOh7-;#Ņ Q/LFᎬ0;Ʉgѭ0ʋVr׽Oww [?A3ӧU4D6l娂ܮvso&3tvwJQc ^> MDR\9E zle j5Oe"nW>t,(](tX ?]S{8 s:"YY!hza#NpNDB)<>I34Qbb;h*uz^46B%uLdYVOVry4^:ȟDE5MC9-~ꁠG%]~}ʭOηUc1L_'Y6 5pJ[ "y3?&Q eo[@M/_cY!\E6ϴ0^\A ;0Qu9&Rb+rpowkk3Lh彉]oJ Y(s{ct2i o<`ʴa[D?u*Zf_sJ9R}`ze &O| Ȱg 9qcTՏp'V쪜J畾,K9h UPI'fv{s̸L\۴Sj4]הTq:vs<6B €⶜#T+ n(E[ҶDDfMvW1~l =}%>xɣ`oڋܐayJ,f@67`)~us>y|M殌&SSQh 4q,@uPN{Se*7vTcYw.&1ҳllˤv-Q"s7ΜI*? t^T'gJ_dEpyŐ FZ!e]/[!OJ+ҏl3)O\mh~j$=j }A'㽔Fyڕ>ªO; Z WQ@c,r&{f4IVYIpJ[`r6@eݱTz tK~Cܡvi=8GOɮXi>Ѡj@ԽæmA d#䵉"N;:/f ya:L3~ b>|h@R G 98ܣD]ogCrKa[3H XStK`BoX 2ڠIntlEZi\2+,$TȰPeʤύxH> CF b.28zfوyE 2S-<=D-~8Fd*{H[SuL'+Qĥ(5_gk0 [M|{b{@ `_cbah7fDP@ 3#ƈ,~b$%129C/aPGAB$;ak3w2S'^slx T| jX4͈`2v=Qo A-W',L-p* ѝp;W} 5܇Q‡<%lә:N'ʢڇF E1hJ41k\C59 #a^akWE@܍ 1xy!~Dcv3Ov(F(4 z3i9P|(qFKnq(΋4 #Oog'%l:t?'w&_`,BvpFmE\^笉1VUY=EdE|2GE̷3_ Eb^+1 |{ 8)z?;<.hP&g%`&qV*Eiتͷ1mS)Wˉ_6`"?O >7fQ6^>4!RHɊbaF}Cv=O̦3)B !z5%J5<=r }# ZRS X(9p Qt1&W@> q;SyQf<Ģ>[y3uXC[vszX9]e}1^3"3-Kb[XPIP4&id+zkݽ')UPJ<޿?Efԕ]ePYrZ=v*hюRUs]u.|n GK렌ȹZKH!wGgpH"^,vۈk {lR0zNaoMg ClNA#>RuA\2*= ᇕx 9ױ [ƌNzcsT*mtT)gJ$ݢ뀮5BHYgߧ _o,x> .א:0!^9}J쌬H1N86S#V{.ˆCq#0x8IF5]X}ߔ!&X 4T_$+|e }ѥ5HyK)}NW*%3`ޓJX{8A-eg qr!θEW Ʋe26,LaI+=`=-bF~!zDk1ĵlվ/ ibo =JN~n[;8 ]aOa:a>Ftmp$H6x_0iMN>&նuH7>X+I'A&z9[iS̭"OFgWezoxyd~X!Yz%[x4!۵CՌ8Ygp\ZALZ2noJ6Ė͵ e̠.'*2~c5+Gɟl7K *Sp"I~.L7:RE (SHy:Et7WV~KD na4{>ޜ/Y7w9sn82ǘV0mǺHݘ$)֒8m]q9Κj;__dDҺw+.خ ur?cj/lT3Q`7^xd")}֊ &QT.%o"*(|6߱?ovoU&^9}gi ͫA3y3g2Bぬz YBVFDzr(Wmys]5Gi׭#Zr PJQ{ZL}xO `\=!fzf06ߵ7c>M(fymI)qu]v'&6Tn`P]/S!Br=^筓X:BN*W/~;mϱE+&@-戕h0 *IH.ucHJA IgƦ b0 gSIlj s Z{f-8&ܰ^<(팘㪨!|LONdJy)̸-8rz#X@H5T)"j^")Sbr3F V'Pw/7Yi!*JABP:5-F>37f`'DmQ-Fq&k(PxetWӝgȣE7\T#o.2~7+OH4^C^ghKOdDd\k7nSg;%cJBhKCYIjqD6doPT. p|^Y;1k^},7tW6Q>e47j|uUOr,9|8m͵*ߍѽH"r gIÓ:t̫.妞w`Œ!k ͅ!V+2.2Pbq e)7AmHvbHTvlha%z/ Ɲ!Z`cK1HEjy}zB; O߆[z;"Mka.Ȅ˱c+#0KJb7Hv*4a-\~P2Dcnӷ=ï7%3AKɰP~ N0VU!ڀHbk-5jhV’SJDW ?O{q=A7EGe:V[:K]I7KZ E> hIM*?50Slz0Wxl Y*>=C^}/Hd7"WAO7 ]lj|)+7q*7qMeVL޳< % N@J@'FJ0lPuVQt' Dc^_r;=:sd\@^a,)~~ E<1v4meR} Bh:r֓B=2 h  >2 ]"<;H}nvicߵM :O`.D҈E)FTyS575sk7ֻocڤfC)҄rC˗y;RQʥD82_\-Q}1$c(&|/D漊 '#wo\{Q]4$\md-^Xq[IyBbv1M->L\uPE{nYqI1`>Xq`ЉwT/*bp{}~lpGc%17U-\YnL[BZߒe rC.P&@㓩>,/Yϝt]EH*̈?\,ZW_)spbdd4Ư$ހn֣mCiZ@>FddLju=傂ҙ >3'sN 廢.A!,пR=q/pt?Y|G4 e$cw"`/T!|a"PiWprSljg 2r"U%-Su8y+yZS|lEN 2cqFU]փi$έuZ# >XXIF }Vc|{$߱f D%U 얇 wd;ܒ(e[;12"[wt1_i$tmVgC%,q+#A<35Ig و\K':=Dw,2dj mu(1L@J9/xPf͕]y޺4 aiv8㎃ҴAۿc? m_#VQ`]"-/ )m}K | r1)vgrPEjsv*0=z2ll*o'i bq$Bn%yո/Sc3+<<IҨ"zL+E)Ό`^[!$5GRzD7u(H$#FhoQ1oE&GwMȷC쪕U޻E+"/x@h熌L:vtTE]Rm`%pwFᆵ ά}eW*zXKI(s vyRȎ|7 %Yc<LH0IF?HI2f~T?{g^p=*h~U"e'^"(5f |G`8c6LʖE\/^17ΉCFѹ'л'1Ϛ1#G}oɕi@.I?;B{PPz`-Ɇh$-pG€HkJMko/pș8NMLs2.Ih5>o]% 4 q TnO$< 9N(4ySk ]\A1I"5i51c7nߡ"vng'fa=+e]04]O׆ ?v$a "v9t( ~M 2]5!Ul= \@u`{{V%0/k9 4Rk5ljE>˜l/l'FVҀt _0K] :ظDcߤv'lx 1/]zGǕ^@+} 16UԱlJעY B 8!y_ȧ!Eh6}4_]#wt?0#pپ 'aa8ٶmz耞=57[lMf:/y^$}65gU)B!^UMR[݈A}{ `|34`H'+@iG| r+KVAԌ|JjU= z!@ V݈u;LA&=l]UtOcJ>JO#=L*A2C;mGrp}]'/ˆs~sګE`!d#+UKX;6MID147AL+)wC@_?*| zK}HG[4'AEOf?I _ fIGn;RŠpMA F Ii)CPJ( Yffz6%$78isXԫ|](srb(5Es?~qR\O4YFxA)2@m-M }@Q}0M",@VIYzc}> ӟ9$9כ'4w ~ yV6W)u|'Tf6w;jdw] f[t7dh^D*L8 O,2T~WljV ޯi4_oNu{6IwW/ N4 /E 5!kɻFIT`5b R]WZO/$ܛ0h/9U Tpbv?<]!ly<8v RDQtqޯ[BmO-[@d;-2TkU!h63ʚ45 U@+R$v@n؝p).yΎMCmˬJ}8Ze /xJ,R?_փaEũq84=kUh|J☦"!ի΀L)'u0]>w7Yp6 !eQvr 8>jχ*m/`M()o8;EK&yܬCOi`K/:N g-J2>ʢjK*ayl]22&J;yY aفk@P֎]Xj0i6o|jo/ڔGȐȦMV3vٴ/&tѣ-+Wu\1^JsN-%۴YJYmpŻɊ4ˌP>=yit[_oޤW)UPDk{Zy0ӯXDKuB4O h Fnb) {f!҄N!D'Mw BBL%Eҥ1s#IHG21V8~p`6O\SnH9jq%iB> `1;B Mم#,x\6w rp=U؏^vI\.(ǃ&*9̎н;!1F3oV%aAδ jx]^WflkJ%<\[C  :wm\X܀s8]\u-âjW+kթ5ѲQ=B=p16JkҚsYW@%r._GDH('DI%kP~ l6rúBl[*Y+9IEB,KpO籤 A8NvTygLEPqzh @ Gqd~99|69qVq:,9CO%ۊ1%6j摺3-e/R/=Z.#"Tf#d>.3%_5Y+NNhsg2_矜سp 9<㦥òOb}i.h' 1M!b.oo63;LŽ^pd88pEVERFŇŠ1C@u5(GLPDEkՀ=ҥW1tP?*p~$%l])ĺv]0D#DNs3mJ'<#t3Fly 6חYf±2! X1u5Z",)/:̅/# GZ>RXG/(ݩUqk-I/c 'gtx5 |+(nX%ǎQFI\V52{ U'cl$d$lںnMnگWP;L0b>u!5wj$yʯOrQ6J"ߥd{=**Y›tGz4C`ܟ (PAFҋ4{jUREfc&y[_Y}2Y#n[7[3rҋFi(PׄM0u:;Đhμ 7C6L +zރ<` vc:~*e[ɚqFWkIe{zu2j9r齃$W9d #a K/x5yϽ|x xUI&wgϞjD@VuOɲ=3 e~F Ha9}-2}4ngV؁L`mzpWw9}W!ӻT-fw$ξZ}T|$+{ g 8g`(`-ěGckyVY76 B`z dEVs5TAnƍ*NRܽvKWg*sgv2uf)՝Xf5jdT9:Fk룡,y?љ >h< pb.df YvRXcz&i -6AJD.D"r7(8|ef}Y?@"|5#mI֧L)6P?*ueERɘ3lm!1QB(71"m$޳\j9qD礅4=&cA'?|-qR`ɪunH<~y&*"Y1aF+J"a'r%i>߾rx{!k!sZcȡ6̚Ll2Rw6x,9j<<,ߣ 4|ӲE_V|OM+.^ Yju;o> }6US2ӖS"gHh &-xqp:ySS /e741}ihcFV 5$ 2PAFeKr}E /b6 K㷠)ԉj5 7#vW~̛z[{煮EvLVȩ+NJ:nЊX-HX>yhx6T/LBߺOe+w;7!uRT(yl&TEgZ3$BsΤB6&Θ4w8ID;%&u3%G|%@]~U^$:zl֎gCIx~Xp '{\pKLvGB{ux2~Pd[87ŘA-+f̩PV}9ج}a[Yԑ=| Dz:ä{P4J[EB`XȰ.LZaiO;`JAqM7ݴ?dC\+ щMS[r[b,-T^?k{Qsծ "u&ԔaG$8d8rSeۏ[ck: ͮPn+PMQo1Ү;}<եZ PWI(0Vq^Pi\Եh1jX; OFPQYC֪Q1i}GFAl+2'݊b `Js!;)Wި F&n TwԒ0_q~y!z_f_ `y&Ӧ<'C,>7΃V}R\;5LLUe%0grp%/,Y(y۞{ԛ(뿴ͬk1W҈ zI ԁXc-kzz\J3p?ydh"VlE>\Pv"-B~f OL>r8:X':xA$ֶ)AZѧ j('#'gr;wsa=l0B$䥱CKf X=FI Cvq7j7EOͱC?au7[!ү [ƘSAWɌxG{h!-iv