function EditHoliday() { global $txt, $context, $scripturl, $smcFunc; loadAdminTemplate('ManageCalendar'); $context['is_new'] = !isset($_REQUEST['holiday']); $context['page_title'] = $context['is_new'] ? $txt['holidays_add'] : $txt['holidays_edit']; $context['sub_template'] = 'edit_holiday'; // Cast this for safety... if (isset($_REQUEST['holiday'])) { $_REQUEST['holiday'] = (int) $_REQUEST['holiday']; } // Submitting? if (isset($_POST[$context['session_var']]) && (isset($_REQUEST['delete']) || $_REQUEST['title'] != '')) { checkSession(); // Not too long good sir? $_REQUEST['title'] = commonAPI::substr($_REQUEST['title'], 0, 60); $_REQUEST['holiday'] = isset($_REQUEST['holiday']) ? (int) $_REQUEST['holiday'] : 0; if (isset($_REQUEST['delete'])) { smf_db_query(' DELETE FROM {db_prefix}calendar_holidays WHERE id_holiday = {int:selected_holiday}', array('selected_holiday' => $_REQUEST['holiday'])); } else { $date = strftime($_REQUEST['year'] <= 4 ? '0004-%m-%d' : '%Y-%m-%d', mktime(0, 0, 0, $_REQUEST['month'], $_REQUEST['day'], $_REQUEST['year'])); if (isset($_REQUEST['edit'])) { smf_db_query(' UPDATE {db_prefix}calendar_holidays SET event_date = {date:holiday_date}, title = {string:holiday_title} WHERE id_holiday = {int:selected_holiday}', array('holiday_date' => $date, 'selected_holiday' => $_REQUEST['holiday'], 'holiday_title' => $_REQUEST['title'])); } else { smf_db_insert('', '{db_prefix}calendar_holidays', array('event_date' => 'date', 'title' => 'string-60'), array($date, $_REQUEST['title']), array('id_holiday')); } } updateSettings(array('calendar_updated' => time())); redirectexit('action=admin;area=managecalendar;sa=holidays'); } // Default states... if ($context['is_new']) { $context['holiday'] = array('id' => 0, 'day' => date('d'), 'month' => date('m'), 'year' => '0000', 'title' => ''); } else { $request = smf_db_query(' SELECT id_holiday, YEAR(event_date) AS year, MONTH(event_date) AS month, DAYOFMONTH(event_date) AS day, title FROM {db_prefix}calendar_holidays WHERE id_holiday = {int:selected_holiday} LIMIT 1', array('selected_holiday' => $_REQUEST['holiday'])); while ($row = mysql_fetch_assoc($request)) { $context['holiday'] = array('id' => $row['id_holiday'], 'day' => $row['day'], 'month' => $row['month'], 'year' => $row['year'] <= 4 ? 0 : $row['year'], 'title' => $row['title']); } mysql_free_result($request); } // Last day for the drop down? $context['holiday']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['holiday']['month'] == 12 ? 1 : $context['holiday']['month'] + 1, 0, $context['holiday']['month'] == 12 ? $context['holiday']['year'] + 1 : $context['holiday']['year'])); }
/** * Save a new draft, or update an existing draft. */ function saveDraft() { global $smcFunc, $topic, $board, $user_info, $options; if (!isset($_REQUEST['draft']) || $user_info['is_guest'] || empty($options['use_drafts'])) { return false; } $msgid = isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0; // Clean up what we may or may not have $subject = isset($_POST['subject']) ? $_POST['subject'] : ''; $message = isset($_POST['message']) ? $_POST['message'] : ''; $icon = isset($_POST['icon']) ? preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']) : 'xx'; // Sanitise what we do have $subject = commonAPI::htmltrim(commonAPI::htmlspecialchars($subject)); $message = commonAPI::htmlspecialchars($message, ENT_QUOTES); preparsecode($message); if (commonAPI::htmltrim(commonAPI::htmlspecialchars($subject)) === '' && commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message']), ENT_QUOTES) === '') { fatal_lang_error('empty_draft', false); } // Hrm, so is this a new draft or not? if (isset($_REQUEST['draft_id']) && (int) $_REQUEST['draft_id'] > 0 || $msgid) { $_REQUEST['draft_id'] = (int) $_REQUEST['draft_id']; $id_cond = $msgid ? ' 1=1 ' : ' id_draft = {int:draft} '; $id_sel = $msgid ? ' AND id_msg = {int:message} ' : ' AND id_board = {int:board} AND id_topic = {int:topic} '; // Does this draft exist? smf_db_query(' UPDATE {db_prefix}drafts SET subject = {string:subject}, body = {string:body}, updated = {int:post_time}, icon = {string:post_icon}, smileys = {int:smileys_enabled}, is_locked = {int:locked}, is_sticky = {int:sticky} WHERE ' . $id_cond . ' AND id_member = {int:member} ' . $id_sel . ' LIMIT 1', array('draft' => $_REQUEST['draft_id'], 'board' => $board, 'topic' => $topic, 'message' => $msgid, 'member' => $user_info['id'], 'subject' => $subject, 'body' => $message, 'post_time' => time(), 'post_icon' => $icon, 'smileys_enabled' => !isset($_POST['ns']) ? 1 : 0, 'locked' => !empty($_POST['lock_draft']) ? 1 : 0, 'sticky' => isset($_POST['sticky']) ? 1 : 0)); if (smf_db_affected_rows() != 0) { return $_REQUEST['draft_id']; } } smf_db_insert('insert', '{db_prefix}drafts', array('id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'id_member' => 'int', 'subject' => 'string', 'body' => 'string', 'updated' => 'int', 'icon' => 'string', 'smileys' => 'int', 'is_locked' => 'int', 'is_sticky' => 'int'), array($board, $topic, $msgid, $user_info['id'], $subject, $message, time(), $icon, !isset($_POST['ns']) ? 1 : 0, !empty($_POST['lock_draft']) ? 1 : 0, isset($_POST['sticky']) ? 1 : 0), array('id_draft')); return smf_db_insert_id('{db_prefix}drafts'); }
function getLastPosts($latestPostOptions) { global $scripturl, $txt, $user_info, $modSettings, $smcFunc, $context; // Find all the posts. Newer ones will have higher IDs. (assuming the last 20 * number are accessable...) // !!!SLOW This query is now slow, NEEDS to be fixed. Maybe break into two? $request = smf_db_query(' SELECT m.poster_time, m.subject, m.id_topic, m.id_member, m.id_msg, b.name, m1.subject AS first_subject, IFNULL(mem.real_name, m.poster_name) AS poster_name, t.id_board, b.name AS board_name, SUBSTRING(m.body, 1, 385) AS body, m.smileys_enabled FROM {db_prefix}messages AS m INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) INNER JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg) LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) WHERE m.id_msg >= {int:likely_max_msg}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' AND b.id_board != {int:recycle_board}' : '') . ' AND {query_wanna_see_board}' . ($modSettings['postmod_active'] ? ' AND t.approved = {int:is_approved} AND m.approved = {int:is_approved}' : '') . ' ORDER BY m.id_msg DESC LIMIT ' . $latestPostOptions['number_posts'], array('likely_max_msg' => max(0, $modSettings['maxMsgID'] - 50 * $latestPostOptions['number_posts']), 'recycle_board' => $modSettings['recycle_board'], 'is_approved' => 1)); $posts = array(); while ($row = mysql_fetch_assoc($request)) { // Censor the subject and post for the preview ;). censorText($row['subject']); censorText($row['body']); $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']), array('<br />' => ' '))); if (commonAPI::strlen($row['body']) > 128) { $row['body'] = commonAPI::substr($row['body'], 0, 128) . '...'; } $bhref = URL::board($row['id_board'], $row['board_name'], 0, true); $mhref = URL::user($row['id_member'], $row['poster_name']); $thref = URL::topic($row['id_topic'], $row['first_subject'], 0, false, '.msg' . $row['id_msg'], ';topicseen#msg' . $row['id_msg']); // Build the array. $posts[] = array('board' => array('id' => $row['id_board'], 'name' => $row['board_name'], 'href' => $bhref, 'link' => '<a href="' . $bhref . '">' . $row['board_name'] . '</a>'), 'topic' => $row['id_topic'], 'poster' => array('id' => $row['id_member'], 'name' => $row['poster_name'], 'href' => empty($row['id_member']) ? '' : $mhref, 'link' => empty($row['id_member']) ? $row['poster_name'] : '<a href="' . $mhref . '">' . $row['poster_name'] . '</a>'), 'subject' => $row['subject'], 'short_subject' => shorten_subject($row['subject'], 35), 'preview' => $row['body'], 'time' => timeformat($row['poster_time']), 'timestamp' => forum_time(true, $row['poster_time']), 'raw_timestamp' => $row['poster_time'], 'href' => $thref, 'link' => '<a href="' . $thref . '" rel="nofollow">' . $row['first_subject'] . '</a>'); } mysql_free_result($request); return $posts; }
function getLanguages($use_cache = true, $favor_utf8 = true) { global $context, $settings, $modSettings; // Either we don't use the cache, or its expired. if (!$use_cache || ($context['languages'] = CacheAPI::getCache('known_languages' . ($favor_utf8 ? '' : '_all'), !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600)) == null) { // If we don't have our theme information yet, lets get it. if (empty($settings['default_theme_dir'])) { loadTheme(0, false); } else { $settings['actual_theme_url'] = $settings['theme_url']; $settings['actual_images_url'] = $settings['images_url']; $settings['actual_theme_dir'] = $settings['theme_dir']; } // Default language directories to try. $language_directories = array($settings['default_theme_dir'] . '/languages', $settings['actual_theme_dir'] . '/languages'); // We possibly have a base theme directory. if (!empty($settings['base_theme_dir'])) { $language_directories[] = $settings['base_theme_dir'] . '/languages'; } // Remove any duplicates. $language_directories = array_unique($language_directories); foreach ($language_directories as $language_dir) { // Can't look in here... doesn't exist! if (!file_exists($language_dir)) { continue; } $dir = dir($language_dir); while ($entry = $dir->read()) { // Look for the index language file.... if (!preg_match('~^index\\.(.+)\\.php$~', $entry, $matches)) { continue; } $context['languages'][$matches[1]] = array('name' => commonAPI::ucwords(strtr($matches[1], array('_' => ' '))), 'selected' => false, 'filename' => $matches[1], 'location' => $language_dir . '/index.' . $matches[1] . '.php'); } $dir->close(); } // Favoring UTF8? Then prevent us from selecting non-UTF8 versions. if ($favor_utf8) { foreach ($context['languages'] as $lang) { if (substr($lang['filename'], strlen($lang['filename']) - 5, 5) != '-utf8' && isset($context['languages'][$lang['filename'] . '-utf8'])) { unset($context['languages'][$lang['filename']]); } } } // Lets cash in on this deal. if (!empty($modSettings['cache_enable'])) { CacheAPI::putCache('known_languages' . ($favor_utf8 ? '' : '_all'), $context['languages'], !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); } } return $context['languages']; }
function PackageServerAdd() { global $smcFunc; // Validate the user. checkSession(); // If they put a slash on the end, get rid of it. if (substr($_POST['serverurl'], -1) == '/') { $_POST['serverurl'] = substr($_POST['serverurl'], 0, -1); } // Are they both nice and clean? $servername = trim(commonAPI::htmlspecialchars($_POST['servername'])); $serverurl = trim(commonAPI::htmlspecialchars($_POST['serverurl'])); // Make sure the URL has the correct prefix. if (strpos($serverurl, 'http://') !== 0 && strpos($serverurl, 'https://') !== 0) { $serverurl = 'http://' . $serverurl; } smf_db_insert('', '{db_prefix}package_servers', array('name' => 'string-255', 'url' => 'string-255'), array($servername, $serverurl), array('id_server')); redirectexit('action=admin;area=packages;get'); }
function __construct($request, $total_items, $not_profile = false) { global $context, $txt, $user_info, $scripturl, $options, $memberContext, $modSettings; if (!isset($context['pageindex_multiplier'])) { $context['pageindex_multiplier'] = commonAPI::getMessagesPerPage(); } $cb_name = isset($context['cb_name']) ? $context['cb_name'] : 'topics[]'; while ($row = mysql_fetch_assoc($request)) { censorText($row['subject']); $this->topic_ids[] = $row['id_topic']; $f_post_mem_href = !empty($row['id_member']) ? URL::user($row['id_member'], $row['first_member_name']) : ''; $t_href = URL::topic($row['id_topic'], $row['subject'], 0); $l_post_mem_href = !empty($row['id_member_updated']) ? URL::user($row['id_member_updated'], $row['last_real_name']) : ''; $l_post_msg_href = URL::topic($row['id_topic'], $row['last_subject'], $user_info['is_guest'] ? !empty($options['view_newest_first']) ? 0 : (int) ($row['num_replies'] / $context['pageindex_multiplier']) * $context['pageindex_multiplier'] : 0, $user_info['is_guest'] ? true : false, $user_info['is_guest'] ? '' : '.msg' . $row['id_last_msg'], $user_info['is_guest'] ? '#msg' . $row['id_last_msg'] : '#new'); $this->topiclist[$row['id_topic']] = array('id' => $row['id_topic'], 'id_member_started' => empty($row['id_member']) ? 0 : $row['id_member'], 'first_post' => array('id' => $row['id_first_msg'], 'member' => array('username' => $row['first_member_name'], 'name' => $row['first_member_name'], 'id' => empty($row['id_member']) ? 0 : $row['id_member'], 'href' => $f_post_mem_href, 'link' => !empty($row['id_member']) ? '<a onclick="getMcard(' . $row['id_member'] . ', $(this));return(false);" href="' . $f_post_mem_href . '" title="' . $txt['profile_of'] . ' ' . $row['first_member_name'] . '">' . $row['first_member_name'] . '</a>' : $row['first_member_name']), 'time' => timeformat($row['first_poster_time']), 'timestamp' => forum_time(true, $row['first_poster_time']), 'subject' => $row['subject'], 'icon' => $row['first_icon'], 'icon_url' => getPostIcon($row['first_icon']), 'href' => $t_href, 'link' => '<a href="' . $t_href . '">' . $row['subject'] . '</a>'), 'last_post' => array('id' => $row['id_last_msg'], 'member' => array('username' => $row['last_real_name'], 'name' => $row['last_real_name'], 'id' => $row['id_member_updated'], 'href' => $l_post_mem_href, 'link' => !empty($row['id_member_updated']) ? '<a onclick="getMcard(' . $row['id_member_updated'] . ', $(this));return(false);" href="' . $l_post_mem_href . '">' . $row['last_real_name'] . '</a>' : $row['last_real_name']), 'time' => timeformat($row['last_post_time']), 'timestamp' => forum_time(true, $row['last_post_time']), 'subject' => $row['last_subject'], 'href' => $l_post_msg_href, 'link' => '<a href="' . $l_post_msg_href . ($row['num_replies'] == 0 ? '' : ' rel="nofollow"') . '>' . $row['last_subject'] . '</a>'), 'checkbox_name' => $cb_name, 'subject' => $row['subject'], 'new' => $row['new_from'] <= $row['id_msg_modified'], 'new_from' => $row['new_from'], 'newtime' => $row['new_from'], 'updated' => timeformat($row['poster_time']), 'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new', 'new_link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new">' . $row['subject'] . '</a>', 'replies' => comma_format($row['num_replies']), 'views' => comma_format($row['num_views']), 'approved' => $row['approved'], 'unapproved_posts' => $row['unapproved_posts'], 'is_old' => !empty($modSettings['oldTopicDays']) ? $context['time_now'] - $row['last_post_time'] > $modSettings['oldTopicDays'] * 86400 : false, 'is_posted_in' => false, 'prefix' => '', 'pages' => '', 'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($row['is_sticky']), 'is_locked' => !empty($row['locked']), 'is_poll' => false, 'is_hot' => $row['num_replies'] >= $modSettings['hotTopicPosts'], 'is_very_hot' => $row['num_replies'] >= $modSettings['hotTopicVeryPosts'], 'board' => isset($row['id_board']) && !empty($row['id_board']) ? array('name' => $row['board_name'], 'id' => $row['id_board'], 'href' => URL::board($row['id_board'], $row['board_name'])) : array('name' => '', 'id' => 0, 'href' => '')); determineTopicClass($this->topiclist[$row['id_topic']]); if (!empty($row['id_member']) && ($row['id_member'] != $user_info['id'] || $not_profile)) { $this->users_to_load[$row['id_member']] = $row['id_member']; } } loadMemberData($this->users_to_load); foreach ($this->topiclist as &$topic) { if (!isset($memberContext[$topic['id_member_started']])) { loadMemberContext($topic['id_member_started']); } $topic['first_post']['member']['avatar'] =& $memberContext[$topic['id_member_started']]['avatar']['image']; } // figure out whether we have posted in a topic (but only if we are not the topic starter) if (!empty($modSettings['enableParticipation']) && !$user_info['is_guest'] && !empty($this->topic_ids)) { $result = smf_db_query(' SELECT id_topic FROM {db_prefix}messages WHERE id_topic IN ({array_int:topic_list}) AND id_member = {int:current_member} GROUP BY id_topic LIMIT ' . count($this->topic_ids), array('current_member' => $user_info['id'], 'topic_list' => $this->topic_ids)); while ($row = mysql_fetch_assoc($result)) { if ($this->topiclist[$row['id_topic']]['first_post']['member']['id'] != $user_info['id']) { $this->topiclist[$row['id_topic']]['is_posted_in'] = true; } } mysql_free_result($result); } }
function isReservedName($name, $current_ID_MEMBER = 0, $is_name = true, $fatal = true) { global $modSettings, $context; // No cheating with entities please. $replaceEntities = create_function('$string', ' $num = substr($string, 0, 1) === \'x\' ? hexdec(substr($string, 1)) : (int) $string; if ($num === 0x202E || $num === 0x202D) return \'\'; if (in_array($num, array(0x22, 0x26, 0x27, 0x3C, 0x3E))) return \'&#\' . $num . \';\';' . 'return $num < 0x20 || $num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) ? \'\' : ($num < 0x80 ? chr($num) : ($num < 0x800 ? chr(192 | $num >> 6) . chr(128 | $num & 63) : ($num < 0x10000 ? chr(224 | $num >> 12) . chr(128 | $num >> 6 & 63) . chr(128 | $num & 63) : chr(240 | $num >> 18) . chr(128 | $num >> 12 & 63) . chr(128 | $num >> 6 & 63) . chr(128 | $num & 63))));'); $name = preg_replace('~(&#(\\d{1,7}|x[0-9a-fA-F]{1,6});)~e', '$replaceEntities(\'\\2\')', $name); $checkName = commonAPI::strtolower($name); // Administrators are never restricted ;). if (!allowedTo('moderate_forum') && (!empty($modSettings['reserveName']) && $is_name || !empty($modSettings['reserveUser']) && !$is_name)) { $reservedNames = explode("\n", $modSettings['reserveNames']); // Case sensitive check? $checkMe = empty($modSettings['reserveCase']) ? $checkName : $name; // Check each name in the list... foreach ($reservedNames as $reserved) { if ($reserved == '') { continue; } // The admin might've used entities too, level the playing field. $reservedCheck = preg_replace('~(&#(\\d{1,7}|x[0-9a-fA-F]{1,6});)~e', '$replaceEntities(\'\\2\')', $reserved); // Case sensitive name? if (empty($modSettings['reserveCase'])) { $reservedCheck = commonAPI::strtolower($reservedCheck); } // If it's not just entire word, check for it in there somewhere... if ($checkMe == $reservedCheck || commonAPI::strpos($checkMe, $reservedCheck) !== false && empty($modSettings['reserveWord'])) { if ($fatal) { fatal_lang_error('username_reserved', 'password', array($reserved)); } else { return true; } } } $censor_name = $name; if (censorText($censor_name) != $name) { if ($fatal) { fatal_lang_error('name_censored', 'password', array($name)); } else { return true; } } } // Characters we just shouldn't allow, regardless. foreach (array('*') as $char) { if (strpos($checkName, $char) !== false) { if ($fatal) { fatal_lang_error('username_reserved', 'password', array($char)); } else { return true; } } } // Get rid of any SQL parts of the reserved name... $checkName = strtr($name, array('_' => '\\_', '%' => '\\%')); // Make sure they don't want someone else's name. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE ' . (empty($current_ID_MEMBER) ? '' : 'id_member != {int:current_member} AND ') . '(real_name LIKE {string:check_name} OR member_name LIKE {string:check_name}) LIMIT 1', array('current_member' => $current_ID_MEMBER, 'check_name' => $checkName)); if (mysql_num_rows($request) > 0) { mysql_free_result($request); return true; } // Does name case insensitive match a member group name? $request = smf_db_query(' SELECT id_group FROM {db_prefix}membergroups WHERE group_name LIKE {string:check_name} LIMIT 1', array('check_name' => $checkName)); if (mysql_num_rows($request) > 0) { mysql_free_result($request); return true; } // Okay, they passed. return false; }
function sendpm($recipients, $subject, $message, $store_outbox = false, $from = null, $pm_head = 0) { global $scripturl, $txt, $user_info, $language; global $modSettings, $sourcedir; // Make sure the PM language file is loaded, we might need something out of it. loadLanguage('PersonalMessage'); $onBehalf = $from !== null; // Initialize log array. $log = array('failed' => array(), 'sent' => array()); if ($from === null) { $from = array('id' => $user_info['id'], 'name' => $user_info['name'], 'username' => $user_info['username']); } else { $user_info['name'] = $from['name']; } // This is the one that will go in their inbox. $htmlmessage = commonAPI::htmlspecialchars($message, ENT_QUOTES); $htmlsubject = commonAPI::htmlspecialchars($subject); preparsecode($htmlmessage); // Integrated PMs HookAPI::callHook('integrate_personal_message', array($recipients, $from['username'], $subject, $message)); // Get a list of usernames and convert them to IDs. $usernames = array(); foreach ($recipients as $rec_type => $rec) { foreach ($rec as $id => $member) { if (!is_numeric($recipients[$rec_type][$id])) { //$recipients[$rec_type][$id] = commonAPI::strtolower(trim(preg_replace('/[<>&"\'=\\\]/', '', $recipients[$rec_type][$id]))); $recipients[$rec_type][$id] = commonAPI::strtolower(trim(preg_replace('/[<>&"\'=\\]/', '', $recipients[$rec_type][$id]))); $usernames[$recipients[$rec_type][$id]] = 0; } } } if (!empty($usernames)) { $request = smf_db_query(' SELECT id_member, member_name FROM {db_prefix}members WHERE ' . 'member_name' . ' IN ({array_string:usernames})', array('usernames' => array_keys($usernames))); while ($row = mysql_fetch_assoc($request)) { if (isset($usernames[commonAPI::strtolower($row['member_name'])])) { $usernames[commonAPI::strtolower($row['member_name'])] = $row['id_member']; } } mysql_free_result($request); // Replace the usernames with IDs. Drop usernames that couldn't be found. foreach ($recipients as $rec_type => $rec) { foreach ($rec as $id => $member) { if (is_numeric($recipients[$rec_type][$id])) { continue; } if (!empty($usernames[$member])) { $recipients[$rec_type][$id] = $usernames[$member]; } else { $log['failed'][$id] = sprintf($txt['pm_error_user_not_found'], $recipients[$rec_type][$id]); unset($recipients[$rec_type][$id]); } } } } // Make sure there are no duplicate 'to' members. $recipients['to'] = array_unique($recipients['to']); // Only 'bcc' members that aren't already in 'to'. $recipients['bcc'] = array_diff(array_unique($recipients['bcc']), $recipients['to']); // Combine 'to' and 'bcc' recipients. $all_to = array_merge($recipients['to'], $recipients['bcc']); // Check no-one will want it deleted right away! $request = smf_db_query(' SELECT id_member, criteria, is_or FROM {db_prefix}pm_rules WHERE id_member IN ({array_int:to_members}) AND delete_pm = {int:delete_pm}', array('to_members' => $all_to, 'delete_pm' => 1)); $deletes = array(); // Check whether we have to apply anything... while ($row = mysql_fetch_assoc($request)) { $criteria = unserialize($row['criteria']); // Note we don't check the buddy status, cause deletion from buddy = madness! $delete = false; foreach ($criteria as $criterium) { $match = false; if ($criterium['t'] == 'mid' && $criterium['v'] == $from['id'] || $criterium['t'] == 'gid' && in_array($criterium['v'], $user_info['groups']) || $criterium['t'] == 'sub' && strpos($subject, $criterium['v']) !== false || $criterium['t'] == 'msg' && strpos($message, $criterium['v']) !== false) { $delete = true; } elseif (!$row['is_or']) { $delete = false; break; } } if ($delete) { $deletes[$row['id_member']] = 1; } } mysql_free_result($request); // Load the membergrounp message limits. //!!! Consider caching this? static $message_limit_cache = array(); if (!allowedTo('moderate_forum') && empty($message_limit_cache)) { $request = smf_db_query(' SELECT id_group, max_messages FROM {db_prefix}membergroups', array()); while ($row = mysql_fetch_assoc($request)) { $message_limit_cache[$row['id_group']] = $row['max_messages']; } mysql_free_result($request); } // Load the groups that are allowed to read PMs. $allowed_groups = array(); $disallowed_groups = array(); $request = smf_db_query(' SELECT id_group, add_deny FROM {db_prefix}permissions WHERE permission = {string:read_permission}', array('read_permission' => 'pm_read')); while ($row = mysql_fetch_assoc($request)) { if (empty($row['add_deny'])) { $disallowed_groups[] = $row['id_group']; } else { $allowed_groups[] = $row['id_group']; } } mysql_free_result($request); if (empty($modSettings['permission_enable_deny'])) { $disallowed_groups = array(); } $request = smf_db_query(' SELECT member_name, real_name, id_member, email_address, lngfile, pm_email_notify, instant_messages,' . (allowedTo('moderate_forum') ? ' 0' : ' (pm_receive_from = {int:admins_only}' . (empty($modSettings['enable_buddylist']) ? '' : ' OR (pm_receive_from = {int:buddies_only} AND FIND_IN_SET({string:from_id}, buddy_list) = 0) OR (pm_receive_from = {int:not_on_ignore_list} AND FIND_IN_SET({string:from_id}, pm_ignore_list) != 0)') . ')') . ' AS ignored, FIND_IN_SET({string:from_id}, buddy_list) != 0 AS is_buddy, is_activated, additional_groups, id_group, id_post_group FROM {db_prefix}members WHERE id_member IN ({array_int:recipients}) ORDER BY lngfile LIMIT {int:count_recipients}', array('not_on_ignore_list' => 1, 'buddies_only' => 2, 'admins_only' => 3, 'recipients' => $all_to, 'count_recipients' => count($all_to), 'from_id' => $from['id'])); $notifications = array(); $as_notifications = array(); while ($row = mysql_fetch_assoc($request)) { // Don't do anything for members to be deleted! if (isset($deletes[$row['id_member']])) { continue; } // We need to know this members groups. $groups = explode(',', $row['additional_groups']); $groups[] = $row['id_group']; $groups[] = $row['id_post_group']; $message_limit = -1; // For each group see whether they've gone over their limit - assuming they're not an admin. if (!in_array(1, $groups)) { foreach ($groups as $id) { if (isset($message_limit_cache[$id]) && $message_limit != 0 && $message_limit < $message_limit_cache[$id]) { $message_limit = $message_limit_cache[$id]; } } if ($message_limit > 0 && $message_limit <= $row['instant_messages']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_data_limit_reached'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // Do they have any of the allowed groups? if (count(array_intersect($allowed_groups, $groups)) == 0 || count(array_intersect($disallowed_groups, $groups)) != 0) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } } // Note that PostgreSQL can return a lowercase t/f for FIND_IN_SET if (!empty($row['ignored']) && $row['ignored'] != 'f' && $row['id_member'] != $from['id']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_ignored_by_user'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // If the receiving account is banned (>=10) or pending deletion (4), refuse to send the PM. if ($row['is_activated'] >= 10 || $row['is_activated'] == 4 && !$user_info['is_admin']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // Send a notification, if enabled - taking the buddy list into account. if (!empty($row['email_address']) && ($row['pm_email_notify'] == 1 || $row['pm_email_notify'] > 1 && (!empty($modSettings['enable_buddylist']) && $row['is_buddy'])) && $row['is_activated'] == 1) { $notifications[empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']][] = $row['email_address']; } $as_notifications[] = $row['id_member']; $log['sent'][$row['id_member']] = sprintf(isset($txt['pm_successfully_sent']) ? $txt['pm_successfully_sent'] : '', $row['real_name']); } mysql_free_result($request); // Only 'send' the message if there are any recipients left. if (empty($all_to)) { return $log; } // Insert the message itself and then grab the last insert id. smf_db_insert('', '{db_prefix}personal_messages', array('id_pm_head' => 'int', 'id_member_from' => 'int', 'deleted_by_sender' => 'int', 'from_name' => 'string-255', 'msgtime' => 'int', 'subject' => 'string-255', 'body' => 'string-65534'), array($pm_head, $from['id'], $store_outbox ? 0 : 1, $from['username'], time(), $htmlsubject, $htmlmessage), array('id_pm')); $id_pm = smf_db_insert_id('{db_prefix}personal_messages', 'id_pm'); if ($modSettings['astream_active']) { require_once $sourcedir . '/lib/Subs-Activities.php'; $id_act = aStreamAdd($from['id'], ACT_PM, array('member_name' => $from['username']), 0, 0, $id_pm, $from['id'], ACT_PLEVEL_PRIVATE); if ((int) $id_act > 0) { aStreamAddNotification($as_notifications, $id_act, ACT_PM); } } // Add the recipients. if (!empty($id_pm)) { // If this is new we need to set it part of it's own conversation. if (empty($pm_head)) { smf_db_query(' UPDATE {db_prefix}personal_messages SET id_pm_head = {int:id_pm_head} WHERE id_pm = {int:id_pm_head}', array('id_pm_head' => $id_pm)); } // Some people think manually deleting personal_messages is fun... it's not. We protect against it though :) smf_db_query(' DELETE FROM {db_prefix}pm_recipients WHERE id_pm = {int:id_pm}', array('id_pm' => $id_pm)); $insertRows = array(); foreach ($all_to as $to) { $insertRows[] = array($id_pm, $to, in_array($to, $recipients['bcc']) ? 1 : 0, isset($deletes[$to]) ? 1 : 0, 1); } smf_db_insert('insert', '{db_prefix}pm_recipients', array('id_pm' => 'int', 'id_member' => 'int', 'bcc' => 'int', 'deleted' => 'int', 'is_new' => 'int'), $insertRows, array('id_pm', 'id_member')); } censorText($message); censorText($subject); $message = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc(htmlspecialchars($message), false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '[' => '[', ']' => ']'))))); foreach ($notifications as $lang => $notification_list) { // Make sure to use the right language. loadLanguage('index+PersonalMessage', $lang, false); // Replace the right things in the message strings. $mailsubject = str_replace(array('SUBJECT', 'SENDER'), array($subject, un_htmlspecialchars($from['name'])), $txt['new_pm_subject']); $mailmessage = str_replace(array('SUBJECT', 'MESSAGE', 'SENDER'), array($subject, $message, un_htmlspecialchars($from['name'])), $txt['pm_email']); $mailmessage .= "\n\n" . $txt['instant_reply'] . ' ' . $scripturl . '?action=pm;sa=send;f=inbox;pmsg=' . $id_pm . ';quote;u=' . $from['id']; // Off the notification email goes! sendmail($notification_list, $mailsubject, $mailmessage, null, 'p' . $id_pm, false, 2, null, true); } // Back to what we were on before! loadLanguage('index+PersonalMessage'); // Add one to their unread and read message counts. foreach ($all_to as $k => $id) { if (isset($deletes[$id])) { unset($all_to[$k]); } } if (!empty($all_to)) { updateMemberData($all_to, array('instant_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1)); } return $log; }
function ModifyLanguage() { global $settings, $context, $txt, $modSettings, $boarddir, $sourcedir, $language; loadLanguage('ManageSettings'); // Select the languages tab. $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'edit'; $context['page_title'] = $txt['edit_languages']; $context['sub_template'] = 'modify_language_entries'; $context['lang_id'] = $_GET['lid']; list($theme_id, $file_id) = empty($_REQUEST['tfid']) || strpos($_REQUEST['tfid'], '+') === false ? array(1, '') : explode('+', $_REQUEST['tfid']); // Clean the ID - just in case. preg_match('~([A-Za-z0-9_-]+)~', $context['lang_id'], $matches); $context['lang_id'] = $matches[1]; // Get all the theme data. $request = smf_db_query(' SELECT id_theme, variable, value FROM {db_prefix}themes WHERE id_theme != {int:default_theme} AND id_member = {int:no_member} AND variable IN ({string:name}, {string:theme_dir})', array('default_theme' => 1, 'no_member' => 0, 'name' => 'name', 'theme_dir' => 'theme_dir')); $themes = array(1 => array('name' => $txt['dvc_default'], 'theme_dir' => $settings['default_theme_dir'])); while ($row = mysql_fetch_assoc($request)) { $themes[$row['id_theme']][$row['variable']] = $row['value']; } mysql_free_result($request); // This will be where we look $lang_dirs = array(); // Check we have themes with a path and a name - just in case - and add the path. foreach ($themes as $id => $data) { if (count($data) != 2) { unset($themes[$id]); } elseif (is_dir($data['theme_dir'] . '/languages')) { $lang_dirs[$id] = $data['theme_dir'] . '/languages'; } // How about image directories? if (is_dir($data['theme_dir'] . '/images/' . $context['lang_id'])) { $images_dirs[$id] = $data['theme_dir'] . '/images/' . $context['lang_id']; } } $current_file = $file_id ? $lang_dirs[$theme_id] . '/' . $file_id . '.' . $context['lang_id'] . '.php' : ''; // Now for every theme get all the files and stick them in context! $context['possible_files'] = array(); foreach ($lang_dirs as $theme => $theme_dir) { // Open it up. $dir = dir($theme_dir); while ($entry = $dir->read()) { // We're only after the files for this language. if (preg_match('~^([A-Za-z]+)\\.' . $context['lang_id'] . '\\.php$~', $entry, $matches) == 0) { continue; } //!!! Temp! if ($matches[1] == 'EmailTemplates') { continue; } if (!isset($context['possible_files'][$theme])) { $context['possible_files'][$theme] = array('id' => $theme, 'name' => $themes[$theme]['name'], 'files' => array()); } $context['possible_files'][$theme]['files'][] = array('id' => $matches[1], 'name' => isset($txt['lang_file_desc_' . $matches[1]]) ? $txt['lang_file_desc_' . $matches[1]] : $matches[1], 'selected' => $theme_id == $theme && $file_id == $matches[1]); } $dir->close(); } // We no longer wish to speak this language. if (!empty($_POST['delete_main']) && $context['lang_id'] != 'english') { checkSession(); // !!! Todo: FTP Controls? require_once $sourcedir . '/lib/Subs-Package.php'; // First, Make a backup? if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['lang_id'] . '$$$')) { $_SESSION['last_backup_for'] = $context['lang_id'] . '$$$'; package_create_backup('backup_lang_' . $context['lang_id']); } // Second, loop through the array to remove the files. foreach ($lang_dirs as $curPath) { foreach ($context['possible_files'][1]['files'] as $lang) { if (file_exists($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php')) { unlink($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php'); } } // Check for the email template. if (file_exists($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php')) { unlink($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php'); } } // Third, the agreement file. if (file_exists($boarddir . '/agreement.' . $context['lang_id'] . '.txt')) { unlink($boarddir . '/agreement.' . $context['lang_id'] . '.txt'); } // Fourth, a related images folder? foreach ($images_dirs as $curPath) { if (is_dir($curPath)) { deltree($curPath); } } // Members can no longer use this language. smf_db_query(' UPDATE {db_prefix}members SET lngfile = {string:empty_string} WHERE lngfile = {string:current_language}', array('empty_string' => '', 'current_language' => $context['lang_id'])); // Fifth, update getLanguages() cache. if (!empty($modSettings['cache_enable'])) { CacheAPI::putCache('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); CacheAPI::putCache('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); } // Sixth, if we deleted the default language, set us back to english? if ($context['lang_id'] == $language) { require_once $sourcedir . '/lib/Subs-Admin.php'; $language = 'english'; updateSettingsFile(array('language' => '\'' . $language . '\'')); } // Seventh, get out of here. redirectexit('action=admin;area=languages;sa=edit;' . $context['session_var'] . '=' . $context['session_id']); } // Saving primary settings? $madeSave = false; if (!empty($_POST['save_main']) && !$current_file) { checkSession(); // Read in the current file. $current_data = implode('', file($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php')); // These are the replacements. old => new $replace_array = array('~\\$txt\\[\'lang_character_set\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_character_set\'] = \'' . addslashes($_POST['character_set']) . '\';', '~\\$txt\\[\'lang_locale\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_locale\'] = \'' . addslashes($_POST['locale']) . '\';', '~\\$txt\\[\'lang_dictionary\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_dictionary\'] = \'' . addslashes($_POST['dictionary']) . '\';', '~\\$txt\\[\'lang_spelling\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_spelling\'] = \'' . addslashes($_POST['spelling']) . '\';', '~\\$txt\\[\'lang_rtl\'\\]\\s=\\s[A-Za-z0-9]+;~' => '$txt[\'lang_rtl\'] = ' . (!empty($_POST['rtl']) ? 'true' : 'false') . ';'); $current_data = preg_replace(array_keys($replace_array), array_values($replace_array), $current_data); $fp = fopen($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php', 'w+'); fwrite($fp, $current_data); fclose($fp); $madeSave = true; } // Quickly load index language entries. $old_txt = $txt; require $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'; $context['lang_file_not_writable_message'] = is_writable($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php') ? '' : sprintf($txt['lang_file_not_writable'], $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'); // Setup the primary settings context. $context['primary_settings'] = array('name' => commonAPI::ucwords(strtr($context['lang_id'], array('_' => ' ', '-utf8' => ''))), 'character_set' => $txt['lang_character_set'], 'locale' => $txt['lang_locale'], 'dictionary' => $txt['lang_dictionary'], 'spelling' => $txt['lang_spelling'], 'rtl' => $txt['lang_rtl']); // Restore normal service. $txt = $old_txt; // Are we saving? $save_strings = array(); if (isset($_POST['save_entries']) && !empty($_POST['entry'])) { checkSession(); // Clean each entry! foreach ($_POST['entry'] as $k => $v) { // Only try to save if it's changed! if ($_POST['entry'][$k] != $_POST['comp'][$k]) { $save_strings[$k] = cleanLangString($v, false); } } } // If we are editing a file work away at that. if ($current_file) { $context['entries_not_writable_message'] = is_writable($current_file) ? '' : sprintf($txt['lang_entries_not_writable'], $current_file); $entries = array(); // We can't just require it I'm afraid - otherwise we pass in all kinds of variables! $multiline_cache = ''; foreach (file($current_file) as $line) { // Got a new entry? if ($line[0] == '$' && !empty($multiline_cache)) { preg_match('~\\$(helptxt|txt)\\[\'(.+)\'\\]\\s=\\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches); if (!empty($matches[3])) { $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]); $multiline_cache = ''; } } $multiline_cache .= $line . "\n"; } // Last entry to add? if ($multiline_cache) { preg_match('~\\$(helptxt|txt)\\[\'(.+)\'\\]\\s=\\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches); if (!empty($matches[3])) { $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]); } } // These are the entries we can definitely save. $final_saves = array(); $context['file_entries'] = array(); foreach ($entries as $entryKey => $entryValue) { // Ignore some things we set separately. $ignore_files = array('lang_character_set', 'lang_locale', 'lang_dictionary', 'lang_spelling', 'lang_rtl'); if (in_array($entryKey, $ignore_files)) { continue; } // These are arrays that need breaking out. $arrays = array('days', 'days_short', 'months', 'months_titles', 'months_short'); if (in_array($entryKey, $arrays)) { // Get off the first bits. $entryValue['entry'] = substr($entryValue['entry'], strpos($entryValue['entry'], '(') + 1, strrpos($entryValue['entry'], ')') - strpos($entryValue['entry'], '(')); $entryValue['entry'] = explode(',', strtr($entryValue['entry'], array(' ' => ''))); // Now create an entry for each item. $cur_index = 0; $save_cache = array('enabled' => false, 'entries' => array()); foreach ($entryValue['entry'] as $id => $subValue) { // Is this a new index? if (preg_match('~^(\\d+)~', $subValue, $matches)) { $cur_index = $matches[1]; $subValue = substr($subValue, strpos($subValue, '\'')); } // Clean up some bits. $subValue = strtr($subValue, array('"' => '', '\'' => '', ')' => '')); // Can we save? if (isset($save_strings[$entryKey . '-+- ' . $cur_index])) { $save_cache['entries'][$cur_index] = strtr($save_strings[$entryKey . '-+- ' . $cur_index], array('\'' => '')); $save_cache['enabled'] = true; } else { $save_cache['entries'][$cur_index] = $subValue; } $context['file_entries'][] = array('key' => $entryKey . '-+- ' . $cur_index, 'value' => $subValue, 'rows' => 1); $cur_index++; } // Do we need to save? if ($save_cache['enabled']) { // Format the string, checking the indexes first. $items = array(); $cur_index = 0; foreach ($save_cache['entries'] as $k2 => $v2) { // Manually show the custom index. if ($k2 != $cur_index) { $items[] = $k2 . ' => \'' . $v2 . '\''; $cur_index = $k2; } else { $items[] = '\'' . $v2 . '\''; } $cur_index++; } // Now create the string! $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = array(' . implode(', ', $items) . ');'); } } else { // Saving? if (isset($save_strings[$entryKey]) && $save_strings[$entryKey] != $entryValue['entry']) { // !!! Fix this properly. if ($save_strings[$entryKey] == '') { $save_strings[$entryKey] = '\'\''; } // Set the new value. $entryValue['entry'] = $save_strings[$entryKey]; // And we know what to save now! $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = ' . $save_strings[$entryKey] . ';'); } $editing_string = cleanLangString($entryValue['entry'], true); $context['file_entries'][] = array('key' => $entryKey, 'value' => $editing_string, 'rows' => (int) (strlen($editing_string) / 38) + substr_count($editing_string, "\n") + 1); } } // Any saves to make? if (!empty($final_saves)) { checkSession(); $file_contents = implode('', file($current_file)); foreach ($final_saves as $save) { $file_contents = strtr($file_contents, array($save['find'] => $save['replace'])); } // Save the actual changes. $fp = fopen($current_file, 'w+'); fwrite($fp, $file_contents); fclose($fp); $madeSave = true; } // Another restore. $txt = $old_txt; } // If we saved, redirect. if ($madeSave) { redirectexit('action=admin;area=languages;sa=editlang;lid=' . $context['lang_id']); } }
function modifyBoard($board_id, &$boardOptions) { global $sourcedir, $cat_tree, $boards, $boardList, $modSettings, $smcFunc; // Get some basic information about all boards and categories. getBoardTree(); // Make sure given boards and categories exist. if (!isset($boards[$board_id]) || isset($boardOptions['target_board']) && !isset($boards[$boardOptions['target_board']]) || isset($boardOptions['target_category']) && !isset($cat_tree[$boardOptions['target_category']])) { fatal_lang_error('no_board'); } // All things that will be updated in the database will be in $boardUpdates. $boardUpdates = array(); $boardUpdateParameters = array(); // In case the board has to be moved if (isset($boardOptions['move_to'])) { // Move the board to the top of a given category. if ($boardOptions['move_to'] == 'top') { $id_cat = $boardOptions['target_category']; $child_level = 0; $id_parent = 0; $after = $cat_tree[$id_cat]['last_board_order']; } elseif ($boardOptions['move_to'] == 'bottom') { $id_cat = $boardOptions['target_category']; $child_level = 0; $id_parent = 0; $after = 0; foreach ($cat_tree[$id_cat]['children'] as $id_board => $dummy) { $after = max($after, $boards[$id_board]['order']); } } elseif ($boardOptions['move_to'] == 'child') { $id_cat = $boards[$boardOptions['target_board']]['category']; $child_level = $boards[$boardOptions['target_board']]['level'] + 1; $id_parent = $boardOptions['target_board']; // People can be creative, in many ways... if (isChildOf($id_parent, $board_id)) { fatal_lang_error('mboards_parent_own_child_error', false); } elseif ($id_parent == $board_id) { fatal_lang_error('mboards_board_own_child_error', false); } $after = $boards[$boardOptions['target_board']]['order']; // Check if there are already children and (if so) get the max board order. if (!empty($boards[$id_parent]['tree']['children']) && empty($boardOptions['move_first_child'])) { foreach ($boards[$id_parent]['tree']['children'] as $childBoard_id => $dummy) { $after = max($after, $boards[$childBoard_id]['order']); } } } elseif (in_array($boardOptions['move_to'], array('before', 'after'))) { $id_cat = $boards[$boardOptions['target_board']]['category']; $child_level = $boards[$boardOptions['target_board']]['level']; $id_parent = $boards[$boardOptions['target_board']]['parent']; $after = $boards[$boardOptions['target_board']]['order'] - ($boardOptions['move_to'] == 'before' ? 1 : 0); } else { trigger_error('modifyBoard(): The move_to value \'' . $boardOptions['move_to'] . '\' is incorrect', E_USER_ERROR); } // Get a list of children of this board. $childList = array(); recursiveBoards($childList, $boards[$board_id]['tree']); // See if there are changes that affect children. $childUpdates = array(); $levelDiff = $child_level - $boards[$board_id]['level']; if ($levelDiff != 0) { $childUpdates[] = 'child_level = child_level ' . ($levelDiff > 0 ? '+ ' : '') . '{int:level_diff}'; } if ($id_cat != $boards[$board_id]['category']) { $childUpdates[] = 'id_cat = {int:category}'; } // Fix the children of this board. if (!empty($childList) && !empty($childUpdates)) { smf_db_query(' UPDATE {db_prefix}boards SET ' . implode(', ', $childUpdates) . ' WHERE id_board IN ({array_int:board_list})', array('board_list' => $childList, 'category' => $id_cat, 'level_diff' => $levelDiff)); } // Make some room for this spot. smf_db_query(' UPDATE {db_prefix}boards SET board_order = board_order + {int:new_order} WHERE board_order > {int:insert_after} AND id_board != {int:selected_board}', array('insert_after' => $after, 'selected_board' => $board_id, 'new_order' => 1 + count($childList))); $boardUpdates[] = 'id_cat = {int:id_cat}'; $boardUpdates[] = 'id_parent = {int:id_parent}'; $boardUpdates[] = 'child_level = {int:child_level}'; $boardUpdates[] = 'board_order = {int:board_order}'; $boardUpdateParameters += array('id_cat' => $id_cat, 'id_parent' => $id_parent, 'child_level' => $child_level, 'board_order' => $after + 1); } // This setting is a little twisted in the database... if (isset($boardOptions['posts_count'])) { $boardUpdates[] = 'count_posts = {int:count_posts}'; $boardUpdateParameters['count_posts'] = $boardOptions['posts_count'] ? 0 : 1; } if (isset($boardOptions['allow_topics'])) { $boardUpdates[] = 'allow_topics = {int:allow_topics}'; $boardUpdateParameters['allow_topics'] = $boardOptions['allow_topics'] ? 1 : 0; } if (isset($boardOptions['automerge'])) { $boardUpdates[] = 'automerge = {int:automerge}'; $boardUpdateParameters['automerge'] = $boardOptions['automerge']; } if (isset($boardOptions['boardicon'])) { $boardUpdates[] = 'icon = {string:boardicon}'; $boardUpdateParameters['boardicon'] = $boardOptions['boardicon']; } // Set the theme for this board. if (isset($boardOptions['board_theme'])) { $boardUpdates[] = 'id_theme = {int:id_theme}'; $boardUpdateParameters['id_theme'] = (int) $boardOptions['board_theme']; } // Should the board theme override the user preferred theme? if (isset($boardOptions['override_theme'])) { $boardUpdates[] = 'override_theme = {int:override_theme}'; $boardUpdateParameters['override_theme'] = $boardOptions['override_theme'] ? 1 : 0; } // Who's allowed to access this board. if (isset($boardOptions['access_groups'])) { $boardUpdates[] = 'member_groups = {string:member_groups}'; $boardUpdateParameters['member_groups'] = implode(',', $boardOptions['access_groups']); } if (isset($boardOptions['board_name'])) { $boardUpdates[] = 'name = {string:board_name}'; $boardUpdateParameters['board_name'] = $boardOptions['board_name']; } if (isset($boardOptions['board_description'])) { $boardUpdates[] = 'description = {string:board_description}'; $boardUpdateParameters['board_description'] = $boardOptions['board_description']; } if (isset($boardOptions['profile'])) { $boardUpdates[] = 'id_profile = {int:profile}'; $boardUpdateParameters['profile'] = (int) $boardOptions['profile']; } if (isset($boardOptions['redirect'])) { $boardUpdates[] = 'redirect = {string:redirect}'; $boardUpdateParameters['redirect'] = $boardOptions['redirect']; } if (isset($boardOptions['num_posts'])) { $boardUpdates[] = 'num_posts = {int:num_posts}'; $boardUpdateParameters['num_posts'] = (int) $boardOptions['num_posts']; } // Do the updates (if any). if (!empty($boardUpdates)) { $request = smf_db_query(' UPDATE {db_prefix}boards SET ' . implode(', ', $boardUpdates) . ' WHERE id_board = {int:selected_board}', array_merge($boardUpdateParameters, array('selected_board' => $board_id))); } // Set moderators of this board. if (isset($boardOptions['moderators']) || isset($boardOptions['moderator_string'])) { // Reset current moderators for this board - if there are any! smf_db_query(' DELETE FROM {db_prefix}moderators WHERE id_board = {int:board_list}', array('board_list' => $board_id)); // Validate and get the IDs of the new moderators. if (isset($boardOptions['moderator_string']) && trim($boardOptions['moderator_string']) != '') { // Divvy out the usernames, remove extra space. $moderator_string = strtr(commonAPI::htmlspecialchars($boardOptions['moderator_string'], ENT_QUOTES), array('"' => '"')); preg_match_all('~"([^"]+)"~', $moderator_string, $matches); $moderators = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $moderator_string))); for ($k = 0, $n = count($moderators); $k < $n; $k++) { $moderators[$k] = trim($moderators[$k]); if (strlen($moderators[$k]) == 0) { unset($moderators[$k]); } } // Find all the id_member's for the member_name's in the list. if (empty($boardOptions['moderators'])) { $boardOptions['moderators'] = array(); } if (!empty($moderators)) { $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE member_name IN ({array_string:moderator_list}) OR real_name IN ({array_string:moderator_list}) LIMIT ' . count($moderators), array('moderator_list' => $moderators)); while ($row = mysql_fetch_assoc($request)) { $boardOptions['moderators'][] = $row['id_member']; } mysql_free_result($request); } } // Add the moderators to the board. if (!empty($boardOptions['moderators'])) { $inserts = array(); foreach ($boardOptions['moderators'] as $moderator) { $inserts[] = array($board_id, $moderator); } smf_db_insert('insert', '{db_prefix}moderators', array('id_board' => 'int', 'id_member' => 'int'), $inserts, array('id_board', 'id_member')); } // Note that caches can now be wrong! updateSettings(array('settings_updated' => time())); } if (isset($boardOptions['move_to'])) { reorderBoards(); } clean_cache('data'); if (empty($boardOptions['dont_log'])) { logAction('edit_board', array('board' => $board_id), 'admin'); } }
public function prepareIndexes($word, &$wordsSearch, &$wordsExclude, $isExcluded) { global $modSettings, $smcFunc; $subwords = text2words($word, $this->min_word_length, true); if (empty($modSettings['search_force_index'])) { $wordsSearch['words'][] = $word; } // Excluded phrases don't benefit from being split into subwords. if (count($subwords) > 1 && $isExcluded) { continue; } else { foreach ($subwords as $subword) { if (commonAPI::strlen($subword) >= $this->min_word_length && !in_array($subword, $this->bannedWords)) { $wordsSearch['indexed_words'][] = $subword; if ($isExcluded) { $wordsExclude[] = $subword; } } } } }
function Display() { global $scripturl, $txt, $modSettings, $context, $settings, $memberContext, $output; global $options, $sourcedir, $user_info, $user_profile, $board_info, $topic, $board; global $attachments, $messages_request, $topicinfo, $language; $context['response_prefixlen'] = strlen($txt['response_prefix']); $context['need_synhlt'] = true; $context['is_display_std'] = true; $context['pcache_update_counter'] = !empty($modSettings['use_post_cache']) ? 0 : PCACHE_UPDATE_PER_VIEW + 1; $context['time_cutoff_ref'] = time(); $context['template_hooks']['display'] = array('header' => '', 'extend_topicheader' => '', 'above_posts' => '', 'below_posts' => '', 'footer' => ''); //EoS_Smarty::getConfigInstance()->registerHookTemplate('postbit_below', 'overrides/foo'); if (!empty($modSettings['karmaMode'])) { require_once $sourcedir . '/lib/Subs-Ratings.php'; } else { $context['can_see_like'] = $context['can_give_like'] = false; } // What are you gonna display if these are empty?! if (empty($topic)) { fatal_lang_error('no_board', false); } // Not only does a prefetch make things slower for the server, but it makes it impossible to know if they read it. if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') { ob_end_clean(); header('HTTP/1.1 403 Prefetch Forbidden'); die; } // How much are we sticking on each page? $context['messages_per_page'] = commonAPI::getMessagesPerPage(); $context['page_number'] = isset($_REQUEST['start']) ? $_REQUEST['start'] / $context['messages_per_page'] : 0; // Let's do some work on what to search index. //$context['multiquote_cookiename'] = 'mq_' . $context['current_topic']; $context['multiquote_posts'] = array(); if (isset($_COOKIE[$context['multiquote_cookiename']]) && strlen($_COOKIE[$context['multiquote_cookiename']]) > 1) { $context['multiquote_posts'] = explode(',', $_COOKIE[$context['multiquote_cookiename']]); } $context['multiquote_posts_count'] = count($context['multiquote_posts']); if (count($_GET) > 2) { foreach ($_GET as $k => $v) { if (!in_array($k, array('topic', 'board', 'start', session_name()))) { $context['robot_no_index'] = true; } } } if (!empty($_REQUEST['start']) && (!is_numeric($_REQUEST['start']) || $_REQUEST['start'] % $context['messages_per_page'] != 0)) { $context['robot_no_index'] = true; } // Find the previous or next topic. Make a fuss if there are no more. if (isset($_REQUEST['prev_next']) && ($_REQUEST['prev_next'] == 'prev' || $_REQUEST['prev_next'] == 'next')) { // No use in calculating the next topic if there's only one. if ($board_info['num_topics'] > 1) { // Just prepare some variables that are used in the query. $gt_lt = $_REQUEST['prev_next'] == 'prev' ? '>' : '<'; $order = $_REQUEST['prev_next'] == 'prev' ? '' : ' DESC'; $request = smf_db_query(' SELECT t2.id_topic FROM {db_prefix}topics AS t INNER JOIN {db_prefix}topics AS t2 ON (' . (empty($modSettings['enableStickyTopics']) ? ' t2.id_last_msg ' . $gt_lt . ' t.id_last_msg' : ' (t2.id_last_msg ' . $gt_lt . ' t.id_last_msg AND t2.is_sticky ' . $gt_lt . '= t.is_sticky) OR t2.is_sticky ' . $gt_lt . ' t.is_sticky') . ') WHERE t.id_topic = {int:current_topic} AND t2.id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' AND (t2.approved = {int:is_approved} OR (t2.id_member_started != {int:id_member_started} AND t2.id_member_started = {int:current_member}))') . ' ORDER BY' . (empty($modSettings['enableStickyTopics']) ? '' : ' t2.is_sticky' . $order . ',') . ' t2.id_last_msg' . $order . ' LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic, 'is_approved' => 1, 'id_member_started' => 0)); // No more left. if (mysql_num_rows($request) == 0) { mysql_free_result($request); // Roll over - if we're going prev, get the last - otherwise the first. $request = smf_db_query(' SELECT id_topic FROM {db_prefix}topics WHERE id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' AND (approved = {int:is_approved} OR (id_member_started != {int:id_member_started} AND id_member_started = {int:current_member}))') . ' ORDER BY' . (empty($modSettings['enableStickyTopics']) ? '' : ' is_sticky' . $order . ',') . ' id_last_msg' . $order . ' LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'is_approved' => 1, 'id_member_started' => 0)); } // Now you can be sure $topic is the id_topic to view. list($topic) = mysql_fetch_row($request); mysql_free_result($request); $context['current_topic'] = $topic; } // Go to the newest message on this topic. $_REQUEST['start'] = 'new'; } // Add 1 to the number of views of this topic. if (empty($_SESSION['last_read_topic']) || $_SESSION['last_read_topic'] != $topic) { smf_db_query(' UPDATE {db_prefix}topics SET num_views = num_views + 1 WHERE id_topic = {int:current_topic}', array('current_topic' => $topic)); $_SESSION['last_read_topic'] = $topic; } if ($modSettings['tags_active']) { $dbresult = smf_db_query(' SELECT t.tag,l.ID,t.ID_TAG FROM {db_prefix}tags_log as l, {db_prefix}tags as t WHERE t.ID_TAG = l.ID_TAG && l.ID_TOPIC = {int:topic}', array('topic' => $topic)); $context['topic_tags'] = array(); while ($row = mysql_fetch_assoc($dbresult)) { $context['topic_tags'][] = array('ID' => $row['ID'], 'ID_TAG' => $row['ID_TAG'], 'tag' => $row['tag']); } mysql_free_result($dbresult); $context['tags_active'] = true; } else { $context['topic_tags'] = $context['tags_active'] = 0; } // Get all the important topic info. $request = smf_db_query('SELECT t.num_replies, t.num_views, t.locked, ms.poster_name, ms.subject, ms.poster_email, ms.poster_time AS first_post_time, t.is_sticky, t.id_poll, t.id_member_started, t.id_first_msg, t.id_last_msg, t.approved, t.unapproved_posts, t.id_layout, ' . ($user_info['is_guest'] ? 't.id_last_msg + 1' : 'IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1') . ' AS new_from ' . (!empty($modSettings['recycle_board']) && $modSettings['recycle_board'] == $board ? ', id_previous_board, id_previous_topic' : '') . ', p.name AS prefix_name, ms1.poster_time AS last_post_time, ms1.modified_time AS last_modified_time, IFNULL(b.automerge, 0) AS automerge FROM {db_prefix}topics AS t INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) INNER JOIN {db_prefix}messages AS ms1 ON (ms1.id_msg = t.id_last_msg) INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)' . ($user_info['is_guest'] ? '' : ' LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member}) LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member})') . ' LEFT JOIN {db_prefix}prefixes as p ON p.id_prefix = t.id_prefix WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_member' => $user_info['id'], 'current_topic' => $topic, 'current_board' => $board)); if (mysql_num_rows($request) == 0) { fatal_lang_error('not_a_topic', false); } // Added by Related Topics if (isset($modSettings['have_related_topics']) && $modSettings['have_related_topics'] && !empty($modSettings['relatedTopicsEnabled'])) { require_once $sourcedir . '/lib/Subs-Related.php'; loadRelated($topic); } $topicinfo = mysql_fetch_assoc($request); mysql_free_result($request); $context['topic_banned_members'] = array(); $request = smf_db_query('SELECT id_member FROM {db_prefix}topicbans WHERE id_topic = {int:topic}', array('topic' => $topic)); if (mysql_num_rows($request) != 0) { while ($row = mysql_fetch_row($request)) { $context['topic_banned_members'][] = $row[0]; } } mysql_free_result($request); $context['topic_banned_members_count'] = count($context['topic_banned_members']); $context['topic_last_modified'] = max($topicinfo['last_post_time'], $topicinfo['last_modified_time']); // todo: considering - make post cutoff time for the cache depend on the modification time of the topic's last post $context['real_num_replies'] = $context['num_replies'] = $topicinfo['num_replies']; $context['topic_first_message'] = $topicinfo['id_first_msg']; $context['topic_last_message'] = $topicinfo['id_last_msg']; $context['first_subject'] = $topicinfo['subject']; $context['prefix'] = !empty($topicinfo['prefix_name']) ? html_entity_decode($topicinfo['prefix_name']) . ' ' : ''; $context['automerge'] = $topicinfo['automerge'] > 0; // Add up unapproved replies to get real number of replies... if ($modSettings['postmod_active'] && allowedTo('approve_posts')) { $context['real_num_replies'] += $topicinfo['unapproved_posts'] - ($topicinfo['approved'] ? 0 : 1); } // If this topic has unapproved posts, we need to work out how many posts the user can see, for page indexing. if ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !$user_info['is_guest'] && !allowedTo('approve_posts')) { $request = smf_db_query(' SELECT COUNT(id_member) AS my_unapproved_posts FROM {db_prefix}messages WHERE id_topic = {int:current_topic} AND id_member = {int:current_member} AND approved = 0', array('current_topic' => $topic, 'current_member' => $user_info['id'])); list($myUnapprovedPosts) = mysql_fetch_row($request); mysql_free_result($request); $context['total_visible_posts'] = $context['num_replies'] + $myUnapprovedPosts + ($topicinfo['approved'] ? 1 : 0); } else { $context['total_visible_posts'] = $context['num_replies'] + $topicinfo['unapproved_posts'] + ($topicinfo['approved'] ? 1 : 0); } // When was the last time this topic was replied to? Should we warn them about it? /* redundant query? last_post_time is already in $topicinfo[] $request = smf_db_query( ' SELECT poster_time FROM {db_prefix}messages WHERE id_msg = {int:id_last_msg} LIMIT 1', array( 'id_last_msg' => $topicinfo['id_last_msg'], ) ); list ($lastPostTime) = mysql_fetch_row($request); mysql_free_result($request); */ $lastPostTime = $topicinfo['last_post_time']; $context['oldTopicError'] = !empty($modSettings['oldTopicDays']) && $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time() && empty($sticky); // The start isn't a number; it's information about what to do, where to go. if (!is_numeric($_REQUEST['start'])) { // Redirect to the page and post with new messages, originally by Omar Bazavilvazo. if ($_REQUEST['start'] == 'new') { // Guests automatically go to the last post. if ($user_info['is_guest']) { $context['start_from'] = $context['total_visible_posts'] - 1; $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : 0; } else { // Find the earliest unread message in the topic. (the use of topics here is just for both tables.) $request = smf_db_query(' SELECT IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1 AS new_from FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member}) LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member}) WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic)); list($new_from) = mysql_fetch_row($request); mysql_free_result($request); // Fall through to the next if statement. $_REQUEST['start'] = 'msg' . $new_from; } } // Start from a certain time index, not a message. if (substr($_REQUEST['start'], 0, 4) == 'from') { $timestamp = (int) substr($_REQUEST['start'], 4); if ($timestamp === 0) { $_REQUEST['start'] = 0; } else { // Find the number of messages posted before said time... $request = smf_db_query(' SELECT COUNT(*) FROM {db_prefix}messages WHERE poster_time < {int:timestamp} AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts') ? ' AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), array('current_topic' => $topic, 'current_member' => $user_info['id'], 'is_approved' => 1, 'timestamp' => $timestamp)); list($context['start_from']) = mysql_fetch_row($request); mysql_free_result($request); // Handle view_newest_first options, and get the correct start value. $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1; } } elseif (substr($_REQUEST['start'], 0, 3) == 'msg') { $virtual_msg = (int) substr($_REQUEST['start'], 3); if (!$topicinfo['unapproved_posts'] && $virtual_msg >= $topicinfo['id_last_msg']) { $context['start_from'] = $context['total_visible_posts'] - 1; } elseif (!$topicinfo['unapproved_posts'] && $virtual_msg <= $topicinfo['id_first_msg']) { $context['start_from'] = 0; } else { // Find the start value for that message...... $request = smf_db_query(' SELECT COUNT(*) FROM {db_prefix}messages WHERE id_msg < {int:virtual_msg} AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts') ? ' AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'virtual_msg' => $virtual_msg, 'is_approved' => 1, 'no_member' => 0)); list($context['start_from']) = mysql_fetch_row($request); mysql_free_result($request); } // We need to reverse the start as well in this case. if (isset($_REQUEST['perma'])) { $_REQUEST['start'] = $virtual_msg; } else { $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1; } } } // Create a previous next string if the selected theme has it as a selected option. $context['previous_next'] = $modSettings['enablePreviousNext'] ? '<a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=prev#new">' . $txt['previous_next_back'] . '</a> <a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=next#new">' . $txt['previous_next_forward'] . '</a>' : ''; // Do we need to show the visual verification image? $context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1); if ($context['require_verification']) { require_once $sourcedir . '/lib/Subs-Editor.php'; $verificationOptions = array('id' => 'post', 'skip_template' => true); $context['require_verification'] = create_control_verification($verificationOptions); $context['visual_verification_id'] = $verificationOptions['id']; } // Are we showing signatures - or disabled fields? $context['signature_enabled'] = substr($modSettings['signature_settings'], 0, 1) == 1; $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array(); // Censor the title... censorText($topicinfo['subject']); $context['page_title'] = $topicinfo['subject'] . ((int) $context['page_number'] > 0 ? ' - ' . $txt['page'] . ' ' . ($context['page_number'] + 1) : ''); // Is this topic sticky, or can it even be? $topicinfo['is_sticky'] = empty($modSettings['enableStickyTopics']) ? '0' : $topicinfo['is_sticky']; // Default this topic to not marked for notifications... of course... $context['is_marked_notify'] = false; // Did we report a post to a moderator just now? $context['report_sent'] = isset($_GET['reportsent']); // Let's get nosey, who is viewing this topic? if (!empty($settings['display_who_viewing'])) { // Start out with no one at all viewing it. $context['view_members'] = array(); $context['view_members_list'] = array(); $context['view_num_hidden'] = 0; // Search for members who have this topic set in their GET data. $request = smf_db_query(' SELECT lo.id_member, lo.log_time, mem.real_name, mem.member_name, mem.show_online, mem.id_group, mem.id_post_group FROM {db_prefix}log_online AS lo LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member) WHERE INSTR(lo.url, {string:in_url_string}) > 0 OR lo.session = {string:session}', array('in_url_string' => 's:5:"topic";i:' . $topic . ';', 'session' => $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id())); while ($row = mysql_fetch_assoc($request)) { if (empty($row['id_member'])) { continue; } $class = 'member group_' . (empty($row['id_group']) ? $row['id_post_group'] : $row['id_group']) . (in_array($row['id_member'], $user_info['buddies']) ? ' buddy' : ''); $href = URL::user($row['id_member'], $row['real_name']); if ($row['id_member'] == $user_info['id']) { $link = '<strong>' . $txt['you'] . '</strong>'; } else { $link = '<a onclick="getMcard(' . $row['id_member'] . ');return(false);" class="' . $class . '" href="' . $href . '">' . $row['real_name'] . '</a>'; } // Add them both to the list and to the more detailed list. if (!empty($row['show_online']) || allowedTo('moderate_forum')) { $context['view_members_list'][$row['log_time'] . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link; } $context['view_members'][$row['log_time'] . $row['member_name']] = array('id' => $row['id_member'], 'username' => $row['member_name'], 'name' => $row['real_name'], 'group' => $row['id_group'], 'href' => $href, 'link' => $link, 'hidden' => empty($row['show_online'])); if (empty($row['show_online'])) { $context['view_num_hidden']++; } } // The number of guests is equal to the rows minus the ones we actually used ;). $context['view_num_guests'] = mysql_num_rows($request) - count($context['view_members']); mysql_free_result($request); // Sort the list. krsort($context['view_members']); krsort($context['view_members_list']); } // If all is set, but not allowed... just unset it. $can_show_all = !empty($modSettings['enableAllMessages']) && $context['total_visible_posts'] > $context['messages_per_page'] && $context['total_visible_posts'] < $modSettings['enableAllMessages']; if (isset($_REQUEST['all']) && !$can_show_all) { unset($_REQUEST['all']); } elseif (isset($_REQUEST['all'])) { $_REQUEST['start'] = -1; } // Construct the page index, allowing for the .START method... if (!isset($_REQUEST['perma'])) { $context['page_index'] = constructPageIndex(URL::topic($topic, $topicinfo['subject'], '%1$d'), $_REQUEST['start'], $context['total_visible_posts'], $context['messages_per_page'], true); } $context['start'] = $_REQUEST['start']; // This is information about which page is current, and which page we're on - in case you don't like the constructed page index. (again, wireles..) $context['page_info'] = array('current_page' => $_REQUEST['start'] / $context['messages_per_page'] + 1, 'num_pages' => floor(($context['total_visible_posts'] - 1) / $context['messages_per_page']) + 1); $context['links'] = array('first' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.0' : '', 'prev' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] - $context['messages_per_page']) : '', 'next' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] + $context['messages_per_page']) : '', 'last' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . floor($context['total_visible_posts'] / $context['messages_per_page']) * $context['messages_per_page'] : '', 'up' => $scripturl . '?board=' . $board . '.0'); // If they are viewing all the posts, show all the posts, otherwise limit the number. if ($can_show_all) { if (isset($_REQUEST['all'])) { // No limit! (actually, there is a limit, but...) $context['messages_per_page'] = -1; $context['page_index'] .= '[<strong>' . $txt['all'] . '</strong>] '; // Set start back to 0... $_REQUEST['start'] = 0; } else { if (!isset($context['page_index'])) { $context['page_index'] = ''; } $context['page_index'] .= ' <a href="' . $scripturl . '?topic=' . $topic . '.0;all">' . $txt['all'] . '</a> '; } } // Build the link tree. $context['linktree'][] = array('url' => URL::topic($topic, $topicinfo['subject'], 0), 'name' => $topicinfo['subject'], 'extra_before' => $settings['linktree_inline'] ? $txt['topic'] . ': ' : ''); // Build a list of this board's moderators. $context['moderators'] =& $board_info['moderators']; $context['link_moderators'] = array(); if (!empty($board_info['moderators'])) { // Add a link for each moderator... foreach ($board_info['moderators'] as $mod) { $context['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $mod['id'] . '" title="' . $txt['board_moderator'] . '">' . $mod['name'] . '</a>'; } // And show it after the board's name. //$context['linktree'][count($context['linktree']) - 2]['extra_after'] = ' (' . (count($context['link_moderators']) == 1 ? $txt['moderator'] : $txt['moderators']) . ': ' . implode(', ', $context['link_moderators']) . ')'; } // Information about the current topic... $context['is_locked'] = $topicinfo['locked']; $context['is_sticky'] = $topicinfo['is_sticky']; $context['is_very_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicVeryPosts']; $context['is_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicPosts']; $context['is_approved'] = $topicinfo['approved']; // We don't want to show the poll icon in the topic class here, so pretend it's not one. $context['is_poll'] = false; determineTopicClass($context); $context['is_poll'] = $topicinfo['id_poll'] > 0 && $modSettings['pollMode'] == '1' && allowedTo('poll_view'); // Did this user start the topic or not? $context['user']['started'] = $user_info['id'] == $topicinfo['id_member_started'] && !$user_info['is_guest']; $context['topic_starter_id'] = $topicinfo['id_member_started']; // Set the topic's information for the template. $context['subject'] = $topicinfo['subject']; $context['num_views'] = $topicinfo['num_views']; $context['mark_unread_time'] = $topicinfo['new_from']; // Set a canonical URL for this page. $context['canonical_url'] = URL::topic($topic, $topicinfo['subject'], $context['start']); $context['share_url'] = $scripturl . '?topic=' . $topic; // For quick reply we need a response prefix in the default forum language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix', 600))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } CacheAPI::putCache('response_prefix', $context['response_prefix'], 600); } // If we want to show event information in the topic, prepare the data. if (allowedTo('calendar_view') && !empty($modSettings['cal_showInTopic']) && !empty($modSettings['cal_enabled'])) { // First, try create a better time format, ignoring the "time" elements. if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) { $date_string = $user_info['time_format']; } else { $date_string = $matches[0]; } // Any calendar information for this topic? $request = smf_db_query(' SELECT cal.id_event, cal.start_date, cal.end_date, cal.title, cal.id_member, mem.real_name FROM {db_prefix}calendar AS cal LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = cal.id_member) WHERE cal.id_topic = {int:current_topic} ORDER BY start_date', array('current_topic' => $topic)); $context['linked_calendar_events'] = array(); while ($row = mysql_fetch_assoc($request)) { // Prepare the dates for being formatted. $start_date = sscanf($row['start_date'], '%04d-%02d-%02d'); $start_date = mktime(12, 0, 0, $start_date[1], $start_date[2], $start_date[0]); $end_date = sscanf($row['end_date'], '%04d-%02d-%02d'); $end_date = mktime(12, 0, 0, $end_date[1], $end_date[2], $end_date[0]); $context['linked_calendar_events'][] = array('id' => $row['id_event'], 'title' => $row['title'], 'can_edit' => allowedTo('calendar_edit_any') || $row['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own'), 'modify_href' => $scripturl . '?action=post;msg=' . $topicinfo['id_first_msg'] . ';topic=' . $topic . '.0;calendar;eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], 'start_date' => timeformat_static($start_date, $date_string, 'none'), 'start_timestamp' => $start_date, 'end_date' => timeformat_static($end_date, $date_string, 'none'), 'end_timestamp' => $end_date, 'is_last' => false); } mysql_free_result($request); if (!empty($context['linked_calendar_events'])) { $context['linked_calendar_events'][count($context['linked_calendar_events']) - 1]['is_last'] = true; } } // Create the poll info if it exists. if ($context['is_poll']) { // Get the question and if it's locked. $request = smf_db_query(' SELECT p.question, p.voting_locked, p.hide_results, p.expire_time, p.max_votes, p.change_vote, p.guest_vote, p.id_member, IFNULL(mem.real_name, p.poster_name) AS poster_name, p.num_guest_voters, p.reset_poll FROM {db_prefix}polls AS p LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = p.id_member) WHERE p.id_poll = {int:id_poll} LIMIT 1', array('id_poll' => $topicinfo['id_poll'])); $pollinfo = mysql_fetch_assoc($request); mysql_free_result($request); $request = smf_db_query(' SELECT COUNT(DISTINCT id_member) AS total FROM {db_prefix}log_polls WHERE id_poll = {int:id_poll} AND id_member != {int:not_guest}', array('id_poll' => $topicinfo['id_poll'], 'not_guest' => 0)); list($pollinfo['total']) = mysql_fetch_row($request); mysql_free_result($request); // Total voters needs to include guest voters $pollinfo['total'] += $pollinfo['num_guest_voters']; // Get all the options, and calculate the total votes. $request = smf_db_query(' SELECT pc.id_choice, pc.label, pc.votes, IFNULL(lp.id_choice, -1) AS voted_this FROM {db_prefix}poll_choices AS pc LEFT JOIN {db_prefix}log_polls AS lp ON (lp.id_choice = pc.id_choice AND lp.id_poll = {int:id_poll} AND lp.id_member = {int:current_member} AND lp.id_member != {int:not_guest}) WHERE pc.id_poll = {int:id_poll}', array('current_member' => $user_info['id'], 'id_poll' => $topicinfo['id_poll'], 'not_guest' => 0)); $pollOptions = array(); $realtotal = 0; $pollinfo['has_voted'] = false; while ($row = mysql_fetch_assoc($request)) { censorText($row['label']); $pollOptions[$row['id_choice']] = $row; $realtotal += $row['votes']; $pollinfo['has_voted'] |= $row['voted_this'] != -1; } mysql_free_result($request); // If this is a guest we need to do our best to work out if they have voted, and what they voted for. if ($user_info['is_guest'] && $pollinfo['guest_vote'] && allowedTo('poll_vote')) { if (!empty($_COOKIE['guest_poll_vote']) && preg_match('~^[0-9,;]+$~', $_COOKIE['guest_poll_vote']) && strpos($_COOKIE['guest_poll_vote'], ';' . $topicinfo['id_poll'] . ',') !== false) { // ;id,timestamp,[vote,vote...]; etc $guestinfo = explode(';', $_COOKIE['guest_poll_vote']); // Find the poll we're after. foreach ($guestinfo as $i => $guestvoted) { $guestvoted = explode(',', $guestvoted); if ($guestvoted[0] == $topicinfo['id_poll']) { break; } } // Has the poll been reset since guest voted? if ($pollinfo['reset_poll'] > $guestvoted[1]) { // Remove the poll info from the cookie to allow guest to vote again unset($guestinfo[$i]); if (!empty($guestinfo)) { $_COOKIE['guest_poll_vote'] = ';' . implode(';', $guestinfo); } else { unset($_COOKIE['guest_poll_vote']); } } else { // What did they vote for? unset($guestvoted[0], $guestvoted[1]); foreach ($pollOptions as $choice => $details) { $pollOptions[$choice]['voted_this'] = in_array($choice, $guestvoted) ? 1 : -1; $pollinfo['has_voted'] |= $pollOptions[$choice]['voted_this'] != -1; } unset($choice, $details, $guestvoted); } unset($guestinfo, $guestvoted, $i); } } // Set up the basic poll information. $context['poll'] = array('id' => $topicinfo['id_poll'], 'image' => 'normal_' . (empty($pollinfo['voting_locked']) ? 'poll' : 'locked_poll'), 'question' => parse_bbc($pollinfo['question']), 'total_votes' => $pollinfo['total'], 'change_vote' => !empty($pollinfo['change_vote']), 'is_locked' => !empty($pollinfo['voting_locked']), 'options' => array(), 'lock' => allowedTo('poll_lock_any') || $context['user']['started'] && allowedTo('poll_lock_own'), 'edit' => allowedTo('poll_edit_any') || $context['user']['started'] && allowedTo('poll_edit_own'), 'allowed_warning' => $pollinfo['max_votes'] > 1 ? sprintf($txt['poll_options6'], min(count($pollOptions), $pollinfo['max_votes'])) : '', 'is_expired' => !empty($pollinfo['expire_time']) && $pollinfo['expire_time'] < time(), 'expire_time' => !empty($pollinfo['expire_time']) ? timeformat($pollinfo['expire_time']) : 0, 'has_voted' => !empty($pollinfo['has_voted']), 'starter' => array('id' => $pollinfo['id_member'], 'name' => $row['poster_name'], 'href' => $pollinfo['id_member'] == 0 ? '' : $scripturl . '?action=profile;u=' . $pollinfo['id_member'], 'link' => $pollinfo['id_member'] == 0 ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $pollinfo['id_member'] . '">' . $row['poster_name'] . '</a>')); // Make the lock and edit permissions defined above more directly accessible. $context['allow_lock_poll'] = $context['poll']['lock']; $context['allow_edit_poll'] = $context['poll']['edit']; // You're allowed to vote if: // 1. the poll did not expire, and // 2. you're either not a guest OR guest voting is enabled... and // 3. you're not trying to view the results, and // 4. the poll is not locked, and // 5. you have the proper permissions, and // 6. you haven't already voted before. $context['allow_vote'] = !$context['poll']['is_expired'] && (!$user_info['is_guest'] || $pollinfo['guest_vote'] && allowedTo('poll_vote')) && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && !$context['poll']['has_voted']; // You're allowed to view the results if: // 1. you're just a super-nice-guy, or // 2. anyone can see them (hide_results == 0), or // 3. you can see them after you voted (hide_results == 1), or // 4. you've waited long enough for the poll to expire. (whether hide_results is 1 or 2.) $context['allow_poll_view'] = allowedTo('moderate_board') || $pollinfo['hide_results'] == 0 || $pollinfo['hide_results'] == 1 && $context['poll']['has_voted'] || $context['poll']['is_expired']; $context['poll']['show_results'] = $context['allow_poll_view'] && (isset($_REQUEST['viewresults']) || isset($_REQUEST['viewResults'])); $context['show_view_results_button'] = $context['allow_vote'] && (!$context['allow_poll_view'] || !$context['poll']['show_results'] || !$context['poll']['has_voted']); // You're allowed to change your vote if: // 1. the poll did not expire, and // 2. you're not a guest... and // 3. the poll is not locked, and // 4. you have the proper permissions, and // 5. you have already voted, and // 6. the poll creator has said you can! $context['allow_change_vote'] = !$context['poll']['is_expired'] && !$user_info['is_guest'] && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && $context['poll']['has_voted'] && $context['poll']['change_vote']; // You're allowed to return to voting options if: // 1. you are (still) allowed to vote. // 2. you are currently seeing the results. $context['allow_return_vote'] = $context['allow_vote'] && $context['poll']['show_results']; // Calculate the percentages and bar lengths... $divisor = $realtotal == 0 ? 1 : $realtotal; // Determine if a decimal point is needed in order for the options to add to 100%. $precision = $realtotal == 100 ? 0 : 1; // Now look through each option, and... foreach ($pollOptions as $i => $option) { // First calculate the percentage, and then the width of the bar... $bar = round($option['votes'] * 100 / $divisor, $precision); $barWide = $bar == 0 ? 1 : floor($bar * 8 / 3); // Now add it to the poll's contextual theme data. $context['poll']['options'][$i] = array('id' => 'options-' . $i, 'percent' => $bar, 'votes' => $option['votes'], 'voted_this' => $option['voted_this'] != -1, 'bar' => '<span style="white-space: nowrap;"><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'right' : 'left') . '.gif" alt="" /><img src="' . $settings['images_url'] . '/poll_middle.gif" width="' . $barWide . '" height="12" alt="-" /><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'left' : 'right') . '.gif" alt="" /></span>', 'bar_ndt' => $bar > 0 ? '<div class="bar" style="width: ' . ($bar * 3.5 + 4) . 'px;"></div>' : '', 'bar_width' => $barWide, 'option' => parse_bbc($option['label']), 'vote_button' => '<input type="' . ($pollinfo['max_votes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="input_' . ($pollinfo['max_votes'] > 1 ? 'check' : 'radio') . '" />'); } } // Calculate the fastest way to get the messages! $ascending = empty($options['view_newest_first']); $start = $_REQUEST['start']; $limit = $context['messages_per_page']; $firstIndex = 0; if ($start >= $context['total_visible_posts'] / 2 && $context['messages_per_page'] != -1) { $ascending = !$ascending; $limit = $context['total_visible_posts'] <= $start + $limit ? $context['total_visible_posts'] - $start : $limit; $start = $context['total_visible_posts'] <= $start + $limit ? 0 : $context['total_visible_posts'] - $start - $limit; $firstIndex = $limit - 1; } if (!isset($_REQUEST['perma'])) { // Get each post and poster in this topic. $request = smf_db_query(' SELECT id_msg, id_member, approved FROM {db_prefix}messages WHERE id_topic = {int:current_topic}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : (!empty($modSettings['db_mysql_group_by_fix']) ? '' : ' GROUP BY id_msg') . ' HAVING (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')') . ' ORDER BY id_msg ' . ($ascending ? '' : 'DESC') . ($context['messages_per_page'] == -1 ? '' : ' LIMIT ' . $start . ', ' . $limit), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'is_approved' => 1, 'blank_id_member' => 0)); $messages = array(); $all_posters = array(); while ($row = mysql_fetch_assoc($request)) { if (!empty($row['id_member'])) { $all_posters[$row['id_msg']] = $row['id_member']; } $messages[] = $row['id_msg']; } mysql_free_result($request); $posters[$context['topic_first_message']] = $context['topic_starter_id']; $posters = array_unique($all_posters); } else { $request = smf_db_query(' SELECT id_member, approved FROM {db_prefix}messages WHERE id_msg = {int:id_msg}', array('id_msg' => $virtual_msg)); list($id_member, $approved) = mysql_fetch_row($request); mysql_free_result($request); EoS_Smarty::loadTemplate('topic/topic_singlepost'); //loadTemplate('DisplaySingle'); $context['sub_template'] = isset($_REQUEST['xml']) ? 'single_post_xml' : 'single_post'; if (isset($_REQUEST['xml'])) { $context['template_layers'] = array(); header('Content-Type: text/xml; charset=UTF-8'); } $messages = array($virtual_msg); $posters[$virtual_msg] = $id_member; } // Guests can't mark topics read or for notifications, just can't sorry. if (!$user_info['is_guest']) { $mark_at_msg = max($messages); if ($mark_at_msg >= $topicinfo['id_last_msg']) { $mark_at_msg = $modSettings['maxMsgID']; } if ($mark_at_msg >= $topicinfo['new_from']) { smf_db_insert($topicinfo['new_from'] == 0 ? 'ignore' : 'replace', '{db_prefix}log_topics', array('id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int'), array($user_info['id'], $topic, $mark_at_msg), array('id_member', 'id_topic')); } // Check for notifications on this topic OR board. $request = smf_db_query(' SELECT sent, id_topic FROM {db_prefix}log_notify WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board}) AND id_member = {int:current_member} LIMIT 2', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic)); $do_once = true; while ($row = mysql_fetch_assoc($request)) { // Find if this topic is marked for notification... if (!empty($row['id_topic'])) { $context['is_marked_notify'] = true; } // Only do this once, but mark the notifications as "not sent yet" for next time. if (!empty($row['sent']) && $do_once) { smf_db_query(' UPDATE {db_prefix}log_notify SET sent = {int:is_not_sent} WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board}) AND id_member = {int:current_member}', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic, 'is_not_sent' => 0)); $do_once = false; } } // Have we recently cached the number of new topics in this board, and it's still a lot? if (isset($_REQUEST['topicseen']) && isset($_SESSION['topicseen_cache'][$board]) && $_SESSION['topicseen_cache'][$board] > 5) { $_SESSION['topicseen_cache'][$board]--; } elseif (isset($_REQUEST['topicseen'])) { // Use the mark read tables... and the last visit to figure out if this should be read or not. $request = smf_db_query(' SELECT COUNT(*) FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = {int:current_board} AND lb.id_member = {int:current_member}) LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) WHERE t.id_board = {int:current_board} AND t.id_last_msg > IFNULL(lb.id_msg, 0) AND t.id_last_msg > IFNULL(lt.id_msg, 0)' . (empty($_SESSION['id_msg_last_visit']) ? '' : ' AND t.id_last_msg > {int:id_msg_last_visit}'), array('current_board' => $board, 'current_member' => $user_info['id'], 'id_msg_last_visit' => (int) $_SESSION['id_msg_last_visit'])); list($numNewTopics) = mysql_fetch_row($request); mysql_free_result($request); // If there're no real new topics in this board, mark the board as seen. if (empty($numNewTopics)) { $_REQUEST['boardseen'] = true; } else { $_SESSION['topicseen_cache'][$board] = $numNewTopics; } } elseif (isset($_SESSION['topicseen_cache'][$board])) { $_SESSION['topicseen_cache'][$board]--; } // Mark board as seen if we came using last post link from BoardIndex. (or other places...) if (isset($_REQUEST['boardseen'])) { smf_db_insert('replace', '{db_prefix}log_boards', array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), array($modSettings['maxMsgID'], $user_info['id'], $board), array('id_member', 'id_board')); } } $attachments = array(); // deal with possible sticky posts and different postbit layouts for // the first post // topic.id_layout meanings: bit 0-6 > layout id, bit 7 > first post sticky on every page. // don't blame me for using bit magic here. I'm a C guy and a 8bits can store more than just one bool :P $layout = (int) ($topicinfo['id_layout'] & 0x7f); $postbit_classes =& EoS_Smarty::getConfigInstance()->getPostbitClasses(); // set defaults... $context['postbit_callbacks'] = array('firstpost' => 'template_postbit_normal', 'post' => 'template_postbit_normal'); $context['postbit_template_class'] = array('firstpost' => $postbit_classes['normal'], 'post' => $postbit_classes['normal']); if ($topicinfo['id_layout']) { $this_start = isset($_REQUEST['perma']) ? 0 : (int) $_REQUEST['start']; if ((int) $topicinfo['id_layout'] & 0x80) { if ($this_start > 0) { array_unshift($messages, intval($topicinfo['id_first_msg'])); } $context['postbit_callbacks']['firstpost'] = $layout == 0 ? 'template_postbit_normal' : ($layout == 2 ? 'template_postbit_clean' : 'template_postbit_lean'); $context['postbit_callbacks']['post'] = $layout == 2 ? 'template_postbit_comment' : 'template_postbit_normal'; $context['postbit_template_class']['firstpost'] = $layout == 0 ? $postbit_classes['normal'] : ($layout == 2 ? $postbit_classes['article'] : $postbit_classes['lean']); $context['postbit_template_class']['post'] = $layout == 2 ? $postbit_classes['commentstyle'] : $postbit_classes['normal']; } elseif ($layout) { $context['postbit_callbacks']['firstpost'] = $layout == 0 || $this_start != 0 ? 'template_postbit_normal' : ($layout == 2 ? 'template_postbit_clean' : 'template_postbit_lean'); $context['postbit_callbacks']['post'] = $layout == 2 ? 'template_postbit_comment' : 'template_postbit_normal'; $context['postbit_template_class']['firstpost'] = $layout == 0 || $this_start != 0 ? $postbit_classes['normal'] : ($layout == 2 ? $postbit_classes['article'] : $postbit_classes['lean']); $context['postbit_template_class']['post'] = $layout == 2 ? $postbit_classes['commentstyle'] : $postbit_classes['normal']; } } // now we know which display template we need if (!isset($_REQUEST['perma'])) { EoS_Smarty::loadTemplate($layout > 1 ? 'topic/topic_page' : 'topic/topic'); } /* if($user_info['is_admin']) { EoS_Smarty::init(); if(!isset($_REQUEST['perma'])) EoS_Smarty::loadTemplate($layout > 1 ? 'topic_page' : 'topic'); } else { if(!isset($_REQUEST['perma'])) loadTemplate($layout > 1 ? 'DisplayPage' : 'Display'); loadTemplate('Postbit'); } */ // If there _are_ messages here... (probably an error otherwise :!) if (!empty($messages)) { // Fetch attachments. if (!empty($modSettings['attachmentEnable']) && allowedTo('view_attachments')) { $request = smf_db_query(' SELECT a.id_attach, a.id_folder, a.id_msg, a.filename, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved, a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ', IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . ' FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ' LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . ' WHERE a.id_msg IN ({array_int:message_list}) AND a.attachment_type = {int:attachment_type}', array('message_list' => $messages, 'attachment_type' => 0, 'is_approved' => 1)); $temp = array(); while ($row = mysql_fetch_assoc($request)) { if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id'])) { continue; } $temp[$row['id_attach']] = $row; if (!isset($attachments[$row['id_msg']])) { $attachments[$row['id_msg']] = array(); } } mysql_free_result($request); // This is better than sorting it with the query... ksort($temp); foreach ($temp as $row) { $attachments[$row['id_msg']][] = $row; } } // What? It's not like it *couldn't* be only guests in this topic... if (!isset($posters[$context['topic_starter_id']])) { $posters[] = $context['topic_starter_id']; } if (!empty($posters)) { loadMemberData($posters); } if (!isset($user_profile[$context['topic_starter_id']])) { $context['topicstarter']['name'] = $topicinfo['poster_name']; $context['topicstarter']['id'] = 0; $context['topicstarter']['group'] = $txt['guest_title']; $context['topicstarter']['link'] = $topicinfo['poster_name']; $context['topicstarter']['email'] = $topicinfo['poster_email']; $context['topicstarter']['show_email'] = showEmailAddress(true, 0); $context['topicstarter']['is_guest'] = true; $context['topicstarter']['avatar'] = array(); } else { loadMemberContext($context['topic_starter_id'], true); $context['topicstarter'] =& $memberContext[$context['topic_starter_id']]; } $context['topicstarter']['start_time'] = timeformat($topicinfo['first_post_time']); $sql_what = ' m.id_msg, m.icon, m.subject, m.poster_time, m.poster_ip, m.id_member, m.modified_time, m.modified_name, m.body, mc.body AS cached_body, m.smileys_enabled, m.poster_name, m.poster_email, m.approved, m.locked,' . (!empty($modSettings['karmaMode']) ? 'c.likes_count, c.like_status, c.updated AS like_updated, l.rtype AS liked,' : '0 AS likes_count, 0 AS like_status, 0 AS like_updated, 0 AS liked,') . ' m.id_msg_modified < {int:new_from} AS is_read'; $sql_from_tables = ' FROM {db_prefix}messages AS m'; $sql_from_joins = (!empty($modSettings['karmaMode']) ? ' LEFT JOIN {db_prefix}likes AS l ON (l.id_msg = m.id_msg AND l.ctype = 1 AND l.id_user = {int:id_user}) LEFT JOIN {db_prefix}like_cache AS c ON (c.id_msg = m.id_msg AND c.ctype = 1)' : '') . ' LEFT JOIN {db_prefix}messages_cache AS mc on mc.id_msg = m.id_msg AND mc.style = {int:style} AND mc.lang = {int:lang}'; $sql_array = array('message_list' => $messages, 'new_from' => $topicinfo['new_from'], 'style' => $user_info['smiley_set_id'], 'lang' => $user_info['language_id'], 'id_user' => $user_info['id']); HookAPI::callHook('display_messagerequest', array(&$sql_what, &$sql_from_tables, &$sql_from_joins, &$sql_array)); $messages_request = smf_db_query(' SELECT ' . $sql_what . ' ' . $sql_from_tables . $sql_from_joins . ' WHERE m.id_msg IN ({array_int:message_list}) ORDER BY m.id_msg' . (empty($options['view_newest_first']) ? '' : ' DESC'), $sql_array); // Go to the last message if the given time is beyond the time of the last message. if (isset($context['start_from']) && $context['start_from'] >= $topicinfo['num_replies']) { $context['start_from'] = $topicinfo['num_replies']; } // Since the anchor information is needed on the top of the page we load these variables beforehand. $context['first_message'] = isset($messages[$firstIndex]) ? $messages[$firstIndex] : $messages[0]; if (empty($options['view_newest_first'])) { $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['start_from']; } else { $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $topicinfo['num_replies'] - $context['start_from']; } } else { $messages_request = false; $context['first_message'] = 0; $context['first_new_message'] = false; } $context['jump_to'] = array('label' => addslashes(un_htmlspecialchars($txt['jump_to'])), 'board_name' => htmlspecialchars(strtr(strip_tags($board_info['name']), array('&' => '&'))), 'child_level' => $board_info['child_level']); // Set the callback. (do you REALIZE how much memory all the messages would take?!?) $context['get_message'] = 'prepareDisplayContext'; // Now set all the wonderful, wonderful permissions... like moderation ones... $common_permissions = array('can_approve' => 'approve_posts', 'can_ban' => 'manage_bans', 'can_sticky' => 'make_sticky', 'can_merge' => 'merge_any', 'can_split' => 'split_any', 'calendar_post' => 'calendar_post', 'can_mark_notify' => 'mark_any_notify', 'can_send_topic' => 'send_topic', 'can_send_pm' => 'pm_send', 'can_report_moderator' => 'report_any', 'can_moderate_forum' => 'moderate_forum', 'can_issue_warning' => 'issue_warning', 'can_restore_topic' => 'move_any', 'can_restore_msg' => 'move_any'); foreach ($common_permissions as $contextual => $perm) { $context[$contextual] = allowedTo($perm); } // Permissions with _any/_own versions. $context[YYY] => ZZZ_any/_own. $anyown_permissions = array('can_move' => 'move', 'can_lock' => 'lock', 'can_delete' => 'remove', 'can_add_poll' => 'poll_add', 'can_remove_poll' => 'poll_remove', 'can_reply' => 'post_reply', 'can_reply_unapproved' => 'post_unapproved_replies'); foreach ($anyown_permissions as $contextual => $perm) { $context[$contextual] = allowedTo($perm . '_any') || $context['user']['started'] && allowedTo($perm . '_own'); } $context['can_add_tags'] = $context['user']['started'] && allowedTo('smftags_add') || allowedTo('smftags_manage'); $context['can_delete_tags'] = $context['user']['started'] && allowedTo('smftags_del') || allowedTo('smftags_manage'); $context['can_moderate_board'] = allowedTo('moderate_board'); $context['can_modify_any'] = allowedTo('modify_any'); $context['can_modify_replies'] = allowedTo('modify_replies'); $context['can_modify_own'] = allowedTo('modify_own'); $context['can_delete_any'] = allowedTo('delete_any'); $context['can_delete_replies'] = allowedTo('delete_replies'); $context['can_delete_own'] = allowedTo('delete_own'); $context['use_share'] = !$user_info['possibly_robot'] && allowedTo('use_share') && ($context['user']['is_guest'] || (empty($options['use_share_bar']) ? 1 : !$options['use_share_bar'])); $context['can_unapprove'] = $context['can_approve'] && !empty($modSettings['postmod_active']); $context['can_profile_view_any'] = allowedTo('profile_view_any'); $context['can_profile_view_own'] = allowedTo('profile_view_own'); $context['is_banned_from_topic'] = !$user_info['is_admin'] && !$context['can_moderate_forum'] && !$context['can_moderate_board'] && (!empty($context['topic_banned_members']) ? in_array($user_info['id'], $context['topic_banned_members']) : false); $context['banned_notice'] = $context['is_banned_from_topic'] ? $txt['topic_banned_notice'] : ''; // Cleanup all the permissions with extra stuff... $context['can_mark_notify'] &= !$context['user']['is_guest']; $context['can_sticky'] &= !empty($modSettings['enableStickyTopics']); $context['calendar_post'] &= !empty($modSettings['cal_enabled']); $context['can_add_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['id_poll'] <= 0; $context['can_remove_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['id_poll'] > 0; $context['can_reply'] &= empty($topicinfo['locked']) || allowedTo('moderate_board'); $context['can_reply_unapproved'] &= $modSettings['postmod_active'] && (empty($topicinfo['locked']) || allowedTo('moderate_board')); $context['can_issue_warning'] &= in_array('w', $context['admin_features']) && $modSettings['warning_settings'][0] == 1; // Handle approval flags... $context['can_reply_approved'] = $context['can_reply']; $context['can_reply'] |= $context['can_reply_unapproved']; $context['can_quote'] = $context['can_reply'] && (empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']))); $context['can_mark_unread'] = !$user_info['is_guest'] && $settings['show_mark_read']; $context['can_send_topic'] = (!$modSettings['postmod_active'] || $topicinfo['approved']) && allowedTo('send_topic'); // Start this off for quick moderation - it will be or'd for each post. $context['can_remove_post'] = allowedTo('delete_any') || allowedTo('delete_replies') && $context['user']['started']; // Can restore topic? That's if the topic is in the recycle board and has a previous restore state. $context['can_restore_topic'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_board']); $context['can_restore_msg'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_topic']); if ($context['is_banned_from_topic']) { $context['can_add_tags'] = $context['can_delete_tags'] = $context['can_modify_any'] = $context['can_modify_replies'] = $context['can_modify_own'] = $context['can_delete_any'] = $context['can_delete_replies'] = $context['can_delete_own'] = $context['can_lock'] = $context['can_sticky'] = $context['calendar_post'] = $context['can_add_poll'] = $context['can_remove_poll'] = $context['can_reply'] = $context['can_reply_unapproved'] = $context['can_quote'] = $context['can_remove_post'] = false; } // Load up the "double post" sequencing magic. if (!empty($options['display_quick_reply'])) { checkSubmitOnce('register'); $context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : ''; $context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : ''; } // todo: drafts -> plugin $context['can_save_draft'] = false; //$context['can_reply'] && !$context['user']['is_guest'] && in_array('dr', $context['admin_features']) && !empty($options['use_drafts']) && allowedTo('drafts_allow'); $context['can_autosave_draft'] = false; //$context['can_save_draft'] && !empty($modSettings['enableAutoSaveDrafts']) && allowedTo('drafts_autosave_allow'); enqueueThemeScript('topic', 'scripts/topic.js', true); if ($context['can_autosave_draft']) { enqueueThemeScript('drafts', 'scripts/drafts.js', true); } $context['can_moderate_member'] = $context['can_issue_warning'] || $context['can_moderate_board']; $context['topic_has_banned_members_msg'] = $context['topic_banned_members_count'] > 0 && $context['can_moderate_board'] ? sprintf($txt['topic_has_bans_msg'], URL::parse('?action=moderate;area=topicbans;sa=bytopic;t=' . $topic)) : ''; if (EoS_Smarty::isActive()) { if (isset($context['poll'])) { $context['poll_buttons'] = array('vote' => array('test' => 'allow_return_vote', 'text' => 'poll_return_vote', 'image' => 'poll_options.gif', 'lang' => true, 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start']), 'results' => array('test' => 'show_view_results_button', 'text' => 'poll_results', 'image' => 'poll_results.gif', 'lang' => true, 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start'] . ';viewresults'), 'change_vote' => array('test' => 'allow_change_vote', 'text' => 'poll_change_vote', 'image' => 'poll_change_vote.gif', 'lang' => true, 'url' => $scripturl . '?action=vote;topic=' . $context['current_topic'] . '.' . $context['start'] . ';poll=' . $context['poll']['id'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'lock' => array('test' => 'allow_lock_poll', 'text' => !$context['poll']['is_locked'] ? 'poll_lock' : 'poll_unlock', 'image' => 'poll_lock.gif', 'lang' => true, 'url' => $scripturl . '?action=lockvoting;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'edit' => array('test' => 'allow_edit_poll', 'text' => 'poll_edit', 'image' => 'poll_edit.gif', 'lang' => true, 'url' => $scripturl . '?action=editpoll;topic=' . $context['current_topic'] . '.' . $context['start']), 'remove_poll' => array('test' => 'can_remove_poll', 'text' => 'poll_remove', 'image' => 'admin_remove_poll.gif', 'lang' => true, 'custom' => 'onclick="return Eos_Confirm(\'\', \'' . $txt['poll_remove_warn'] . '\', $(this).attr(\'href\'));"', 'url' => $scripturl . '?action=removepoll;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id'])); } $context['normal_buttons'] = array('reply' => array('test' => 'can_reply', 'text' => 'reply', 'custom' => 'onclick="return oQuickReply.quote(0);" ', 'image' => 'reply.gif', 'lang' => true, 'url' => $scripturl . '?action=post;topic=' . $context['current_topic'] . '.' . $context['start'] . ';last_msg=' . $context['topic_last_message'], 'active' => true), 'add_poll' => array('test' => 'can_add_poll', 'text' => 'add_poll', 'image' => 'add_poll.gif', 'lang' => true, 'url' => $scripturl . '?action=editpoll;add;topic=' . $context['current_topic'] . '.' . $context['start']), 'mark_unread' => array('test' => 'can_mark_unread', 'text' => 'mark_unread', 'image' => 'markunread.gif', 'lang' => true, 'url' => $scripturl . '?action=markasread;sa=topic;t=' . $context['mark_unread_time'] . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id'])); HookAPI::callHook('integrate_display_buttons', array(&$context['normal_buttons'])); $remove_url = $scripturl . '?action=removetopic2;topic=' . $context['current_topic'] . '.0;' . $context['session_var'] . '=' . $context['session_id']; $context['mod_buttons'] = array('move' => array('test' => 'can_move', 'text' => 'move_topic', 'image' => 'admin_move.gif', 'lang' => true, 'url' => $scripturl . '?action=movetopic;topic=' . $context['current_topic'] . '.0'), 'delete' => array('test' => 'can_delete', 'text' => 'remove_topic', 'image' => 'admin_rem.gif', 'lang' => true, 'custom' => 'onclick="return Eos_Confirm(\'\',\'' . $txt['are_sure_remove_topic'] . '\',\'' . $remove_url . '\');"', 'url' => $remove_url), 'lock' => array('test' => 'can_lock', 'text' => empty($context['is_locked']) ? 'set_lock' : 'set_unlock', 'image' => 'admin_lock.gif', 'lang' => true, 'url' => $scripturl . '?action=lock;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'sticky' => array('test' => 'can_sticky', 'text' => empty($context['is_sticky']) ? 'set_sticky' : 'set_nonsticky', 'image' => 'admin_sticky.gif', 'lang' => true, 'url' => $scripturl . '?action=sticky;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'merge' => array('test' => 'can_merge', 'text' => 'merge', 'image' => 'merge.gif', 'lang' => true, 'url' => $scripturl . '?action=mergetopics;board=' . $context['current_board'] . '.0;from=' . $context['current_topic']), 'calendar' => array('test' => 'calendar_post', 'text' => 'calendar_link', 'image' => 'linktocal.gif', 'lang' => true, 'url' => $scripturl . '?action=post;calendar;msg=' . $context['topic_first_message'] . ';topic=' . $context['current_topic'] . '.0')); // Restore topic. eh? No monkey business. if ($context['can_restore_topic']) { $context['mod_buttons'][] = array('text' => 'restore_topic', 'image' => '', 'lang' => true, 'url' => $scripturl . '?action=restoretopic;topics=' . $context['current_topic'] . ';' . $context['session_var'] . '=' . $context['session_id']); } // Allow adding new mod buttons easily. HookAPI::callHook('integrate_mod_buttons', array(&$context['mod_buttons'])); $context['message_ids'] = $messages; $context['perma_request'] = isset($_REQUEST['perma']) ? true : false; $context['mod_buttons_style'] = array('id' => 'moderationbuttons_strip', 'class' => 'buttonlist'); $context['full_members_viewing_list'] = empty($context['view_members_list']) ? '0 ' . $txt['members'] : implode(', ', $context['view_members_list']) . (empty($context['view_num_hidden']) || $context['can_moderate_forum'] ? '' : ' (+ ' . $context['view_num_hidden'] . ' ' . $txt['hidden'] . ')'); } fetchNewsItems($board, $topic); HookAPI::callHook('display_general', array()); /* * $message is always available in templates as global variable * prepareDisplayContext() just repopulates it and is called from * the topic display template via $SUPPORT object callback. */ EoS_Smarty::getSmartyInstance()->assignByRef('message', $output); }
function MembergroupMembers() { global $txt, $scripturl, $context, $modSettings, $sourcedir, $user_info, $settings, $smcFunc; $_REQUEST['group'] = isset($_REQUEST['group']) ? (int) $_REQUEST['group'] : 0; // No browsing of guests, membergroup 0 or moderators. if (in_array($_REQUEST['group'], array(-1, 0, 3))) { fatal_lang_error('membergroup_does_not_exist', false); } // Load up the group details. $request = smf_db_query(' SELECT id_group AS id, group_name AS name, CASE WHEN min_posts = {int:min_posts} THEN 1 ELSE 0 END AS assignable, hidden, online_color, stars, description, CASE WHEN min_posts != {int:min_posts} THEN 1 ELSE 0 END AS is_post_group, group_type FROM {db_prefix}membergroups WHERE id_group = {int:id_group} LIMIT 1', array('min_posts' => -1, 'id_group' => $_REQUEST['group'])); // Doesn't exist? if (mysql_num_rows($request) == 0) { fatal_lang_error('membergroup_does_not_exist', false); } $context['group'] = mysql_fetch_assoc($request); mysql_free_result($request); // Fix the stars. $context['group']['stars'] = explode('#', $context['group']['stars']); $context['group']['stars'] = !empty($context['group']['stars'][0]) && !empty($context['group']['stars'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/' . $context['group']['stars'][1] . '" alt="*" />', $context['group']['stars'][0]) : ''; $context['group']['can_moderate'] = allowedTo('manage_membergroups') && (allowedTo('admin_forum') || $context['group']['group_type'] != 1); $context['linktree'][] = array('url' => $scripturl . '?action=groups;sa=members;group=' . $context['group']['id'], 'name' => $context['group']['name']); // Load all the group moderators, for fun. $request = smf_db_query(' SELECT mem.id_member, mem.real_name FROM {db_prefix}group_moderators AS mods INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member) WHERE mods.id_group = {int:id_group}', array('id_group' => $_REQUEST['group'])); $context['group']['moderators'] = array(); while ($row = mysql_fetch_assoc($request)) { $context['group']['moderators'][] = array('id' => $row['id_member'], 'name' => $row['real_name']); if ($user_info['id'] == $row['id_member'] && $context['group']['group_type'] != 1) { $context['group']['can_moderate'] = true; } } mysql_free_result($request); // If this group is hidden then it can only "exists" if the user can moderate it! if ($context['group']['hidden'] && !$context['group']['can_moderate']) { fatal_lang_error('membergroup_does_not_exist', false); } // You can only assign membership if you are the moderator and/or can manage groups! if (!$context['group']['can_moderate']) { $context['group']['assignable'] = 0; } elseif ($context['group']['id'] == 1 && !allowedTo('admin_forum')) { $context['group']['assignable'] = 0; } // Removing member from group? if (isset($_POST['remove']) && !empty($_REQUEST['rem']) && is_array($_REQUEST['rem']) && $context['group']['assignable']) { checkSession(); // Make sure we're dealing with integers only. foreach ($_REQUEST['rem'] as $key => $group) { $_REQUEST['rem'][$key] = (int) $group; } require_once $sourcedir . '/lib/Subs-Membergroups.php'; removeMembersFromGroups($_REQUEST['rem'], $_REQUEST['group'], true); } elseif (isset($_REQUEST['add']) && (!empty($_REQUEST['toAdd']) || !empty($_REQUEST['member_add'])) && $context['group']['assignable']) { checkSession(); $member_query = array(); $member_parameters = array(); // Get all the members to be added... taking into account names can be quoted ;) $_REQUEST['toAdd'] = strtr(commonAPI::htmlspecialchars($_REQUEST['toAdd'], ENT_QUOTES), array('"' => '"')); preg_match_all('~"([^"]+)"~', $_REQUEST['toAdd'], $matches); $member_names = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_REQUEST['toAdd'])))); foreach ($member_names as $index => $member_name) { $member_names[$index] = trim(commonAPI::strtolower($member_names[$index])); if (strlen($member_names[$index]) == 0) { unset($member_names[$index]); } } // Any passed by ID? $member_ids = array(); if (!empty($_REQUEST['member_add'])) { foreach ($_REQUEST['member_add'] as $id) { if ($id > 0) { $member_ids[] = (int) $id; } } } // Construct the query pelements. if (!empty($member_ids)) { $member_query[] = 'id_member IN ({array_int:member_ids})'; $member_parameters['member_ids'] = $member_ids; } if (!empty($member_names)) { $member_query[] = 'LOWER(member_name) IN ({array_string:member_names})'; $member_query[] = 'LOWER(real_name) IN ({array_string:member_names})'; $member_parameters['member_names'] = $member_names; } $members = array(); if (!empty($member_query)) { $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE (' . implode(' OR ', $member_query) . ') AND id_group != {int:id_group} AND FIND_IN_SET({int:id_group}, additional_groups) = 0', array_merge($member_parameters, array('id_group' => $_REQUEST['group']))); while ($row = mysql_fetch_assoc($request)) { $members[] = $row['id_member']; } mysql_free_result($request); } // !!! Add $_POST['additional'] to templates! // Do the updates... if (!empty($members)) { require_once $sourcedir . '/lib/Subs-Membergroups.php'; addMembersToGroup($members, $_REQUEST['group'], isset($_POST['additional']) || $context['group']['hidden'] ? 'only_additional' : 'auto', true); } } // Sort out the sorting! $sort_methods = array('name' => 'real_name', 'email' => allowedTo('moderate_forum') ? 'email_address' : 'hide_email ' . (isset($_REQUEST['desc']) ? 'DESC' : 'ASC') . ', email_address', 'active' => 'last_login', 'registered' => 'date_registered', 'posts' => 'posts'); // They didn't pick one, default to by name.. if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']])) { $context['sort_by'] = 'name'; $querySort = 'real_name'; } else { $context['sort_by'] = $_REQUEST['sort']; $querySort = $sort_methods[$_REQUEST['sort']]; } $context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up'; // The where on the query is interesting. Non-moderators should only see people who are in this group as primary. if ($context['group']['can_moderate']) { $where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group} OR FIND_IN_SET({int:group}, additional_groups) != 0'; } else { $where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group}'; } // Count members of the group. $request = smf_db_query(' SELECT COUNT(*) FROM {db_prefix}members WHERE ' . $where, array('group' => $_REQUEST['group'])); list($context['total_members']) = mysql_fetch_row($request); mysql_free_result($request); $context['total_members'] = comma_format($context['total_members']); // Create the page index. $context['page_index'] = constructPageIndex($scripturl . '?action=' . ($context['group']['can_moderate'] ? 'moderate;area=viewgroups' : 'groups') . ';sa=members;group=' . $_REQUEST['group'] . ';sort=' . $context['sort_by'] . (isset($_REQUEST['desc']) ? ';desc' : ''), $_REQUEST['start'], $context['total_members'], $modSettings['defaultMaxMembers']); $context['start'] = $_REQUEST['start']; $context['can_moderate_forum'] = allowedTo('moderate_forum'); // Load up all members of this group. $request = smf_db_query(' SELECT id_member, member_name, real_name, email_address, member_ip, date_registered, last_login, hide_email, posts, is_activated, real_name FROM {db_prefix}members WHERE ' . $where . ' ORDER BY ' . $querySort . ' ' . ($context['sort_direction'] == 'down' ? 'DESC' : 'ASC') . ' LIMIT ' . $context['start'] . ', ' . $modSettings['defaultMaxMembers'], array('group' => $_REQUEST['group'])); $context['members'] = array(); while ($row = mysql_fetch_assoc($request)) { $last_online = empty($row['last_login']) ? $txt['never'] : timeformat($row['last_login']); // Italicize the online note if they aren't activated. if ($row['is_activated'] % 10 != 1) { $last_online = '<em title="' . $txt['not_activated'] . '">' . $last_online . '</em>'; } $context['members'][] = array('id' => $row['id_member'], 'name' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', 'email' => $row['email_address'], 'show_email' => showEmailAddress(!empty($row['hide_email']), $row['id_member']), 'ip' => '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>', 'registered' => timeformat($row['date_registered']), 'last_online' => $last_online, 'posts' => comma_format($row['posts']), 'is_activated' => $row['is_activated'] % 10 == 1); } mysql_free_result($request); if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'moderate') { EoS_Smarty::loadTemplate('modcenter/modcenter_base'); EoS_Smarty::getConfigInstance()->registerHookTemplate('modcenter_content_area', 'admin/group_list_members'); } else { $context['sub_template'] = 'group_members'; } $context['page_title'] = $txt['membergroups_members_title'] . ': ' . $context['group']['name']; }
function MoveTopic2() { global $txt, $board, $topic, $scripturl, $sourcedir, $modSettings, $context; global $board, $language, $user_info, $smcFunc; if (empty($topic)) { fatal_lang_error('no_access', false); } // You can't choose to have a redirection topic and use an empty reason. if (isset($_POST['postRedirect']) && (!isset($_POST['reason']) || trim($_POST['reason']) == '')) { fatal_lang_error('movetopic_no_reason', false); } // Make sure this form hasn't been submitted before. checkSubmitOnce('check'); $request = smf_db_query(' SELECT id_member_started, id_first_msg, approved FROM {db_prefix}topics WHERE id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic)); list($id_member_started, $id_first_msg, $context['is_approved']) = mysql_fetch_row($request); mysql_free_result($request); // Can they see it? if (!$context['is_approved']) { isAllowedTo('approve_posts'); } // Can they move topics on this board? if (!allowedTo('move_any')) { if ($id_member_started == $user_info['id']) { isAllowedTo('move_own'); $boards = array_merge(boardsAllowedTo('move_own'), boardsAllowedTo('move_any')); } else { isAllowedTo('move_any'); } } else { $boards = boardsAllowedTo('move_any'); } // If this topic isn't approved don't let them move it if they can't approve it! if ($modSettings['postmod_active'] && !$context['is_approved'] && !allowedTo('approve_posts')) { // Only allow them to move it to other boards they can't approve it in. $can_approve = boardsAllowedTo('approve_posts'); $boards = array_intersect($boards, $can_approve); } checkSession(); require_once $sourcedir . '/lib/Subs-Post.php'; // The destination board must be numeric. $_POST['toboard'] = (int) $_POST['toboard']; // Make sure they can see the board they are trying to move to (and get whether posts count in the target board). $request = smf_db_query(' SELECT b.count_posts, b.name, m.subject FROM {db_prefix}boards AS b INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic}) INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) WHERE {query_see_board} AND b.id_board = {int:to_board} AND b.redirect = {string:blank_redirect} LIMIT 1', array('current_topic' => $topic, 'to_board' => $_POST['toboard'], 'blank_redirect' => '')); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board'); } list($pcounter, $board_name, $subject) = mysql_fetch_row($request); mysql_free_result($request); // Remember this for later. $_SESSION['move_to_topic'] = $_POST['toboard']; // Rename the topic... if (isset($_POST['reset_subject'], $_POST['custom_subject']) && $_POST['custom_subject'] != '') { $_POST['custom_subject'] = strtr(commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['custom_subject'])), array("\r" => '', "\n" => '', "\t" => '')); // Keep checking the length. if (commonAPI::strlen($_POST['custom_subject']) > 100) { $_POST['custom_subject'] = commonAPI::substr($_POST['custom_subject'], 0, 100); } // If it's still valid move onwards and upwards. if ($_POST['custom_subject'] != '') { if (isset($_POST['enforce_subject'])) { // Get a response prefix, but in the forum's default language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } CacheAPI::putCache('response_prefix', $context['response_prefix'], 600); } smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:subject} WHERE id_topic = {int:current_topic}', array('current_topic' => $topic, 'subject' => $context['response_prefix'] . $_POST['custom_subject'])); } smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:custom_subject} WHERE id_msg = {int:id_first_msg}', array('id_first_msg' => $id_first_msg, 'custom_subject' => $_POST['custom_subject'])); // Fix the subject cache. updateStats('subject', $topic, $_POST['custom_subject']); } } // Create a link to this in the old board. //!!! Does this make sense if the topic was unapproved before? I'd just about say so. if (isset($_POST['postRedirect'])) { // Should be in the boardwide language. if ($user_info['language'] != $language) { loadLanguage('index', $language); } $_POST['reason'] = commonAPI::htmlspecialchars($_POST['reason'], ENT_QUOTES); preparsecode($_POST['reason']); // Add a URL onto the message. $_POST['reason'] = strtr($_POST['reason'], array($txt['movetopic_auto_board'] => '[url=' . $scripturl . '?board=' . $_POST['toboard'] . '.0]' . $board_name . '[/url]', $txt['movetopic_auto_topic'] => '[iurl]' . $scripturl . '?topic=' . $topic . '.0[/iurl]')); $msgOptions = array('subject' => $txt['moved'] . ': ' . $subject, 'body' => $_POST['reason'], 'icon' => 'moved', 'smileys_enabled' => 1); $topicOptions = array('board' => $board, 'lock_mode' => 1, 'mark_as_read' => true, 'topic_prefix' => 0, 'topic_layout' => 0); $posterOptions = array('id' => $user_info['id'], 'update_post_count' => empty($pcounter)); createPost($msgOptions, $topicOptions, $posterOptions); } $request = smf_db_query(' SELECT count_posts FROM {db_prefix}boards WHERE id_board = {int:current_board} LIMIT 1', array('current_board' => $board)); list($pcounter_from) = mysql_fetch_row($request); mysql_free_result($request); if ($pcounter_from != $pcounter) { $request = smf_db_query(' SELECT id_member FROM {db_prefix}messages WHERE id_topic = {int:current_topic} AND approved = {int:is_approved}', array('current_topic' => $topic, 'is_approved' => 1)); $posters = array(); while ($row = mysql_fetch_assoc($request)) { if (!isset($posters[$row['id_member']])) { $posters[$row['id_member']] = 0; } $posters[$row['id_member']]++; } mysql_free_result($request); foreach ($posters as $id_member => $posts) { // The board we're moving from counted posts, but not to. if (empty($pcounter_from)) { updateMemberData($id_member, array('posts' => 'posts - ' . $posts)); } else { updateMemberData($id_member, array('posts' => 'posts + ' . $posts)); } } } // Do the move (includes statistics update needed for the redirect topic). moveTopics($topic, $_POST['toboard']); // Log that they moved this topic. if (!allowedTo('move_own') || $id_member_started != $user_info['id']) { logAction('move', array('topic' => $topic, 'board_from' => $board, 'board_to' => $_POST['toboard'])); } // Notify people that this topic has been moved? sendNotifications($topic, 'move'); // Why not go back to the original board in case they want to keep moving? if (!isset($_REQUEST['goback'])) { redirectexit('board=' . $board . '.0'); } else { redirectexit('topic=' . $topic . '.0'); } }
public static function obExit($header = null, $do_footer = null, $from_index = false, $from_fatal_error = false) { global $context, $modSettings; static $header_done = false, $footer_done = false, $level = 0, $has_fatal_error = false; // Attempt to prevent a recursive loop. ++$level; if ($level > 1 && !$from_fatal_error && !$has_fatal_error) { exit; } if ($from_fatal_error) { $has_fatal_error = true; } // Clear out the stat cache. trackStats(); // If we have mail to send, send it. if (!empty($context['flush_mail'])) { AddMailQueue(true); } $do_header = $header === null ? !$header_done : $header; if ($do_footer === null) { $do_footer = $do_header; } // Has the template/header been done yet? if ($do_header) { // Was the page title set last minute? Also update the HTML safe one. if (!empty($context['page_title']) && empty($context['page_title_html_safe'])) { $context['page_title_html_safe'] = $context['forum_name_html_safe'] . ' - ' . commonAPI::htmlspecialchars(un_htmlspecialchars($context['page_title'])); } // Start up the session URL fixer. ob_start('ob_sessrewrite'); HookAPI::integrateOB(); //if(!empty($modSettings['simplesef_enable'])) // ob_start('SimpleSEF::ob_simplesef'); // Display the screen in the logical order. self::template_header(); $header_done = true; } if ($do_footer) { if (WIRELESS && !isset($context['sub_template'])) { fatal_lang_error('wireless_error_notyet', false); } self::Display(); // Just so we don't get caught in an endless loop of errors from the footer... if (!$footer_done) { $footer_done = true; // (since this is just debugging... it's okay that it's after </html>.) if (!isset($_REQUEST['xml'])) { db_debug_junk(); } } } // Remember this URL in case someone doesn't like sending HTTP_REFERER. if (strpos($_SERVER['REQUEST_URL'], 'action=dlattach') === false && strpos($_SERVER['REQUEST_URL'], 'action=viewsmfile') === false) { $_SESSION['old_url'] = $_SERVER['REQUEST_URL']; } // For session check verfication.... don't switch browsers... $_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; // Hand off the output to the portal, etc. we're integrated with. HookAPI::callHook('integrate_exit', array($do_footer)); if (!empty($modSettings['simplesef_enable'])) { SimpleSEF::fixXMLOutput($do_footer); } // Don't exit if we're coming from index.php; that will pass through normally. if (!$from_index) { exit; } }
function AdminSearch() { global $txt, $context, $sourcedir, $backend_subdir; isAllowedTo('admin_forum'); // What can we search for? $subactions = array('internal' => 'AdminSearchInternal', 'online' => 'AdminSearchOM', 'member' => 'AdminSearchMember'); $context['search_type'] = !isset($_REQUEST['search_type']) || !isset($subactions[$_REQUEST['search_type']]) ? 'internal' : $_REQUEST['search_type']; $context['search_term'] = isset($_REQUEST['search_term']) ? commonAPI::htmlspecialchars($_REQUEST['search_term'], ENT_QUOTES) : ''; $context['sub_template'] = 'admin_search_results'; $context['page_title'] = $txt['admin_search_results']; // Keep track of what the admin wants. if (empty($context['admin_preferences']['sb']) || $context['admin_preferences']['sb'] != $context['search_type']) { $context['admin_preferences']['sb'] = $context['search_type']; // Update the preferences. require_once $sourcedir . '/lib/Subs-Admin.php'; updateAdminPreferences(); } if (trim($context['search_term']) == '') { $context['search_results'] = array(); } else { $subactions[$context['search_type']](); } }
function RegisterCheckUsername() { global $sourcedir, $context, $txt; // This is XML! loadTemplate('Xml'); $context['sub_template'] = 'check_username'; $context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : ''; $context['valid_username'] = true; // Clean it up like mother would. $context['checked_username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : "Â ") . ']+~u', ' ', $context['checked_username']); if (commonAPI::strlen($context['checked_username']) > 25) { $context['checked_username'] = commonAPI::htmltrim(commonAPI::substr($context['checked_username'], 0, 25)); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false) { $context['valid_username'] = false; } if (stristr($context['checked_username'], $txt['guest_title']) !== false) { $context['valid_username'] = false; } if (trim($context['checked_username']) == '') { $context['valid_username'] = false; } else { require_once $sourcedir . '/lib/Subs-Members.php'; $context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1; } }
function ssi_boardNews($board = null, $limit = null, $start = null, $length = null, $output_method = 'echo') { global $scripturl, $db_prefix, $txt, $settings, $modSettings, $context; global $smcFunc; loadLanguage('Stats'); // Must be integers.... if ($limit === null) { $limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 5; } else { $limit = (int) $limit; } if ($start === null) { $start = isset($_GET['start']) ? (int) $_GET['start'] : 0; } else { $start = (int) $start; } if ($board !== null) { $board = (int) $board; } elseif (isset($_GET['board'])) { $board = (int) $_GET['board']; } if ($length === null) { $length = isset($_GET['length']) ? (int) $_GET['length'] : 0; } else { $length = (int) $length; } $limit = max(0, $limit); $start = max(0, $start); // Make sure guests can see this board. $request = $smcFunc['db_query']('', ' SELECT id_board FROM {db_prefix}boards WHERE ' . ($board === null ? '' : 'id_board = {int:current_board} AND ') . 'FIND_IN_SET(-1, member_groups) LIMIT 1', array('current_board' => $board)); if ($smcFunc['db_num_rows']($request) == 0) { if ($output_method == 'echo') { die($txt['ssi_no_guests']); } else { return array(); } } list($board) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // Load the message icons - the usual suspects. $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless'); $icon_sources = array(); foreach ($stable_icons as $icon) { $icon_sources[$icon] = 'images_url'; } // Find the post ids. $request = $smcFunc['db_query']('', ' SELECT id_first_msg FROM {db_prefix}topics WHERE id_board = {int:current_board}' . ($modSettings['postmod_active'] ? ' AND approved = {int:is_approved}' : '') . ' ORDER BY id_first_msg DESC LIMIT ' . $start . ', ' . $limit, array('current_board' => $board, 'is_approved' => 1)); $posts = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $posts[] = $row['id_first_msg']; } $smcFunc['db_free_result']($request); if (empty($posts)) { return array(); } // Find the posts. $request = $smcFunc['db_query']('', ' SELECT m.icon, m.subject, m.body, IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time, t.num_replies, t.id_topic, m.id_member, m.smileys_enabled, m.id_msg, t.locked, t.id_last_msg FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) WHERE t.id_first_msg IN ({array_int:post_list}) ORDER BY t.id_first_msg DESC LIMIT ' . count($posts), array('post_list' => $posts)); $return = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { // If we want to limit the length of the post. if (!empty($length) && commonAPI::strlen($row['body']) > $length) { $row['body'] = commonAPI::substr($row['body'], 0, $length); // The first space or line break. (<br />, etc.) $cutoff = max(strrpos($row['body'], ' '), strrpos($row['body'], '<')); if ($cutoff !== false) { $row['body'] = commonAPI::substr($row['body'], 0, $cutoff); } $row['body'] .= '...'; } $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']); // Check that this message icon is there... if (empty($modSettings['messageIconChecks_disable']) && !isset($icon_sources[$row['icon']])) { $icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.gif') ? 'images_url' : 'default_images_url'; } censorText($row['subject']); censorText($row['body']); $return[] = array('id' => $row['id_topic'], 'message_id' => $row['id_msg'], 'icon' => '<img src="' . $settings[$icon_sources[$row['icon']]] . '/post/' . $row['icon'] . '.gif" alt="' . $row['icon'] . '" />', 'subject' => $row['subject'], 'time' => timeformat($row['poster_time']), 'timestamp' => forum_time(true, $row['poster_time']), 'body' => $row['body'], 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0', 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['num_replies'] . ' ' . ($row['num_replies'] == 1 ? $txt['ssi_comment'] : $txt['ssi_comments']) . '</a>', 'replies' => $row['num_replies'], 'comment_href' => !empty($row['locked']) ? '' : $scripturl . '?action=post;topic=' . $row['id_topic'] . '.' . $row['num_replies'] . ';last_msg=' . $row['id_last_msg'], 'comment_link' => !empty($row['locked']) ? '' : '<a href="' . $scripturl . '?action=post;topic=' . $row['id_topic'] . '.' . $row['num_replies'] . ';last_msg=' . $row['id_last_msg'] . '">' . $txt['ssi_write_comment'] . '</a>', 'new_comment' => !empty($row['locked']) ? '' : '<a href="' . $scripturl . '?action=post;topic=' . $row['id_topic'] . '.' . $row['num_replies'] . '">' . $txt['ssi_write_comment'] . '</a>', 'poster' => array('id' => $row['id_member'], 'name' => $row['poster_name'], 'href' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '', 'link' => !empty($row['id_member']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>' : $row['poster_name']), 'locked' => !empty($row['locked']), 'is_last' => false); } $smcFunc['db_free_result']($request); if (empty($return)) { return $return; } $return[count($return) - 1]['is_last'] = true; if ($output_method != 'echo') { return $return; } foreach ($return as $news) { echo ' <div class="news_item"> <h3 class="news_header"> ', $news['icon'], ' <a href="', $news['href'], '">', $news['subject'], '</a> </h3> <div class="news_timestamp">', $news['time'], ' ', $txt['by'], ' ', $news['poster']['link'], '</div> <div class="news_body" style="padding: 2ex 0;">', $news['body'], '</div> ', $news['link'], $news['locked'] ? '' : ' | ' . $news['comment_link'], ' </div>'; if (!$news['is_last']) { echo ' <hr />'; } } }
function PackageInstall() { global $boarddir, $txt, $context, $boardurl, $scripturl, $sourcedir, $modSettings; global $user_info, $smcFunc; // Make sure we don't install this mod twice. checkSubmitOnce('check'); checkSession(); // If there's no file, what are we installing? if (!isset($_REQUEST['package']) || $_REQUEST['package'] == '') { redirectexit('action=admin;area=packages'); } $context['filename'] = $_REQUEST['package']; // If this is an uninstall, we'll have an id. $context['install_id'] = isset($_REQUEST['pid']) ? (int) $_REQUEST['pid'] : 0; require_once $sourcedir . '/lib/Subs-Package.php'; // !!! TODO: Perhaps do it in steps, if necessary? $context['uninstalling'] = $_REQUEST['sa'] == 'uninstall2'; // Set up the linktree for other. $context['linktree'][count($context['linktree']) - 1] = array('url' => $scripturl . '?action=admin;area=packages;sa=browse', 'name' => $context['uninstalling'] ? $txt['uninstall'] : $txt['extracting']); $context['page_title'] .= ' - ' . ($context['uninstalling'] ? $txt['uninstall'] : $txt['extracting']); $context['sub_template'] = 'extract_package'; if (!file_exists($boarddir . '/Packages/' . $context['filename'])) { fatal_lang_error('package_no_file', false); } // Load up the package FTP information? create_chmod_control(array(), array('destination_url' => $scripturl . '?action=admin;area=packages;sa=' . $_REQUEST['sa'] . ';package=' . $_REQUEST['package'])); // Make sure temp directory exists and is empty! if (file_exists($boarddir . '/Packages/temp')) { deltree($boarddir . '/Packages/temp', false); } else { mktree($boarddir . '/Packages/temp', 0777); } // Let the unpacker do the work. if (is_file($boarddir . '/Packages/' . $context['filename'])) { $context['extracted_files'] = read_tgz_file($boarddir . '/Packages/' . $context['filename'], $boarddir . '/Packages/temp'); if (!file_exists($boarddir . '/Packages/temp/package-info.xml')) { foreach ($context['extracted_files'] as $file) { if (basename($file['filename']) == 'package-info.xml') { $context['base_path'] = dirname($file['filename']) . '/'; break; } } } if (!isset($context['base_path'])) { $context['base_path'] = ''; } } elseif (is_dir($boarddir . '/Packages/' . $context['filename'])) { copytree($boarddir . '/Packages/' . $context['filename'], $boarddir . '/Packages/temp'); $context['extracted_files'] = listtree($boarddir . '/Packages/temp'); $context['base_path'] = ''; } else { fatal_lang_error('no_access', false); } // Are we installing this into any custom themes? $custom_themes = array(1); $known_themes = explode(',', $modSettings['knownThemes']); if (!empty($_POST['custom_theme'])) { foreach ($_POST['custom_theme'] as $tid) { if (in_array($tid, $known_themes)) { $custom_themes[] = (int) $tid; } } } // Now load up the paths of the themes that we need to know about. $request = smf_db_query(' SELECT id_theme, variable, value FROM {db_prefix}themes WHERE id_theme IN ({array_int:custom_themes}) AND variable IN ({string:name}, {string:theme_dir})', array('custom_themes' => $custom_themes, 'name' => 'name', 'theme_dir' => 'theme_dir')); $theme_paths = array(); $themes_installed = array(1); while ($row = mysql_fetch_assoc($request)) { $theme_paths[$row['id_theme']][$row['variable']] = $row['value']; } mysql_free_result($request); // Are there any theme copying that we want to take place? $context['theme_copies'] = array('require-file' => array(), 'require-dir' => array()); if (!empty($_POST['theme_changes'])) { foreach ($_POST['theme_changes'] as $change) { if (empty($change)) { continue; } $theme_data = unserialize(base64_decode($change)); if (empty($theme_data['type'])) { continue; } $themes_installed[] = $theme_data['id']; $context['theme_copies'][$theme_data['type']][$theme_data['orig']][] = $theme_data['future']; } } // Get the package info... $packageInfo = getPackageInfo($context['filename']); if (!is_array($packageInfo)) { fatal_lang_error($packageInfo); } $packageInfo['filename'] = $context['filename']; // Set the type of extraction... $context['extract_type'] = isset($packageInfo['type']) ? $packageInfo['type'] : 'modification'; // Create a backup file to roll back to! (but if they do this more than once, don't run it a zillion times.) if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['filename'] . ($context['uninstalling'] ? '$$' : '$'))) { $_SESSION['last_backup_for'] = $context['filename'] . ($context['uninstalling'] ? '$$' : '$'); // !!! Internationalize this? package_create_backup(($context['uninstalling'] ? 'backup_' : 'before_') . strtok($context['filename'], '.')); } // The mod isn't installed.... unless proven otherwise. $context['is_installed'] = false; // Is it actually installed? $request = smf_db_query(' SELECT version, themes_installed, db_changes FROM {db_prefix}log_packages WHERE package_id = {string:current_package} AND install_state != {int:not_installed} ORDER BY time_installed DESC LIMIT 1', array('not_installed' => 0, 'current_package' => $packageInfo['id'])); while ($row = mysql_fetch_assoc($request)) { $old_themes = explode(',', $row['themes_installed']); $old_version = $row['version']; $db_changes = empty($row['db_changes']) ? array() : unserialize($row['db_changes']); } mysql_free_result($request); // Wait, it's not installed yet! // !!! TODO: Replace with a better error message! if (!isset($old_version) && $context['uninstalling']) { deltree($boarddir . '/Packages/temp'); fatal_error('Hacker?', false); } elseif ($context['uninstalling']) { $install_log = parsePackageInfo($packageInfo['xml'], false, 'uninstall'); // Gadzooks! There's no uninstaller at all!? if (empty($install_log)) { fatal_lang_error('package_uninstall_cannot', false); } // They can only uninstall from what it was originally installed into. foreach ($theme_paths as $id => $data) { if ($id != 1 && !in_array($id, $old_themes)) { unset($theme_paths[$id]); } } } elseif (isset($old_version) && $old_version != $packageInfo['version']) { // Look for an upgrade... $install_log = parsePackageInfo($packageInfo['xml'], false, 'upgrade', $old_version); // There was no upgrade.... if (empty($install_log)) { $context['is_installed'] = true; } else { // Upgrade previous themes only! foreach ($theme_paths as $id => $data) { if ($id != 1 && !in_array($id, $old_themes)) { unset($theme_paths[$id]); } } } } elseif (isset($old_version) && $old_version == $packageInfo['version']) { $context['is_installed'] = true; } if (!isset($old_version) || $context['is_installed']) { $install_log = parsePackageInfo($packageInfo['xml'], false, 'install'); } $context['install_finished'] = false; // !!! TODO: Make a log of any errors that occurred and output them? if (!empty($install_log)) { $failed_steps = array(); $failed_count = 0; foreach ($install_log as $action) { $failed_count++; if ($action['type'] == 'modification' && !empty($action['filename'])) { if ($action['boardmod']) { $mod_actions = parseBoardMod(file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']), false, $action['reverse'], $theme_paths); } else { $mod_actions = parseModification(file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']), false, $action['reverse'], $theme_paths); } // Any errors worth noting? foreach ($mod_actions as $key => $action) { if ($action['type'] == 'failure') { $failed_steps[] = array('file' => $action['filename'], 'large_step' => $failed_count, 'sub_step' => $key, 'theme' => 1); } // Gather the themes we installed into. if (!empty($action['is_custom'])) { $themes_installed[] = $action['is_custom']; } } } elseif ($action['type'] == 'code' && !empty($action['filename'])) { // This is just here as reference for what is available. global $txt, $boarddir, $sourcedir, $modSettings, $context, $settings, $forum_version, $smcFunc; // Now include the file and be done with it ;). require $boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']; } elseif ($action['type'] == 'database' && !empty($action['filename']) && (!$context['uninstalling'] || !empty($_POST['do_db_changes']))) { // These can also be there for database changes. global $txt, $boarddir, $sourcedir, $modSettings, $context, $settings, $forum_version, $smcFunc; global $db_package_log; // We'll likely want the package specific database functionality! db_extend('packages'); // Let the file work its magic ;) require $boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']; } elseif ($action['type'] == 'redirect' && !empty($action['redirect_url'])) { $context['redirect_url'] = $action['redirect_url']; $context['redirect_text'] = !empty($action['filename']) && file_exists($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']) ? file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']) : ($context['uninstalling'] ? $txt['package_uninstall_done'] : $txt['package_installed_done']); $context['redirect_timeout'] = $action['redirect_timeout']; // Parse out a couple of common urls. $urls = array('$boardurl' => $boardurl, '$scripturl' => $scripturl, '$session_var' => $context['session_var'], '$session_id' => $context['session_id']); $context['redirect_url'] = strtr($context['redirect_url'], $urls); } } package_flush_cache(); // First, ensure this change doesn't get removed by putting a stake in the ground (So to speak). package_put_contents($boarddir . '/Packages/installed.list', time()); // See if this is already installed, and change it's state as required. $request = smf_db_query(' SELECT package_id, install_state, db_changes FROM {db_prefix}log_packages WHERE install_state != {int:not_installed} AND package_id = {string:current_package} ' . ($context['install_id'] ? ' AND id_install = {int:install_id} ' : '') . ' ORDER BY time_installed DESC LIMIT 1', array('not_installed' => 0, 'install_id' => $context['install_id'], 'current_package' => $packageInfo['id'])); $is_upgrade = false; while ($row = mysql_fetch_assoc($request)) { // Uninstalling? if ($context['uninstalling']) { smf_db_query(' UPDATE {db_prefix}log_packages SET install_state = {int:not_installed}, member_removed = {string:member_name}, id_member_removed = {int:current_member}, time_removed = {int:current_time} WHERE package_id = {string:package_id}', array('current_member' => $user_info['id'], 'not_installed' => 0, 'current_time' => time(), 'package_id' => $row['package_id'], 'member_name' => $user_info['name'])); } else { $is_upgrade = true; $old_db_changes = empty($row['db_changes']) ? array() : unserialize($row['db_changes']); } } // Assuming we're not uninstalling, add the entry. if (!$context['uninstalling']) { // Any db changes from older version? if (!empty($old_db_changes)) { $db_package_log = empty($db_package_log) ? $old_db_changes : array_merge($old_db_changes, $db_package_log); } // If there are some database changes we might want to remove then filter them out. if (!empty($db_package_log)) { // We're really just checking for entries which are create table AND add columns (etc). $tables = array(); function sort_table_first($a, $b) { if ($a[0] == $b[0]) { return 0; } return $a[0] == 'remove_table' ? -1 : 1; } usort($db_package_log, 'sort_table_first'); foreach ($db_package_log as $k => $log) { if ($log[0] == 'remove_table') { $tables[] = $log[1]; } elseif (in_array($log[1], $tables)) { unset($db_package_log[$k]); } } $db_changes = serialize($db_package_log); } else { $db_changes = ''; } // What themes did we actually install? $themes_installed = array_unique($themes_installed); $themes_installed = implode(',', $themes_installed); // What failed steps? $failed_step_insert = serialize($failed_steps); smf_db_insert('', '{db_prefix}log_packages', array('filename' => 'string', 'name' => 'string', 'package_id' => 'string', 'version' => 'string', 'id_member_installed' => 'int', 'member_installed' => 'string', 'time_installed' => 'int', 'install_state' => 'int', 'failed_steps' => 'string', 'themes_installed' => 'string', 'member_removed' => 'int', 'db_changes' => 'string'), array($packageInfo['filename'], $packageInfo['name'], $packageInfo['id'], $packageInfo['version'], $user_info['id'], $user_info['name'], time(), $is_upgrade ? 2 : 1, $failed_step_insert, $themes_installed, 0, $db_changes), array('id_install')); } mysql_free_result($request); $context['install_finished'] = true; } // If there's database changes - and they want them removed - let's do it last! if (!empty($db_changes) && !empty($_POST['do_db_changes'])) { // We're gonna be needing the package db functions! db_extend('packages'); foreach ($db_changes as $change) { if ($change[0] == 'remove_table' && isset($change[1])) { smf_db_drop_table($change[1]); } elseif ($change[0] == 'remove_column' && isset($change[2])) { smf_db_remove_column($change[1], $change[2]); } elseif ($change[0] == 'remove_index' && isset($change[2])) { smf_db_remove_index($change[1], $change[2]); } } } // Clean house... get rid of the evidence ;). if (file_exists($boarddir . '/Packages/temp')) { deltree($boarddir . '/Packages/temp'); } // Log what we just did. logAction($context['uninstalling'] ? 'uninstall_package' : (!empty($is_upgrade) ? 'upgrade_package' : 'install_package'), array('package' => commonAPI::htmlspecialchars($packageInfo['name']), 'version' => commonAPI::htmlspecialchars($packageInfo['version'])), 'admin'); // Just in case, let's clear the whole cache to avoid anything going up the swanny. clean_cache(); // Restore file permissions? create_chmod_control(array(), array(), true); }
function JavaScriptModify() { global $sourcedir, $modSettings, $board, $topic, $txt; global $user_info, $context, $language; // We have to have a topic! if (empty($topic)) { obExit(false); } checkSession('get'); require_once $sourcedir . '/lib/Subs-Post.php'; // Assume the first message if no message ID was given. $request = smf_db_query(' SELECT t.locked, t.num_replies, t.id_member_started, t.id_first_msg, m.id_msg, m.id_member, m.poster_time, m.subject, m.smileys_enabled, m.body, m.icon, m.modified_time, m.modified_name, m.approved, ba.id_topic AS banned_from_topic FROM {db_prefix}messages AS m INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic}) LEFT JOIN {db_prefix}topicbans AS ba ON (ba.id_topic = {int:current_topic} AND ba.id_member = {int:current_member}) WHERE m.id_msg = {raw:id_msg} AND m.id_topic = {int:current_topic}' . (allowedTo('approve_posts') ? '' : (!$modSettings['postmod_active'] ? ' AND (m.id_member != {int:guest_id} AND m.id_member = {int:current_member})' : ' AND (m.approved = {int:is_approved} OR (m.id_member != {int:guest_id} AND m.id_member = {int:current_member}))')), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'id_msg' => empty($_REQUEST['msg']) ? 't.id_first_msg' : (int) $_REQUEST['msg'], 'is_approved' => 1, 'guest_id' => 0)); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board', false); } $row = mysql_fetch_assoc($request); mysql_free_result($request); // Change either body or subject requires permissions to modify messages. if (isset($_POST['message']) || isset($_POST['subject']) || isset($_REQUEST['icon'])) { if (!empty($row['locked'])) { isAllowedTo('moderate_board'); } if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any')) { if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) { fatal_lang_error('modify_post_time_passed', false); } elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_any'); } // check topic bans if ($row['banned_from_topic'] != 0 && !$user_info['is_admin'] && !allowedTo('moderate_board') && !allowedTo('moderate_forum')) { fatal_lang_error('banned_from_topic'); } // Only log this action if it wasn't your message. $moderationAction = $row['id_member'] != $user_info['id']; } $post_errors = array(); if (isset($_POST['subject']) && commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['subject'])) !== '') { $_POST['subject'] = strtr(commonAPI::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); // Maximum number of characters. if (commonAPI::strlen($_POST['subject']) > 100) { $_POST['subject'] = commonAPI::substr($_POST['subject'], 0, 100); } } elseif (isset($_POST['subject'])) { $post_errors[] = 'no_subject'; unset($_POST['subject']); } if (isset($_POST['message'])) { if (commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message'])) === '') { $post_errors[] = 'no_message'; unset($_POST['message']); } elseif (!empty($modSettings['max_messageLength']) && commonAPI::strlen($_POST['message']) > $modSettings['max_messageLength']) { $post_errors[] = 'long_message'; unset($_POST['message']); } else { $_POST['message'] = commonAPI::htmlspecialchars($_POST['message'], ENT_QUOTES); preparsecode($_POST['message']); if (commonAPI::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '') { $post_errors[] = 'no_message'; unset($_POST['message']); } } } if (isset($_POST['lock'])) { if (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $row['id_member']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { if ($row['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } elseif (!empty($row['locked']) && !empty($_POST['lock']) || $_POST['lock'] == $row['locked']) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } if (isset($_POST['sticky']) && !allowedTo('make_sticky')) { unset($_POST['sticky']); } if (empty($post_errors)) { $msgOptions = array('id' => $row['id_msg'], 'subject' => isset($_POST['subject']) ? $_POST['subject'] : null, 'body' => isset($_POST['message']) ? $_POST['message'] : null, 'icon' => isset($_REQUEST['icon']) ? preg_replace('~[\\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : null, 'id_owner' => $row['id_member']); $topicOptions = array('id' => $topic, 'board' => $board, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true); $posterOptions = array(); // Only consider marking as editing if they have edited the subject, message or icon. if (isset($_POST['subject']) && $_POST['subject'] != $row['subject'] || isset($_POST['message']) && $_POST['message'] != $row['body'] || isset($_REQUEST['icon']) && $_REQUEST['icon'] != $row['icon']) { // And even then only if the time has passed... if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member']) { $msgOptions['modify_time'] = time(); $msgOptions['modify_name'] = $user_info['name']; } } else { $moderationAction = false; } modifyPost($msgOptions, $topicOptions, $posterOptions); // If we didn't change anything this time but had before put back the old info. if (!isset($msgOptions['modify_time']) && !empty($row['modified_time'])) { $msgOptions['modify_time'] = $row['modified_time']; $msgOptions['modify_name'] = $row['modified_name']; } // Changing the first subject updates other subjects to 'Re: new_subject'. if (isset($_POST['subject']) && isset($_REQUEST['change_all_subjects']) && $row['id_first_msg'] == $row['id_msg'] && !empty($row['num_replies']) && (allowedTo('modify_any') || $row['id_member_started'] == $user_info['id'] && allowedTo('modify_replies'))) { // Get the proper (default language) response prefix first. if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } CacheAPI::putCache('response_prefix', $context['response_prefix'], 600); } smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:subject} WHERE id_topic = {int:current_topic} AND id_msg != {int:id_first_msg}', array('current_topic' => $topic, 'id_first_msg' => $row['id_first_msg'], 'subject' => $context['response_prefix'] . $_POST['subject'])); } if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => $row['id_msg'], 'member' => $row['id_member'], 'board' => $board)); } } if (isset($_REQUEST['xml'])) { $context['sub_template'] = 'modifydone'; if (empty($post_errors) && isset($msgOptions['subject']) && isset($msgOptions['body'])) { $context['message'] = array('id' => $row['id_msg'], 'modified' => array('time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => $msgOptions['subject'], 'first_in_topic' => $row['id_msg'] == $row['id_first_msg'], 'body' => strtr($msgOptions['body'], array(']]>' => ']]]]><![CDATA[>'))); censorText($context['message']['subject']); censorText($context['message']['body']); $cache_key = isset($msgOptions['modify_time']) ? $row['id_msg'] . '|' . $msgOptions['modify_time'] : $row['id_msg']; $context['message']['body'] = parse_bbc($context['message']['body'], $row['smileys_enabled'], $cache_key); parse_bbc_stage2($context['message']['body']); } elseif (empty($post_errors)) { $context['sub_template'] = 'modifytopicdone'; $context['message'] = array('id' => $row['id_msg'], 'icon' => isset($_REQUEST['icon']) ? $_REQUEST['icon'] : '', 'modified' => array('time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => isset($msgOptions['subject']) ? $msgOptions['subject'] : ''); censorText($context['message']['subject']); } else { $context['message'] = array('id' => $row['id_msg'], 'errors' => array(), 'error_in_subject' => in_array('no_subject', $post_errors), 'error_in_body' => in_array('no_message', $post_errors) || in_array('long_message', $post_errors)); loadLanguage('Errors'); foreach ($post_errors as $post_error) { if ($post_error == 'long_message') { $context['message']['errors'][] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']); } else { $context['message']['errors'][] = $txt['error_' . $post_error]; } } } } else { obExit(false); } }
function generateSubscriptionError($text) { global $modSettings, $notify_users, $smcFunc; // Send an email? if (!empty($modSettings['paid_email'])) { $replacements = array('ERROR' => $text); emailAdmins('paid_subscription_error', $replacements, $notify_users); } // Maybe we can try to give them the post data? if (!empty($_POST)) { foreach ($_POST as $key => $val) { $text .= '<br />' . commonAPI::htmlspecialchars($key) . ': ' . commonAPI::htmlspecialchars($val); } } // Then just log and die. log_error($text); exit; }
function issueWarning($memID) { global $txt, $scripturl, $modSettings, $user_info, $mbname; global $context, $cur_profile, $memberContext, $smcFunc, $sourcedir; if (!isset($context['profile_template_support_context'])) { $context['profile_template_support_context'] = new ProfileContext(); } // Get all the actual settings. list($modSettings['warning_enable'], $modSettings['user_limit']) = explode(',', $modSettings['warning_settings']); EoS_Smarty::loadTemplate('profile/profile_base'); EoS_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'profile/issuewarning'); // This stores any legitimate errors. $issueErrors = array(); $context['replace_helper_array'] = array('"' => "'", "\n" => '\\n', "\r" => ''); // Doesn't hurt to be overly cautious. if (empty($modSettings['warning_enable']) || $context['user']['is_owner'] && !$cur_profile['warning'] || !allowedTo('issue_warning')) { fatal_lang_error('no_access', false); } // Make sure things which are disabled stay disabled. $modSettings['warning_watch'] = !empty($modSettings['warning_watch']) ? $modSettings['warning_watch'] : 110; $modSettings['warning_moderate'] = !empty($modSettings['warning_moderate']) && !empty($modSettings['postmod_active']) ? $modSettings['warning_moderate'] : 110; $modSettings['warning_mute'] = !empty($modSettings['warning_mute']) ? $modSettings['warning_mute'] : 110; $context['warning_limit'] = allowedTo('admin_forum') ? 0 : $modSettings['user_limit']; $context['member']['warning'] = $cur_profile['warning']; $context['member']['name'] = $cur_profile['real_name']; // What are the limits we can apply? $context['min_allowed'] = 0; $context['max_allowed'] = 100; if ($context['warning_limit'] > 0) { // Make sure we cannot go outside of our limit for the day. $request = smf_db_query(' SELECT SUM(counter) FROM {db_prefix}log_comments WHERE id_recipient = {int:selected_member} AND id_member = {int:current_member} AND comment_type = {string:warning} AND log_time > {int:day_time_period}', array('current_member' => $user_info['id'], 'selected_member' => $memID, 'day_time_period' => time() - 86400, 'warning' => 'warning')); list($current_applied) = mysql_fetch_row($request); mysql_free_result($request); $context['min_allowed'] = max(0, $cur_profile['warning'] - $current_applied - $context['warning_limit']); $context['max_allowed'] = min(100, $cur_profile['warning'] - $current_applied + $context['warning_limit']); } // Defaults. $context['warning_data'] = array('reason' => '', 'notify' => '', 'notify_subject' => '', 'notify_body' => '', 'topicban' => '', 'topicban_expire' => 0, 'topicban_id_topic' => 0); // Are we saving? if (isset($_POST['save'])) { // Security is good here. checkSession('post'); // This cannot be empty! $_POST['warn_reason'] = isset($_POST['warn_reason']) ? trim($_POST['warn_reason']) : ''; if ($_POST['warn_reason'] == '' && !$context['user']['is_owner']) { $issueErrors[] = 'warning_no_reason'; } $_POST['warn_reason'] = commonAPI::htmlspecialchars($_POST['warn_reason']); // If the value hasn't changed it's either no JS or a real no change (Which this will pass) if ($_POST['warning_level'] == 'SAME') { $_POST['warning_level'] = $_POST['warning_level_nojs']; } $_POST['warning_level'] = (int) $_POST['warning_level']; $_POST['warning_level'] = max(0, min(100, $_POST['warning_level'])); if ($_POST['warning_level'] < $context['min_allowed']) { $_POST['warning_level'] = $context['min_allowed']; } elseif ($_POST['warning_level'] > $context['max_allowed']) { $_POST['warning_level'] = $context['max_allowed']; } // Do we actually have to issue them with a PM? $id_notice = 0; if (!empty($_POST['warn_notify']) && empty($issueErrors)) { $_POST['warn_sub'] = trim($_POST['warn_sub']); $_POST['warn_body'] = trim($_POST['warn_body']); if (empty($_POST['warn_sub']) || empty($_POST['warn_body'])) { $issueErrors[] = 'warning_notify_blank'; } else { require_once $sourcedir . '/lib/Subs-Post.php'; $from = array('id' => 0, 'name' => $context['forum_name'], 'username' => $context['forum_name']); sendpm(array('to' => array($memID), 'bcc' => array()), $_POST['warn_sub'], $_POST['warn_body'], false, $from); // Log the notice! smf_db_insert('', '{db_prefix}log_member_notices', array('subject' => 'string-255', 'body' => 'string-65534'), array(commonAPI::htmlspecialchars($_POST['warn_sub']), commonAPI::htmlspecialchars($_POST['warn_body'])), array('id_notice')); $id_notice = smf_db_insert_id('{db_prefix}log_member_notices', 'id_notice'); } } // Just in case - make sure notice is valid! $id_notice = (int) $id_notice; // What have we changed? $level_change = $_POST['warning_level'] - $cur_profile['warning']; // No errors? Proceed! Only log if you're not the owner. if (empty($issueErrors)) { // Log what we've done! if (!$context['user']['is_owner']) { smf_db_insert('', '{db_prefix}log_comments', array('id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'id_recipient' => 'int', 'recipient_name' => 'string-255', 'log_time' => 'int', 'id_notice' => 'int', 'counter' => 'int', 'body' => 'string-65534'), array($user_info['id'], $user_info['name'], 'warning', $memID, $cur_profile['real_name'], time(), $id_notice, $level_change, $_POST['warn_reason']), array('id_comment')); } // Make the change. updateMemberData($memID, array('warning' => $_POST['warning_level'])); // Leave a lovely message. $context['profile_updated'] = $context['user']['is_owner'] ? $txt['profile_updated_own'] : $txt['profile_warning_success']; // if we want to issue a topicban, do it now if (isset($_POST['warn_topicban']) && !empty($_POST['warn_topicban']) && isset($_POST['warn_topicban_id_topic']) && !empty($_POST['warn_topicban_id_topic'])) { $ban_reason = (isset($_REQUEST['warn_msg']) ? (int) $_REQUEST['warn_msg'] : 0) . '|' . $_POST['warn_reason']; $ban_expires = isset($_POST['warn_topicban_expire']) && !empty($_POST['warn_topicban_expire']) ? $context['time_now'] + 86400 * (int) $_POST['warn_topicban_expire'] : 0; smf_db_insert('', '{db_prefix}topicbans', array('id_topic' => 'int', 'id_member' => 'int', 'updated' => 'int', 'expires' => 'int', 'reason' => 'string'), array($_POST['warn_topicban_id_topic'], $memID, $context['time_now'], $ban_expires, $ban_reason), array('id')); } } else { // Get the base stuff done. loadLanguage('Errors'); $context['custom_error_title'] = $txt['profile_warning_errors_occured']; // Fill in the suite of errors. $context['post_errors'] = array(); foreach ($issueErrors as $error) { $context['post_errors'][] = $txt[$error]; } // Try to remember some bits. $context['warning_data'] = array('reason' => $_POST['warn_reason'], 'notify' => !empty($_POST['warn_notify']), 'notify_subject' => isset($_POST['warn_sub']) ? $_POST['warn_sub'] : '', 'notify_body' => isset($_POST['warn_body']) ? $_POST['warn_body'] : '', 'topicban' => isset($_POST['warn_topicban']) && !empty($_POST['warn_topicban']) ? 1 : 0, 'topicban_expire' => isset($_POST['warn_topicban_expire']) && !empty($_POST['warn_topicban_expire']) ? (int) $_POST['warn_topicban_expire'] : 0, 'topicban_id_topic' => isset($_POST['warn_topicban_id_topic']) ? (int) $_POST['warn_topicban_id_topic'] : 0, 'msg' => isset($_POST['warn_msg']) && !empty($_POST['warn_msg']) ? (int) $_POST['warn_msg'] : 0); } // Show the new improved warning level. $context['member']['warning'] = $_POST['warning_level']; } $context['page_title'] = $txt['profile_issue_warning']; // Work our the various levels. $context['level_effects'] = array(0 => $txt['profile_warning_effect_none'], $modSettings['warning_watch'] => $txt['profile_warning_effect_watch'], $modSettings['warning_moderate'] => $txt['profile_warning_effect_moderation'], $modSettings['warning_mute'] => $txt['profile_warning_effect_mute']); $context['current_level'] = 0; foreach ($context['level_effects'] as $limit => $dummy) { if ($context['member']['warning'] >= $limit) { $context['current_level'] = $limit; } } // Load up all the old warnings - count first! $context['total_warnings'] = list_getUserWarningCount($memID); // Make the page index. $context['start'] = (int) $_REQUEST['start']; $perPage = (int) $modSettings['defaultMaxMessages']; $context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';area=issuewarning', $context['start'], $context['total_warnings'], $perPage); // Now do the data itself. $context['previous_warnings'] = list_getUserWarnings($context['start'], $perPage, 'log_time DESC', $memID); // Are they warning because of a message? $context['warned_message_subject'] = ''; if (isset($_REQUEST['msg']) && 0 < (int) $_REQUEST['msg']) { $request = smf_db_query(' SELECT subject, id_topic FROM {db_prefix}messages AS m INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) WHERE id_msg = {int:message} AND {query_see_board} LIMIT 1', array('message' => (int) $_REQUEST['msg'])); if (mysql_num_rows($request) != 0) { $context['warning_for_message'] = (int) $_REQUEST['msg']; $context['warning_data']['msg'] = $context['warning_for_message']; list($context['warned_message_subject'], $context['warning_for_topic']) = mysql_fetch_row($request); } mysql_free_result($request); } if (isset($_POST['warn_topicban_id_topic'])) { $context['warning_for_message'] = (int) $_POST['warn_topicban_id_topic']; } // Didn't find the message? if (empty($context['warning_for_message'])) { $context['warning_for_message'] = $context['warning_for_topic'] = 0; $context['warned_message_subject'] = ''; } // we can issue a topic ban, now check if the member doesn't have one already if (isset($context['warning_for_topic'])) { $context['can_issue_topicban'] = $context['warning_for_topic']; $request = smf_db_query('SELECT id_member FROM {db_prefix}topicbans WHERE id_topic = {int:topic} AND id_member = {int:member}', array('topic' => $context['warning_for_topic'], 'member' => $memID)); if (mysql_num_rows($request) > 0) { $context['warning_for_topic'] = $context['can_issue_topicban'] = 0; $context['member_is_topic_banned'] = true; } else { $context['warning_data']['topicban_id_topic'] = $context['warning_for_topic']; } mysql_free_result($request); } else { $context['can_issue_topicban'] = 0; } // Any custom templates? $context['notification_templates'] = array(); $request = smf_db_query(' SELECT recipient_name AS template_title, body FROM {db_prefix}log_comments WHERE comment_type = {string:warntpl} AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})', array('warntpl' => 'warntpl', 'generic' => 0, 'current_member' => $user_info['id'])); while ($row = mysql_fetch_assoc($request)) { // If we're not warning for a message skip any that are. if (!$context['warning_for_message'] && strpos($row['body'], '{MESSAGE}') !== false) { continue; } $context['notification_templates'][] = array('title' => $row['template_title'], 'body' => $row['body']); } mysql_free_result($request); // Setup the "default" templates. foreach (array('spamming', 'offence', 'insulting') as $type) { $context['notification_templates'][] = array('title' => $txt['profile_warning_notify_title_' . $type], 'body' => sprintf($txt['profile_warning_notify_template_outline' . (!empty($context['warning_for_message']) ? '_post' : '')], $txt['profile_warning_notify_for_' . $type])); } // Replace all the common variables in the templates. foreach ($context['notification_templates'] as $k => $name) { $context['notification_templates'][$k]['body'] = strtr($name['body'], array('{MEMBER}' => un_htmlspecialchars($context['member']['name']), '{MESSAGE}' => '[url=' . $scripturl . '?msg=' . $context['warning_for_message'] . ']' . un_htmlspecialchars($context['warned_message_subject']) . '[/url]', '{SCRIPTURL}' => $scripturl, '{FORUMNAME}' => $mbname, '{REGARDS}' => $txt['regards_team'])); } }
/** * @param $memID int member id * * show activities, notifications and settings on the profile page. The latter two * are only handled when viewing your own profile. * * This is here because Profile-View.php is already big enough :) */ function showActivitiesProfile($memID) { global $context, $user_info, $sourcedir, $user_profile, $txt, $modSettings, $options; $context['user']['is_owner'] = $memID == $user_info['id']; require_once $sourcedir . '/lib/Subs-Activities.php'; Eos_Smarty::loadTemplate('profile/profile_base'); loadLanguage('Activities'); $sa = isset($_GET['sa']) ? $_GET['sa'] : 'activities'; $start = isset($_GET['start']) ? (int) $_GET['start'] : 0; if ($sa == 'settings') { return showActivitiesProfileSettings($memID); } Eos_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'profile/activities_display'); $context['page_title'] = $txt['showActivities'] . ' - ' . $user_profile[$memID]['real_name']; $context['pageindex_multiplier'] = commonAPI::getMessagesPerPage(); $context['act_results'] = 0; $context['rich_output'] = true; $context[$context['profile_menu_name']]['tab_data'] = array('title' => $txt['showActivities'], 'description' => $txt['showActivitiesMenu'], 'tabs' => array()); // these areas cannot be visited if it's not our own profile unless you are the mighty one if (($sa == 'notifications' || $sa == 'settings') && !$context['user']['is_owner'] && !$user_info['is_admin']) { fatal_lang_error('no_access'); } $result = smf_db_query(' SELECT a.*, t.*, b.name AS board_name FROM {db_prefix}log_activities AS a LEFT JOIN {db_prefix}activity_types AS t ON (t.id_type = a.id_type) LEFT JOIN {db_prefix}boards AS b ON(b.id_board = a.id_board) WHERE ({query_see_board} OR a.id_board = 0) AND (a.id_member = {int:id_user} OR a.id_owner = {int:id_user}) ORDER BY a.id_act DESC LIMIT {int:start}, 20', array('start' => $start, 'id_user' => $memID)); $context['act_global'] = true; aStreamOutput($result); $context['titletext'] = $context['page_title']; }
function ReportToModerator2() { global $txt, $scripturl, $topic, $board, $user_info, $modSettings, $sourcedir, $language, $context, $smcFunc; // You must have the proper permissions! isAllowedTo('report_any'); // Make sure they aren't spamming. spamProtection('reporttm'); require_once $sourcedir . '/lib/Subs-Post.php'; // No errors, yet. $post_errors = array(); // Check their session. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } // Make sure we have a comment and it's clean. if (!isset($_POST['comment']) || commonAPI::htmltrim($_POST['comment']) === '') { $post_errors[] = 'no_comment'; } $poster_comment = strtr(commonAPI::htmlspecialchars($_POST['comment']), array("\r" => '', "\n" => '', "\t" => '')); // Guests need to provide their address! if ($user_info['is_guest']) { $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']); if ($_POST['email'] === '') { $post_errors[] = 'no_email'; } elseif (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) { $post_errors[] = 'bad_email'; } isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); $user_info['email'] = htmlspecialchars($_POST['email']); } // Could they get the right verification code? if ($user_info['is_guest'] && !empty($modSettings['guests_report_require_captcha'])) { require_once $sourcedir . '/lib/Subs-Editor.php'; $verificationOptions = array('id' => 'report'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { $post_errors = array_merge($post_errors, $context['require_verification']); } } // Any errors? if (!empty($post_errors)) { loadLanguage('Errors'); $context['post_errors'] = array(); foreach ($post_errors as $post_error) { $context['post_errors'][] = $txt['error_' . $post_error]; } return ReportToModerator(); } // Get the basic topic information, and make sure they can see it. $_POST['msg'] = (int) $_POST['msg']; $request = smf_db_query(' SELECT m.id_topic, m.id_board, m.subject, m.body, m.id_member AS id_poster, m.poster_name, mem.real_name FROM {db_prefix}messages AS m LEFT JOIN {db_prefix}members AS mem ON (m.id_member = mem.id_member) WHERE m.id_msg = {int:id_msg} AND m.id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic, 'id_msg' => $_POST['msg'])); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board', false); } $message = mysql_fetch_assoc($request); mysql_free_result($request); $poster_name = un_htmlspecialchars($message['real_name']) . ($message['real_name'] != $message['poster_name'] ? ' (' . $message['poster_name'] . ')' : ''); $reporterName = un_htmlspecialchars($user_info['name']) . ($user_info['name'] != $user_info['username'] && $user_info['username'] != '' ? ' (' . $user_info['username'] . ')' : ''); $subject = un_htmlspecialchars($message['subject']); // Get a list of members with the moderate_board permission. require_once $sourcedir . '/lib/Subs-Members.php'; $moderators = membersAllowedTo('moderate_board', $board); $request = smf_db_query(' SELECT id_member, email_address, lngfile, mod_prefs FROM {db_prefix}members WHERE id_member IN ({array_int:moderator_list}) AND notify_types != {int:notify_types} ORDER BY lngfile', array('moderator_list' => $moderators, 'notify_types' => 4)); // Check that moderators do exist! if (mysql_num_rows($request) == 0) { fatal_lang_error('no_mods', false); } // If we get here, I believe we should make a record of this, for historical significance, yabber. if (empty($modSettings['disable_log_report'])) { $request2 = smf_db_query(' SELECT id_report, ignore_all FROM {db_prefix}log_reported WHERE id_msg = {int:id_msg} AND (closed = {int:not_closed} OR ignore_all = {int:ignored}) ORDER BY ignore_all DESC', array('id_msg' => $_POST['msg'], 'not_closed' => 0, 'ignored' => 1)); if (mysql_num_rows($request2) != 0) { list($id_report, $ignore) = mysql_fetch_row($request2); } mysql_free_result($request2); // If we're just going to ignore these, then who gives a monkeys... if (!empty($ignore)) { redirectexit('topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); } // Already reported? My god, we could be dealing with a real rogue here... if (!empty($id_report)) { smf_db_query(' UPDATE {db_prefix}log_reported SET num_reports = num_reports + 1, time_updated = {int:current_time} WHERE id_report = {int:id_report}', array('current_time' => time(), 'id_report' => $id_report)); } else { if (empty($message['real_name'])) { $message['real_name'] = $message['poster_name']; } smf_db_insert('', '{db_prefix}log_reported', array('id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string', 'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int', 'num_reports' => 'int', 'closed' => 'int'), array($_POST['msg'], $message['id_topic'], $message['id_board'], $message['id_poster'], $message['real_name'], $message['subject'], $message['body'], time(), time(), 1, 0), array('id_report')); $id_report = smf_db_insert_id('{db_prefix}log_reported', 'id_report'); } // Now just add our report... if ($id_report) { smf_db_insert('', '{db_prefix}log_reported_comments', array('id_report' => 'int', 'id_member' => 'int', 'membername' => 'string', 'email_address' => 'string', 'member_ip' => 'string', 'comment' => 'string', 'time_sent' => 'int'), array($id_report, $user_info['id'], $user_info['name'], $user_info['email'], $user_info['ip'], $poster_comment, time()), array('id_comment')); } } // Find out who the real moderators are - for mod preferences. $request2 = smf_db_query(' SELECT id_member FROM {db_prefix}moderators WHERE id_board = {int:current_board}', array('current_board' => $board)); $real_mods = array(); while ($row = mysql_fetch_assoc($request2)) { $real_mods[] = $row['id_member']; } mysql_free_result($request2); // Send every moderator an email. while ($row = mysql_fetch_assoc($request)) { // Maybe they don't want to know?! if (!empty($row['mod_prefs'])) { list(, , $pref_binary) = explode('|', $row['mod_prefs']); if (!($pref_binary & 1) && (!($pref_binary & 2) || !in_array($row['id_member'], $real_mods))) { continue; } } $replacements = array('TOPICSUBJECT' => $subject, 'POSTERNAME' => $poster_name, 'REPORTERNAME' => $reporterName, 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg'], 'REPORTLINK' => !empty($id_report) ? $scripturl . '?action=moderate;area=reports;report=' . $id_report : '', 'COMMENT' => $_POST['comment']); $emaildata = loadEmailTemplate('report_to_moderator', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // Send it to the moderator. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], $user_info['email'], null, false, 2); } mysql_free_result($request); // Keep track of when the mod reports get updated, that way we know when we need to look again. updateSettings(array('last_mod_report_action' => time())); // Back to the post we reported! redirectexit('reportsent;topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); }
function EditPoll2() { global $txt, $topic, $board, $context; global $modSettings, $user_info, $smcFunc, $sourcedir; // Sneaking off, are we? if (empty($_POST)) { redirectexit('action=editpoll;topic=' . $topic . '.0'); } if (checkSession('post', '', false) != '') { $poll_errors[] = 'session_timeout'; } if (isset($_POST['preview'])) { return EditPoll(); } // HACKERS (!!) can't edit :P. if (empty($topic)) { fatal_lang_error('no_access', false); } // Is this a new poll, or editing an existing? $isEdit = isset($_REQUEST['add']) ? 0 : 1; // Get the starter and the poll's ID - if it's an edit. $request = smf_db_query(' SELECT t.id_member_started, t.id_poll, p.id_member AS poll_starter, p.expire_time FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = t.id_poll) WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic)); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board'); } $bcinfo = mysql_fetch_assoc($request); mysql_free_result($request); // Check their adding/editing is valid. if (!$isEdit && !empty($bcinfo['id_poll'])) { fatal_lang_error('poll_already_exists'); } elseif ($isEdit && empty($bcinfo['id_poll'])) { fatal_lang_error('poll_not_found'); } // Check if they have the power to add or edit the poll. if ($isEdit && !allowedTo('poll_edit_any')) { isAllowedTo('poll_edit_' . ($user_info['id'] == $bcinfo['id_member_started'] || $bcinfo['poll_starter'] != 0 && $user_info['id'] == $bcinfo['poll_starter'] ? 'own' : 'any')); } elseif (!$isEdit && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_' . ($user_info['id'] == $bcinfo['id_member_started'] ? 'own' : 'any')); } $optionCount = 0; // Ensure the user is leaving a valid amount of options - there must be at least two. foreach ($_POST['options'] as $k => $option) { if (trim($option) != '') { $optionCount++; } } if ($optionCount < 2) { $poll_errors[] = 'poll_few'; } // Also - ensure they are not removing the question. if (trim($_POST['question']) == '') { $poll_errors[] = 'no_question'; } // Got any errors to report? if (!empty($poll_errors)) { loadLanguage('Errors'); // Previewing. $_POST['preview'] = true; $context['poll_error'] = array('messages' => array()); foreach ($poll_errors as $poll_error) { $context['poll_error'][$poll_error] = true; $context['poll_error']['messages'][] = $txt['error_' . $poll_error]; } return EditPoll(); } // Prevent double submission of this form. checkSubmitOnce('check'); // Now we've done all our error checking, let's get the core poll information cleaned... question first. $_POST['question'] = commonAPI::htmlspecialchars($_POST['question']); $_POST['question'] = commonAPI::truncate($_POST['question'], 255); $_POST['poll_hide'] = (int) $_POST['poll_hide']; $_POST['poll_expire'] = isset($_POST['poll_expire']) ? (int) $_POST['poll_expire'] : 0; $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0; $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0; // Make sure guests are actually allowed to vote generally. if ($_POST['poll_guest_vote']) { require_once $sourcedir . '/lib/Subs-Members.php'; $allowedGroups = groupsAllowedTo('poll_vote', $board); if (!in_array(-1, $allowedGroups['allowed'])) { $_POST['poll_guest_vote'] = 0; } } // Ensure that the number options allowed makes sense, and the expiration date is valid. if (!$isEdit || allowedTo('moderate_board')) { $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']); if (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } elseif (!$isEdit || $_POST['poll_expire'] != ceil($bcinfo['expire_time'] <= time() ? -1 : ($bcinfo['expire_time'] - time()) / (3600 * 24))) { $_POST['poll_expire'] = empty($_POST['poll_expire']) ? '0' : time() + $_POST['poll_expire'] * 3600 * 24; } else { $_POST['poll_expire'] = $bcinfo['expire_time']; } if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } } // If we're editing, let's commit the changes. if ($isEdit) { smf_db_query(' UPDATE {db_prefix}polls SET question = {string:question}, change_vote = {int:change_vote},' . (allowedTo('moderate_board') ? ' hide_results = {int:hide_results}, expire_time = {int:expire_time}, max_votes = {int:max_votes}, guest_vote = {int:guest_vote}' : ' hide_results = CASE WHEN expire_time = {int:expire_time_zero} AND {int:hide_results} = 2 THEN 1 ELSE {int:hide_results} END') . ' WHERE id_poll = {int:id_poll}', array('change_vote' => $_POST['poll_change_vote'], 'hide_results' => $_POST['poll_hide'], 'expire_time' => !empty($_POST['poll_expire']) ? $_POST['poll_expire'] : 0, 'max_votes' => !empty($_POST['poll_max_votes']) ? $_POST['poll_max_votes'] : 0, 'guest_vote' => $_POST['poll_guest_vote'], 'expire_time_zero' => 0, 'id_poll' => $bcinfo['id_poll'], 'question' => $_POST['question'])); } else { // Create the poll. smf_db_insert('', '{db_prefix}polls', array('question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int', 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'), array($_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], $_POST['poll_expire'], $user_info['id'], $user_info['username'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']), array('id_poll')); // Set the poll ID. $bcinfo['id_poll'] = smf_db_insert_id('{db_prefix}polls', 'id_poll'); // Link the poll to the topic smf_db_query(' UPDATE {db_prefix}topics SET id_poll = {int:id_poll} WHERE id_topic = {int:current_topic}', array('current_topic' => $topic, 'id_poll' => $bcinfo['id_poll'])); } // Get all the choices. (no better way to remove all emptied and add previously non-existent ones.) $request = smf_db_query(' SELECT id_choice FROM {db_prefix}poll_choices WHERE id_poll = {int:id_poll}', array('id_poll' => $bcinfo['id_poll'])); $choices = array(); while ($row = mysql_fetch_assoc($request)) { $choices[] = $row['id_choice']; } mysql_free_result($request); $delete_options = array(); foreach ($_POST['options'] as $k => $option) { // Make sure the key is numeric for sanity's sake. $k = (int) $k; // They've cleared the box. Either they want it deleted, or it never existed. if (trim($option) == '') { // They want it deleted. Bye. if (in_array($k, $choices)) { $delete_options[] = $k; } // Skip the rest... continue; } // Dress the option up for its big date with the database. $option = commonAPI::htmlspecialchars($option); // If it's already there, update it. If it's not... add it. if (in_array($k, $choices)) { smf_db_query(' UPDATE {db_prefix}poll_choices SET label = {string:option_name} WHERE id_poll = {int:id_poll} AND id_choice = {int:id_choice}', array('id_poll' => $bcinfo['id_poll'], 'id_choice' => $k, 'option_name' => $option)); } else { smf_db_insert('', '{db_prefix}poll_choices', array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255', 'votes' => 'int'), array($bcinfo['id_poll'], $k, $option, 0), array()); } } // I'm sorry, but... well, no one was choosing you. Poor options, I'll put you out of your misery. if (!empty($delete_options)) { smf_db_query(' DELETE FROM {db_prefix}log_polls WHERE id_poll = {int:id_poll} AND id_choice IN ({array_int:delete_options})', array('delete_options' => $delete_options, 'id_poll' => $bcinfo['id_poll'])); smf_db_query(' DELETE FROM {db_prefix}poll_choices WHERE id_poll = {int:id_poll} AND id_choice IN ({array_int:delete_options})', array('delete_options' => $delete_options, 'id_poll' => $bcinfo['id_poll'])); } // Shall I reset the vote count, sir? if (isset($_POST['resetVoteCount'])) { smf_db_query(' UPDATE {db_prefix}polls SET num_guest_voters = {int:no_votes}, reset_poll = {int:time} WHERE id_poll = {int:id_poll}', array('no_votes' => 0, 'id_poll' => $bcinfo['id_poll'], 'time' => time())); smf_db_query(' UPDATE {db_prefix}poll_choices SET votes = {int:no_votes} WHERE id_poll = {int:id_poll}', array('no_votes' => 0, 'id_poll' => $bcinfo['id_poll'])); smf_db_query(' DELETE FROM {db_prefix}log_polls WHERE id_poll = {int:id_poll}', array('id_poll' => $bcinfo['id_poll'])); } // Off we go. redirectexit('topic=' . $topic . '.' . $_REQUEST['start']); }
function validatePassword($password, $username, $restrict_in = array()) { global $modSettings, $smcFunc; // Perform basic requirements first. if (commonAPI::strlen($password) < (empty($modSettings['password_strength']) ? 4 : 8)) { return 'short'; } // Is this enough? if (empty($modSettings['password_strength'])) { return null; } // Otherwise, perform the medium strength test - checking if password appears in the restricted string. if (preg_match('~\\b' . preg_quote($password, '~') . '\\b~', implode(' ', $restrict_in)) != 0) { return 'restricted_words'; } elseif (commonAPI::strpos($password, $username) !== false) { return 'restricted_words'; } // !!! If pspell is available, use it on the word, and return restricted_words if it doesn't give "bad spelling"? // If just medium, we're done. if ($modSettings['password_strength'] == 1) { return null; } // Otherwise, hard test next, check for numbers and letters, uppercase too. $good = preg_match('~(\\D\\d|\\d\\D)~', $password) != 0; $good &= commonAPI::strtolower($password) != $password; return $good ? null : 'chars'; }
function getBoardIndex($boardIndexOptions) { global $smcFunc, $scripturl, $user_info, $modSettings, $txt; global $settings, $context; // For performance, track the latest post while going through the boards. if (!empty($boardIndexOptions['set_latest_post'])) { $latest_post = array('timestamp' => 0, 'ref' => 0); } // Find all boards and categories, as well as related information. This will be sorted by the natural order of boards and categories, which we control. $result_boards = smf_db_query(' SELECT' . ($boardIndexOptions['include_categories'] ? ' c.id_cat, c.name AS cat_name, c.description AS cat_desc,' : '') . ' b.id_board, b.name AS board_name, b.description, b.redirect, b.icon AS boardicon, CASE WHEN b.redirect != {string:blank_string} THEN 1 ELSE 0 END AS is_redirect, b.num_posts, b.num_topics, b.unapproved_posts, b.unapproved_topics, b.id_parent, b.allow_topics, IFNULL(m.poster_time, 0) AS poster_time, IFNULL(mem.member_name, m.poster_name) AS poster_name, m.subject, m1.subject AS first_subject, m.id_topic, t.id_first_msg AS id_first_msg, t.id_prefix, m1.icon AS icon, IFNULL(mem.real_name, m.poster_name) AS real_name, p.name as topic_prefix, ' . ($user_info['is_guest'] ? ' 1 AS is_read, 0 AS new_from,' : ' (IFNULL(lb.id_msg, 0) >= b.id_msg_updated) AS is_read, IFNULL(lb.id_msg, -1) + 1 AS new_from,' . ($boardIndexOptions['include_categories'] ? ' c.can_collapse, IFNULL(cc.id_member, 0) AS is_collapsed,' : '')) . ' IFNULL(mem.id_member, 0) AS id_member, m.id_msg, IFNULL(mods_mem.id_member, 0) AS id_moderator, mods_mem.real_name AS mod_real_name FROM {db_prefix}boards AS b' . ($boardIndexOptions['include_categories'] ? ' LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)' : '') . ' LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = b.id_last_msg) LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) LEFT JOIN {db_prefix}prefixes AS p ON (p.id_prefix = t.id_prefix) LEFT JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg) LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)' . ($user_info['is_guest'] ? '' : ' LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})' . ($boardIndexOptions['include_categories'] ? ' LEFT JOIN {db_prefix}collapsed_categories AS cc ON (cc.id_cat = c.id_cat AND cc.id_member = {int:current_member})' : '')) . ' LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = b.id_board) LEFT JOIN {db_prefix}members AS mods_mem ON (mods_mem.id_member = mods.id_member) WHERE {query_see_board}' . (empty($boardIndexOptions['countChildPosts']) ? empty($boardIndexOptions['base_level']) ? '' : ' AND b.child_level >= {int:child_level}' : ' AND b.child_level BETWEEN ' . $boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 1)), array('current_member' => $user_info['id'], 'child_level' => $boardIndexOptions['base_level'], 'blank_string' => '')); // Start with an empty array. if ($boardIndexOptions['include_categories']) { $categories = array(); } else { $this_category = array(); } $total_ignored_boards = 0; // Run through the categories and boards (or only boards).... while ($row_board = mysql_fetch_assoc($result_boards)) { // Perhaps we are ignoring this board? $ignoreThisBoard = in_array($row_board['id_board'], $user_info['ignoreboards']); $total_ignored_boards += $ignoreThisBoard ? 1 : 0; $row_board['is_read'] = !empty($row_board['is_read']) || $ignoreThisBoard ? '1' : '0'; if ($boardIndexOptions['include_categories']) { // Haven't set this category yet. if (empty($categories[$row_board['id_cat']])) { $categories[$row_board['id_cat']] = array('id' => $row_board['id_cat'], 'name' => $row_board['cat_name'], 'desc' => $row_board['cat_desc'], 'is_collapsed' => isset($row_board['can_collapse']) && $row_board['can_collapse'] == 1 && $row_board['is_collapsed'] > 0, 'can_collapse' => isset($row_board['can_collapse']) && $row_board['can_collapse'] == 1, 'collapse_href' => isset($row_board['can_collapse']) ? $scripturl . '?action=collapse;c=' . $row_board['id_cat'] . ';sa=' . ($row_board['is_collapsed'] > 0 ? 'expand;' : 'collapse;') . $context['session_var'] . '=' . $context['session_id'] . '#c' . $row_board['id_cat'] : '', 'collapse_image' => isset($row_board['can_collapse']) ? '<img class="clipsrc ' . ($row_board['is_collapsed'] ? ' _expand' : '_collapse') . '" src="' . $settings['images_url'] . '/clipsrc.png" alt="-" />' : '', 'href' => $scripturl . '#c' . $row_board['id_cat'], 'boards' => array(), 'is_root' => $row_board['cat_name'][0] === '!' ? true : false, 'new' => false); $categories[$row_board['id_cat']]['link'] = '<a id="c' . $row_board['id_cat'] . '"></a>' . ($categories[$row_board['id_cat']]['can_collapse'] ? '<a href="' . $categories[$row_board['id_cat']]['collapse_href'] . '">' . $row_board['cat_name'] . '</a>' : $row_board['cat_name']); } // If this board has new posts in it (and isn't the recycle bin!) then the category is new. if (empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $row_board['id_board']) { $categories[$row_board['id_cat']]['new'] |= empty($row_board['is_read']) && $row_board['poster_name'] != ''; } // Avoid showing category unread link where it only has redirection boards. $categories[$row_board['id_cat']]['show_unread'] = !empty($categories[$row_board['id_cat']]['show_unread']) ? 1 : !$row_board['is_redirect']; // Collapsed category - don't do any of this. //if ($categories[$row_board['id_cat']]['is_collapsed']) // continue; // Let's save some typing. Climbing the array might be slower, anyhow. $this_category =& $categories[$row_board['id_cat']]['boards']; } // This is a parent board. if ($row_board['id_parent'] == $boardIndexOptions['parent_id']) { // Is this a new board, or just another moderator? if (!isset($this_category[$row_board['id_board']])) { // Not a child. $isChild = false; $href = URL::board($row_board['id_board'], $row_board['board_name'], 0, false); $this_category[$row_board['id_board']] = array('new' => empty($row_board['is_read']), 'id' => $row_board['id_board'], 'name' => $row_board['board_name'], 'description' => $row_board['description'], 'moderators' => array(), 'link_moderators' => array(), 'children' => array(), 'link_children' => array(), 'children_new' => false, 'topics' => $row_board['num_topics'], 'posts' => $row_board['num_posts'], 'is_redirect' => $row_board['is_redirect'], 'is_page' => !empty($row_board['redirect']) && $row_board['redirect'][0] === '%' && intval(substr($row_board['redirect'], 1)) > 0, 'redirect' => $row_board['redirect'], 'boardicon' => $row_board['boardicon'], 'unapproved_topics' => $row_board['unapproved_topics'], 'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'], 'can_approve_posts' => !empty($user_info['mod_cache']['ap']) && ($user_info['mod_cache']['ap'] == array(0) || in_array($row_board['id_board'], $user_info['mod_cache']['ap'])), 'href' => $href, 'link' => '<a href="' . $href . '">' . $row_board['board_name'] . '</a>', 'act_as_cat' => $row_board['allow_topics'] ? false : true, 'ignored' => $ignoreThisBoard); $this_category[$row_board['id_board']]['page_link'] = $this_category[$row_board['id_board']]['is_page'] ? URL::topic(intval(substr($this_category[$row_board['id_board']]['redirect'], 1)), $this_category[$row_board['id_board']]['name'], 0) : ''; } if (!empty($row_board['id_moderator'])) { $this_category[$row_board['id_board']]['moderators'][$row_board['id_moderator']] = array('id' => $row_board['id_moderator'], 'name' => $row_board['mod_real_name'], 'href' => $scripturl . '?action=profile;u=' . $row_board['id_moderator'], 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_board['id_moderator'] . '" title="' . $txt['board_moderator'] . '">' . $row_board['mod_real_name'] . '</a>'); $this_category[$row_board['id_board']]['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $row_board['id_moderator'] . '" title="' . $txt['board_moderator'] . '">' . $row_board['mod_real_name'] . '</a>'; } } elseif (isset($this_category[$row_board['id_parent']]['children']) && !isset($this_category[$row_board['id_parent']]['children'][$row_board['id_board']])) { // A valid child! $isChild = true; $href = URL::board($row_board['id_board'], $row_board['board_name'], 0, false); $this_category[$row_board['id_parent']]['children'][$row_board['id_board']] = array('id' => $row_board['id_board'], 'name' => $row_board['board_name'], 'description' => $row_board['description'], 'short_description' => !empty($row_board['description']) ? $modSettings['child_board_desc_shortened'] ? '(' . commonAPI::substr($row_board['description'], 0, $modSettings['child_board_desc_shortened']) . '...)' : '(' . $row_board['description'] . ')' : '', 'new' => empty($row_board['is_read']) && $row_board['poster_name'] != '', 'topics' => $row_board['num_topics'], 'posts' => $row_board['num_posts'], 'is_redirect' => $row_board['is_redirect'], 'is_page' => !empty($row_board['redirect']) && $row_board['redirect'][0] === '%' && intval(substr($row_board['redirect'], 1)) > 0, 'redirect' => $row_board['redirect'], 'boardicon' => $row_board['boardicon'], 'unapproved_topics' => $row_board['unapproved_topics'], 'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'], 'can_approve_posts' => !empty($user_info['mod_cache']['ap']) && ($user_info['mod_cache']['ap'] == array(0) || in_array($row_board['id_board'], $user_info['mod_cache']['ap'])), 'href' => $href, 'link' => '<a href="' . $href . '">' . $row_board['board_name'] . '</a>', 'act_as_cat' => $row_board['allow_topics'] ? false : true, 'ignored' => $ignoreThisBoard); $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['page_link'] = $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['is_page'] ? URL::topic(intval(substr($this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['redirect'], 1)), $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['name'], 0) : ''; // Counting child board posts is... slow :/. if (!empty($boardIndexOptions['countChildPosts']) && !$row_board['is_redirect']) { $this_category[$row_board['id_parent']]['posts'] += $row_board['num_posts']; $this_category[$row_board['id_parent']]['topics'] += $row_board['num_topics']; } // Does this board contain new boards? $this_category[$row_board['id_parent']]['children_new'] |= empty($row_board['is_read']); // This is easier to use in many cases for the theme.... $this_category[$row_board['id_parent']]['link_children'][] =& $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['link']; } elseif (!empty($boardIndexOptions['countChildPosts'])) { if (!isset($parent_map)) { $parent_map = array(); } if (!isset($parent_map[$row_board['id_parent']])) { foreach ($this_category as $id => $board) { if (!isset($board['children'][$row_board['id_parent']])) { continue; } $parent_map[$row_board['id_parent']] = array(&$this_category[$id], &$this_category[$id]['children'][$row_board['id_parent']]); $parent_map[$row_board['id_board']] = array(&$this_category[$id], &$this_category[$id]['children'][$row_board['id_parent']]); break; } } if (isset($parent_map[$row_board['id_parent']]) && !$row_board['is_redirect']) { $parent_map[$row_board['id_parent']][0]['posts'] += $row_board['num_posts']; $parent_map[$row_board['id_parent']][0]['topics'] += $row_board['num_topics']; $parent_map[$row_board['id_parent']][1]['posts'] += $row_board['num_posts']; $parent_map[$row_board['id_parent']][1]['topics'] += $row_board['num_topics']; continue; } continue; } else { continue; } // Prepare the subject, and make sure it's not too long. censorText($row_board['subject']); $mhref = $row_board['poster_name'] != '' && !empty($row_board['id_member']) ? URL::user($row_board['id_member'], $row_board['real_name']) : ''; $this_last_post = array('id' => $row_board['id_msg'], 'time' => $row_board['poster_time'] > 0 ? timeformat($row_board['poster_time']) : $txt['not_applicable'], 'timestamp' => forum_time(true, $row_board['poster_time']), 'member' => array('id' => $row_board['id_member'], 'username' => $row_board['poster_name'] != '' ? $row_board['poster_name'] : $txt['not_applicable'], 'name' => $row_board['real_name'], 'href' => $mhref, 'link' => $row_board['poster_name'] != '' ? !empty($row_board['id_member']) ? '<a onclick="getMcard(' . $row_board['id_member'] . ', $(this));return(false);" href="' . $mhref . '">' . $row_board['real_name'] . '</a>' : $row_board['real_name'] : $txt['not_applicable']), 'start' => 'msg' . $row_board['new_from'], 'topic' => $row_board['id_topic'], 'prefix' => !empty($row_board['topic_prefix']) ? html_entity_decode($row_board['topic_prefix']) . ' ' : ''); $row_board['short_subject'] = shorten_subject($row_board['subject'], 50); $this_last_post['subject'] = $row_board['short_subject']; $this_first_post = array('id' => $row_board['id_first_msg'], 'icon' => $row_board['icon'], 'icon_url' => getPostIcon($row_board['icon'])); // Provide the href and link. if ($row_board['subject'] != '') { $this_last_post['href'] = URL::topic($row_board['id_topic'], $row_board['first_subject'], 0, false, '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']), '#new'); if (empty($row_board['is_read'])) { $this_last_post['href'] = URL::addParam($this_last_post['href'], 'boardseen'); } //$this_last_post['href'] = $scripturl . '?topic=' . $row_board['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']) . (empty($row_board['is_read']) ? ';boardseen' : '') . '#new'; $this_last_post['link'] = '<a rel="nofollow" href="' . $this_last_post['href'] . '" title="' . $row_board['subject'] . '">' . $row_board['short_subject'] . '</a>'; $this_last_post['topichref'] = URL::topic($row_board['id_topic'], $row_board['first_subject'], 0); // $scripturl . '?topic=' . $row_board['id_topic']; $this_last_post['topiclink'] = '<a href="' . $this_last_post['topichref'] . '" title="' . $row_board['first_subject'] . '">' . $row_board['short_subject'] . '</a>'; } else { $this_last_post['href'] = ''; $this_last_post['link'] = $txt['not_applicable']; $this_last_post['topiclink'] = $txt['not_applicable']; } // Set the last post in the parent board. if ($row_board['id_parent'] == $boardIndexOptions['parent_id'] || $isChild && !empty($row_board['poster_time']) && $this_category[$row_board['id_parent']]['last_post']['timestamp'] < forum_time(true, $row_board['poster_time'])) { $this_category[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['last_post'] = $this_last_post; $this_category[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['first_post'] = $this_first_post; } // Just in the child...? if ($isChild) { $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['last_post'] = $this_last_post; $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['first_post'] = $this_first_post; // If there are no posts in this board, it really can't be new... $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['new'] &= $row_board['poster_name'] != ''; } elseif ($row_board['poster_name'] == '') { $this_category[$row_board['id_board']]['new'] = false; } // Determine a global most recent topic. if (!empty($boardIndexOptions['set_latest_post']) && !empty($row_board['poster_time']) && $row_board['poster_time'] > $latest_post['timestamp'] && !$ignoreThisBoard) { $latest_post = array('timestamp' => $row_board['poster_time'], 'ref' => &$this_category[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['last_post']); } } mysql_free_result($result_boards); // By now we should know the most recent post...if we wanna know it that is. if (!empty($boardIndexOptions['set_latest_post']) && !empty($latest_post['ref'])) { $context['latest_post'] = $latest_post['ref']; } $hidden_boards = $visible_boards = 0; $context['hidden_boards']['id'] = $context['hidden_boards']['is_collapsed'] = 0; // only run this if we actually have some boards on the ignore list to save cycles. if ($total_ignored_boards) { if ($boardIndexOptions['include_categories']) { foreach ($categories as &$cat) { $hidden_boards += hideIgnoredBoards($cat['boards']); } } else { if (count($this_category)) { $hidden_boards += hideIgnoredBoards($this_category); } } $context['hidden_boards']['notice'] = $txt[$hidden_boards > 1 ? 'hidden_boards_notice_many' : 'hidden_boards_notice_one']; $context['hidden_boards']['setup_notice'] = sprintf($txt['hidden_boards_setup_notice'], $scripturl . '?action=profile;area=ignoreboards'); } $context['hidden_boards']['hidden_count'] = $hidden_boards; $context['hidden_boards']['visible_count'] = $visible_boards; return $boardIndexOptions['include_categories'] ? $categories : $this_category; }
function template_package_list() { global $context, $settings, $options, $txt, $scripturl, $smcFunc; echo ' <div id="admincenter"> <div class="cat_bar"> <h3>' . $context['page_title'] . '</h3> </div> <div class="blue_container"> <div class="content">'; // No packages, as yet. if (empty($context['package_list'])) { echo ' <ul> <li>', $txt['no_packages'], '</li> </ul>'; } else { echo ' <ul id="package_list">'; foreach ($context['package_list'] as $i => $packageSection) { echo ' <li> <strong><img id="ps_img_', $i, '" src="', $settings['images_url'], '/upshrink.png" alt="*" style="display: none;" /> ', $packageSection['title'], '</strong>'; if (!empty($packageSection['text'])) { echo ' <div class="information">', $packageSection['text'], '</div>'; } echo ' <', $context['list_type'], ' id="package_section_', $i, '" class="packages">'; $alt = false; foreach ($packageSection['items'] as $id => $package) { echo ' <li>'; // Textual message. Could be empty just for a blank line... if ($package['is_text']) { echo ' ', empty($package['name']) ? ' ' : $package['name']; } elseif ($package['is_line']) { echo ' <hr class="hrcolor" />'; } elseif ($package['is_remote']) { echo ' <strong>', $package['link'], '</strong>'; } elseif ($package['is_heading'] || $package['is_title']) { echo ' <strong>', $package['name'], '</strong>'; } else { // 1. Some mod [ Download ]. echo ' <strong><img id="ps_img_', $i, '_pkg_', $id, '" src="', $settings['images_url'], '/upshrink.png" alt="*" style="display: none;" /> ', $package['can_install'] ? '<strong>' . $package['name'] . '</strong> <a href="' . $package['download']['href'] . '">[ ' . $txt['download'] . ' ]</a>' : $package['name']; // Mark as installed and current? if ($package['is_installed'] && !$package['is_newer']) { echo '<img src="', $settings['images_url'], '/icons/package_', $package['is_current'] ? 'installed' : 'old', '.gif" width="12" height="11" align="middle" style="margin-left: 2ex;" alt="', $package['is_current'] ? $txt['package_installed_current'] : $txt['package_installed_old'], '" />'; } echo ' </strong> <ul id="package_section_', $i, '_pkg_', $id, '" class="package_section">'; // Show the mod type? if ($package['type'] != '') { echo ' <li class="package_section">', $txt['package_type'], ': ', commonAPI::ucwords(commonAPI::strtolower($package['type'])), '</li>'; } // Show the version number? if ($package['version'] != '') { echo ' <li class="package_section">', $txt['mod_version'], ': ', $package['version'], '</li>'; } // How 'bout the author? if (!empty($package['author']) && $package['author']['name'] != '' && isset($package['author']['link'])) { echo ' <li class="package_section">', $txt['mod_author'], ': ', $package['author']['link'], '</li>'; } // The homepage.... if ($package['author']['website']['link'] != '') { echo ' <li class="package_section">', $txt['author_website'], ': ', $package['author']['website']['link'], '</li>'; } // Desciption: bleh bleh! // Location of file: http://someplace/. echo ' <li class="package_section">', $txt['file_location'], ': <a href="', $package['href'], '">', $package['href'], '</a></li> <li class="package_section"><div class="information">', $txt['package_description'], ': ', $package['description'], '</div></li> </ul>'; } $alt = !$alt; echo ' </li>'; } echo ' </', $context['list_type'], '> </li>'; } echo ' </ul>'; } echo ' </div> </div> <div class="padding smalltext floatleft"> ', $txt['package_installed_key'], ' <img src="', $settings['images_url'], '/icons/package_installed.gif" alt="" align="middle" style="margin-left: 1ex;" /> ', $txt['package_installed_current'], ' <img src="', $settings['images_url'], '/icons/package_old.gif" alt="" align="middle" style="margin-left: 2ex;" /> ', $txt['package_installed_old'], ' </div> </div> <br class="clear" /> '; // Now go through and turn off all the sections. if (!empty($context['package_list'])) { $section_count = count($context['package_list']); echo ' <script type="text/javascript"><!-- // --><![CDATA['; foreach ($context['package_list'] as $section => $ps) { echo ''; foreach ($ps['items'] as $id => $package) { if (!$package['is_text'] && !$package['is_line'] && !$package['is_remote']) { echo ''; } } } echo ' // ]]></script>'; } }
function AutoSuggest_Search_Tags() { global $user_info, $txt, $smcFunc; $_REQUEST['search'] = trim(commonAPI::strtolower($_REQUEST['search'])) . '*'; $_REQUEST['search'] = strtr($_REQUEST['search'], array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_', '&' => '&')); // Find tags $request = smf_db_query(' SELECT id_member, real_name FROM {db_prefix}tags WHERE tag LIKE {string:search} LIMIT ' . (strlen($_REQUEST['search']) <= 2 ? '100' : '800'), array('search' => $_REQUEST['search'])); $xml_data = array('tags' => array('identifier' => 'tag', 'children' => array())); while ($row = mysql_fetch_assoc($request)) { $xml_data['tags']['children'][] = array('attributes' => array('id' => $row['id_tag']), 'value' => $row['tag']); } mysql_free_result($request); return $xml_data; }
function getXmlRecent($xml_format) { global $user_info, $scripturl, $modSettings, $board; global $query_this_board, $smcFunc, $settings, $context; $done = false; $loops = 0; while (!$done) { $optimize_msg = implode(' AND ', $context['optimize_msg']); $request = smf_db_query(' SELECT m.id_msg FROM {db_prefix}messages AS m INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) WHERE ' . $query_this_board . (empty($optimize_msg) ? '' : ' AND {raw:optimize_msg}') . (empty($board) ? '' : ' AND m.id_board = {int:current_board}') . ($modSettings['postmod_active'] ? ' AND m.approved = {int:is_approved}' : '') . ' ORDER BY m.id_msg DESC LIMIT {int:limit}', array('limit' => $_GET['limit'], 'current_board' => $board, 'is_approved' => 1, 'optimize_msg' => $optimize_msg)); // If we don't have $_GET['limit'] results, try again with an unoptimized version covering all rows. if ($loops < 2 && mysql_num_rows($request) < $_GET['limit']) { mysql_free_result($request); if (empty($_REQUEST['boards']) && empty($board)) { unset($context['optimize_msg']['lowest']); } else { $context['optimize_msg']['lowest'] = $loops ? 'm.id_msg >= t.id_first_msg' : 'm.id_msg >= (t.id_last_msg - t.id_first_msg) / 2'; } $loops++; } else { $done = true; } } $messages = array(); while ($row = mysql_fetch_assoc($request)) { $messages[] = $row['id_msg']; } mysql_free_result($request); if (empty($messages)) { return array(); } // Find the most recent posts this user can see. $request = smf_db_query(' SELECT m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, m.id_topic, t.id_board, b.name AS bname, t.num_replies, m.id_member, m.icon, mf.id_member AS id_first_member, IFNULL(mem.real_name, m.poster_name) AS poster_name, mf.subject AS first_subject, IFNULL(memf.real_name, mf.poster_name) AS first_poster_name, mem.hide_email, IFNULL(mem.email_address, m.poster_email) AS poster_email, m.modified_time FROM {db_prefix}messages AS m INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) LEFT JOIN {db_prefix}members AS memf ON (memf.id_member = mf.id_member) WHERE m.id_msg IN ({array_int:message_list}) ' . (empty($board) ? '' : 'AND t.id_board = {int:current_board}') . ' ORDER BY m.id_msg DESC LIMIT {int:limit}', array('limit' => $_GET['limit'], 'current_board' => $board, 'message_list' => $messages)); $data = array(); while ($row = mysql_fetch_assoc($request)) { // Limit the length of the message, if the option is set. if (!empty($modSettings['xmlnews_maxlen']) && commonAPI::strlen(str_replace('<br />', "\n", $row['body'])) > $modSettings['xmlnews_maxlen']) { $row['body'] = strtr(commonAPI::substr(str_replace('<br />', "\n", $row['body']), 0, $modSettings['xmlnews_maxlen'] - 3), array("\n" => '<br />')) . '...'; } $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']); censorText($row['body']); censorText($row['subject']); // Doesn't work as well as news, but it kinda does.. if ($xml_format == 'rss' || $xml_format == 'rss2') { $data[] = array('title' => $row['subject'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'description' => cdata_parse($row['body']), 'author' => in_array(showEmailAddress(!empty($row['hide_email']), $row['id_member']), array('yes', 'yes_permission_override')) ? $row['poster_email'] : null, 'category' => cdata_parse($row['bname']), 'comments' => $scripturl . '?action=post;topic=' . $row['id_topic'] . '.0', 'pubDate' => gmdate('D, d M Y H:i:s \\G\\M\\T', $row['poster_time']), 'guid' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']); } elseif ($xml_format == 'rdf') { $data[] = array('title' => $row['subject'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'description' => cdata_parse($row['body'])); } elseif ($xml_format == 'atom') { $data[] = array('title' => $row['subject'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'summary' => cdata_parse($row['body']), 'category' => array('term' => $row['id_board'], 'label' => cdata_parse($row['bname'])), 'author' => array('name' => $row['poster_name'], 'email' => in_array(showEmailAddress(!empty($row['hide_email']), $row['id_member']), array('yes', 'yes_permission_override')) ? $row['poster_email'] : null, 'uri' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : ''), 'published' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $row['poster_time']), 'updated' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', empty($row['modified_time']) ? $row['poster_time'] : $row['modified_time']), 'id' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'icon' => $settings['images_url'] . '/icons/' . $row['icon'] . '.gif'); } else { $data[] = array('time' => htmlspecialchars(strip_tags(timeformat($row['poster_time']))), 'id' => $row['id_msg'], 'subject' => cdata_parse($row['subject']), 'body' => cdata_parse($row['body']), 'starter' => array('name' => cdata_parse($row['first_poster_name']), 'id' => $row['id_first_member'], 'link' => !empty($row['id_first_member']) ? $scripturl . '?action=profile;u=' . $row['id_first_member'] : ''), 'poster' => array('name' => cdata_parse($row['poster_name']), 'id' => $row['id_member'], 'link' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : ''), 'topic' => array('subject' => cdata_parse($row['first_subject']), 'id' => $row['id_topic'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.new#new'), 'board' => array('name' => cdata_parse($row['bname']), 'id' => $row['id_board'], 'link' => $scripturl . '?board=' . $row['id_board'] . '.0'), 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']); } } mysql_free_result($request); return $data; }