/** * 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 ModifyWarningTemplate() { global $context, $txt, $user_info, $sourcedir; EoS_Smarty::loadTemplate('modcenter/modcenter_base'); EoS_Smarty::getConfigInstance()->registerHookTemplate('modcenter_content_area', 'modcenter/edit_warning'); $context['id_template'] = isset($_REQUEST['tid']) ? (int) $_REQUEST['tid'] : 0; $context['is_edit'] = $context['id_template']; // Standard template things. $context['page_title'] = $context['is_edit'] ? $txt['mc_warning_template_modify'] : $txt['mc_warning_template_add']; $context['sub_template'] = 'warn_template'; $context[$context['moderation_menu_name']]['current_subsection'] = 'templates'; // Defaults. $context['template_data'] = array('title' => '', 'body' => $txt['mc_warning_template_body_default'], 'personal' => false, 'can_edit_personal' => true); // If it's an edit load it. if ($context['is_edit']) { $request = smf_db_query(' SELECT id_member, id_recipient, recipient_name AS template_title, body FROM {db_prefix}log_comments WHERE id_comment = {int:id} AND comment_type = {string:warntpl} AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})', array('id' => $context['id_template'], 'warntpl' => 'warntpl', 'generic' => 0, 'current_member' => $user_info['id'])); while ($row = mysql_fetch_assoc($request)) { $context['template_data'] = array('title' => $row['template_title'], 'body' => commonAPI::htmlspecialchars($row['body']), 'personal' => $row['id_recipient'], 'can_edit_personal' => $row['id_member'] == $user_info['id']); } mysql_free_result($request); } // Wait, we are saving? if (isset($_POST['save'])) { checkSession('post'); // To check the BBC is pretty good... require_once $sourcedir . '/lib/Subs-Post.php'; // Bit of cleaning! $_POST['template_body'] = trim($_POST['template_body']); $_POST['template_title'] = trim($_POST['template_title']); // Need something in both boxes. if (empty($_POST['template_body']) || empty($_POST['template_title'])) { fatal_error($txt['mc_warning_template_error_empty']); } // Safety first. $_POST['template_title'] = commonAPI::htmlspecialchars($_POST['template_title']); // Clean up BBC. preparsecode($_POST['template_body']); // But put line breaks back! $_POST['template_body'] = strtr($_POST['template_body'], array('<br />' => "\n")); // Is this personal? $recipient_id = !empty($_POST['make_personal']) ? $user_info['id'] : 0; // If we are this far it's save time. if ($context['is_edit']) { // Simple update... smf_db_query(' UPDATE {db_prefix}log_comments SET id_recipient = {int:personal}, recipient_name = {string:title}, body = {string:body} WHERE id_comment = {int:id} AND comment_type = {string:warntpl} AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})' . ($recipient_id ? ' AND id_member = {int:current_member}' : ''), array('personal' => $recipient_id, 'title' => $_POST['template_title'], 'body' => $_POST['template_body'], 'id' => $context['id_template'], 'warntpl' => 'warntpl', 'generic' => 0, 'current_member' => $user_info['id'])); // If it wasn't visible and now is they've effectively added it. if ($context['template_data']['personal'] && !$recipient_id) { logAction('add_warn_template', array('template' => $_POST['template_title'])); } elseif (!$context['template_data']['personal'] && $recipient_id) { logAction('delete_warn_template', array('template' => $_POST['template_title'])); } else { logAction('modify_warn_template', array('template' => $_POST['template_title'])); } } else { smf_db_insert('', '{db_prefix}log_comments', array('id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'id_recipient' => 'int', 'recipient_name' => 'string-255', 'body' => 'string-65535', 'log_time' => 'int'), array($user_info['id'], $user_info['name'], 'warntpl', $recipient_id, $_POST['template_title'], $_POST['template_body'], time()), array('id_comment')); logAction('add_warn_template', array('template' => $_POST['template_title'])); } // Get out of town... redirectexit('action=moderate;area=warnings;sa=templates'); } }
function loadTheme($id_theme = 0, $initialize = true) { global $user_info, $user_settings, $board_info, $boarddir, $db_show_debug; global $txt, $boardurl, $scripturl, $mbname, $modSettings; global $context, $settings, $options, $sourcedir, $ssi_theme; // The theme was specified by parameter. if (!empty($id_theme)) { $id_theme = (int) $id_theme; } elseif (!empty($_REQUEST['theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum'))) { $id_theme = (int) $_REQUEST['theme']; $_SESSION['id_theme'] = $id_theme; } elseif (!empty($_SESSION['id_theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum'))) { $id_theme = (int) $_SESSION['id_theme']; } elseif (!empty($user_info['theme']) && !isset($_REQUEST['theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum'))) { $id_theme = $user_info['theme']; } elseif (!empty($board_info['theme'])) { $id_theme = $board_info['theme']; } else { $id_theme = $modSettings['theme_guests']; } // Verify the id_theme... no foul play. // Always allow the board specific theme, if they are overriding. if (!empty($board_info['theme']) && $board_info['override_theme']) { $id_theme = $board_info['theme']; } elseif (!empty($ssi_theme) && $id_theme == $ssi_theme) { $id_theme = (int) $id_theme; } elseif (!empty($modSettings['knownThemes']) && !allowedTo('admin_forum')) { $themes = explode(',', $modSettings['knownThemes']); if (!in_array($id_theme, $themes)) { $id_theme = $modSettings['theme_guests']; } else { $id_theme = (int) $id_theme; } } else { $id_theme = (int) $id_theme; } $member = empty($user_info['id']) ? -1 : $user_info['id']; if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2 && ($temp = CacheAPI::getCache('theme_settings-' . $id_theme . ':' . $member, 60)) != null && time() - 60 > $modSettings['settings_updated']) { $themeData = $temp; $flag = true; } elseif (($temp = CacheAPI::getCache('theme_settings-' . $id_theme, 90)) != null && time() - 60 > $modSettings['settings_updated']) { $themeData = $temp + array($member => array()); } else { $themeData = array(-1 => array(), 0 => array(), $member => array()); } if (empty($flag)) { // Load variables from the current or default theme, global or this user's. $result = smf_db_query(' SELECT variable, value, id_member, id_theme FROM {db_prefix}themes WHERE id_member' . (empty($themeData[0]) ? ' IN (-1, 0, {int:id_member})' : ' = {int:id_member}') . ' AND id_theme' . ($id_theme == 1 ? ' = {int:id_theme}' : ' IN ({int:id_theme}, 1)'), array('id_theme' => $id_theme, 'id_member' => $member)); // Pick between $settings and $options depending on whose data it is. while ($row = mysql_fetch_assoc($result)) { // There are just things we shouldn't be able to change as members. if ($row['id_member'] != 0 && in_array($row['variable'], array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url'))) { continue; } // If this is the theme_dir of the default theme, store it. if (in_array($row['variable'], array('theme_dir', 'theme_url', 'images_url')) && $row['id_theme'] == '1' && empty($row['id_member'])) { $themeData[0]['default_' . $row['variable']] = $row['value']; } // If this isn't set yet, is a theme option, or is not the default theme.. if (!isset($themeData[$row['id_member']][$row['variable']]) || $row['id_theme'] != '1') { $themeData[$row['id_member']][$row['variable']] = substr($row['variable'], 0, 5) == 'show_' ? $row['value'] == '1' : $row['value']; } } mysql_free_result($result); if (!empty($themeData[-1])) { foreach ($themeData[-1] as $k => $v) { if (!isset($themeData[$member][$k])) { $themeData[$member][$k] = $v; } } } if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) { CacheAPI::putCache('theme_settings-' . $id_theme . ':' . $member, $themeData, 60); } elseif (!isset($temp)) { CacheAPI::putCache('theme_settings-' . $id_theme, array(-1 => $themeData[-1], 0 => $themeData[0]), 90); } } $settings = $themeData[0]; $options = $themeData[$member]; $member_tracking_optin = $user_info['is_guest'] || (empty($options['disable_analytics']) ? 1 : !$options['disable_analytics']); if (isset($modSettings['embed_GA']) && $modSettings['embed_GA'] && !empty($modSettings['GA_tracker_id']) && !empty($modSettings['GA_domain_name']) && $member_tracking_optin) { $context['want_GA_embedded'] = true; } if (isset($modSettings['embed_piwik']) && $modSettings['embed_piwik'] && !empty($modSettings['piwik_uri']) && !empty($modSettings['piwik_tracker_id']) && $member_tracking_optin) { $context['want_piwik_embedded'] = true; $modSettings['piwik_uri'] = rtrim($modSettings['piwik_uri'], '/\\ '); } $settings['theme_id'] = $id_theme; $settings['actual_theme_url'] = $settings['theme_url']; $settings['actual_images_url'] = $settings['images_url']; $settings['actual_theme_dir'] = $settings['theme_dir']; $settings['posticons_url'] = $settings['images_url'] . '/post/'; $settings['template_dirs'] = array(); // This theme first. $settings['template_dirs'][] = $settings['theme_dir']; // Based on theme (if there is one). if (!empty($settings['base_theme_dir'])) { $settings['template_dirs'][] = $settings['base_theme_dir']; } // Lastly the default theme. if ($settings['theme_dir'] != $settings['default_theme_dir']) { $settings['template_dirs'][] = $settings['default_theme_dir']; } if (!$initialize) { return; } // Check to see if they're accessing it from the wrong place. if (isset($_SERVER['HTTP_HOST']) || isset($_SERVER['SERVER_NAME'])) { $detected_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 'https://' : 'http://'; $detected_url .= empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST']; $temp = preg_replace('~/' . basename($scripturl) . '(/.+)?$~', '', strtr(dirname($_SERVER['PHP_SELF']), '\\', '/')); if ($temp != '/') { $detected_url .= $temp; } } if (isset($detected_url) && $detected_url != $boardurl) { // Try #1 - check if it's in a list of alias addresses. if (!empty($modSettings['forum_alias_urls'])) { $aliases = explode(',', $modSettings['forum_alias_urls']); foreach ($aliases as $alias) { // Rip off all the boring parts, spaces, etc. if ($detected_url == trim($alias) || strtr($detected_url, array('http://' => '', 'https://' => '')) == trim($alias)) { $do_fix = true; } } } // Hmm... check #2 - is it just different by a www? Send them to the correct place!! if (empty($do_fix) && strtr($detected_url, array('://' => '://www.')) == $boardurl && (empty($_GET) || count($_GET) == 1) && SMF != 'SSI') { // Okay, this seems weird, but we don't want an endless loop - this will make $_GET not empty ;). if (empty($_GET)) { redirectexit('wwwRedirect'); } else { list($k, $v) = each($_GET); if ($k != 'wwwRedirect') { redirectexit('wwwRedirect;' . $k . '=' . $v); } } } // #3 is just a check for SSL... if (strtr($detected_url, array('https://' => 'http://')) == $boardurl) { $do_fix = true; } // Okay, #4 - perhaps it's an IP address? We're gonna want to use that one, then. (assuming it's the IP or something...) if (!empty($do_fix) || preg_match('~^http[s]?://(?:[\\d\\.:]+|\\[[\\d:]+\\](?::\\d+)?)(?:$|/)~', $detected_url) == 1) { // Caching is good ;). $oldurl = $boardurl; // Fix $boardurl and $scripturl. $boardurl = $detected_url; $scripturl = strtr($scripturl, array($oldurl => $boardurl)); $_SERVER['REQUEST_URL'] = strtr($_SERVER['REQUEST_URL'], array($oldurl => $boardurl)); // Fix the theme urls... $settings['theme_url'] = strtr($settings['theme_url'], array($oldurl => $boardurl)); $settings['default_theme_url'] = strtr($settings['default_theme_url'], array($oldurl => $boardurl)); $settings['actual_theme_url'] = strtr($settings['actual_theme_url'], array($oldurl => $boardurl)); $settings['images_url'] = strtr($settings['images_url'], array($oldurl => $boardurl)); $settings['default_images_url'] = strtr($settings['default_images_url'], array($oldurl => $boardurl)); $settings['actual_images_url'] = strtr($settings['actual_images_url'], array($oldurl => $boardurl)); // And just a few mod settings :). $modSettings['smileys_url'] = strtr($modSettings['smileys_url'], array($oldurl => $boardurl)); $modSettings['avatar_url'] = strtr($modSettings['avatar_url'], array($oldurl => $boardurl)); // Clean up after loadBoard(). if (isset($board_info['moderators'])) { foreach ($board_info['moderators'] as $k => $dummy) { $board_info['moderators'][$k]['href'] = strtr($dummy['href'], array($oldurl => $boardurl)); $board_info['moderators'][$k]['link'] = strtr($dummy['link'], array('"' . $oldurl => '"' . $boardurl)); } } foreach ($context['linktree'] as $k => $dummy) { $context['linktree'][$k]['url'] = strtr($dummy['url'], array($oldurl => $boardurl)); } } } // Set up the contextual user array. $context['user'] = array('id' => $user_info['id'], 'is_logged' => !$user_info['is_guest'], 'is_guest' => &$user_info['is_guest'], 'is_admin' => &$user_info['is_admin'], 'is_mod' => &$user_info['is_mod'], 'can_mod' => allowedTo('access_mod_center') || !$user_info['is_guest'] && ($user_info['mod_cache']['gq'] != '0=1' || $user_info['mod_cache']['bq'] != '0=1' || $modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap'])), 'username' => $user_info['username'], 'language' => $user_info['language'], 'email' => $user_info['email'], 'ignoreusers' => $user_info['ignoreusers']); if (!$context['user']['is_guest']) { $context['user']['name'] = $user_info['name']; } elseif ($context['user']['is_guest'] && !empty($txt['guest_title'])) { $context['user']['name'] = $txt['guest_title']; } // Determine the current smiley set and map it to a numeric id (parsed post cache needs this, because // we don't want to left join with string matching $smiley_sets = explode(',', $modSettings['smiley_sets_known']); $user_info['smiley_set'] = !in_array($user_info['smiley_set'], $smiley_sets) && $user_info['smiley_set'] != 'none' || empty($modSettings['smiley_sets_enable']) ? !empty($settings['smiley_sets_default']) ? $settings['smiley_sets_default'] : $modSettings['smiley_sets_default'] : $user_info['smiley_set']; if ($user_info['smiley_set'] == 'none') { $user_info['smiley_set_id'] = 0; } else { $user_info['smiley_set_id'] = array_search($user_info['smiley_set'], $smiley_sets) + 1; } $context['user']['smiley_set'] = $user_info['smiley_set']; // Some basic information... if (!isset($context['html_headers'])) { $context['html_headers'] = ''; } $context['menu_separator'] = !empty($settings['use_image_buttons']) ? ' ' : ' | '; $context['session_var'] = $_SESSION['session_var']; $context['session_id'] = $_SESSION['session_value']; $context['forum_name'] = $mbname; $context['forum_name_html_safe'] = commonAPI::htmlspecialchars($context['forum_name']); $context['header_logo_url_html_safe'] = empty($settings['header_logo_url']) ? '' : commonAPI::htmlspecialchars($settings['header_logo_url']); $context['current_action'] = isset($_REQUEST['action']) ? $_REQUEST['action'] : null; $context['current_subaction'] = isset($_REQUEST['sa']) ? $_REQUEST['sa'] : null; if (isset($modSettings['load_average'])) { $context['load_average'] = $modSettings['load_average']; } // Set some permission related settings. $context['show_login_bar'] = $user_info['is_guest'] && !empty($modSettings['enableVBStyleLogin']); // This determines the server... not used in many places, except for login fixing. $context['server'] = array('is_iis' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false, 'is_apache' => isset($_SERVER['SERVER_SOFTWARE']) && (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false), 'is_lighttpd' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false, 'is_nginx' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false, 'is_cgi' => isset($_SERVER['SERVER_SOFTWARE']) && strpos(php_sapi_name(), 'cgi') !== false, 'is_windows' => strpos(PHP_OS, 'WIN') === 0, 'iso_case_folding' => ord(strtolower(chr(138))) === 154, 'complex_preg_chars' => 1); // A bug in some versions of IIS under CGI (older ones) makes cookie setting not work with Location: headers. $context['server']['needs_login_fix'] = $context['server']['is_cgi'] && $context['server']['is_iis']; // Detect the browser. This is separated out because it's also used in attachment downloads detectBrowser(); // Set the top level linktree up. /* array_unshift($context['linktree'], array( 'url' => URL::home(), 'name' => $context['forum_name_html_safe'] )); */ // This allows sticking some HTML on the page output - useful for controls. if (!isset($txt)) { $txt = array(); } $simpleActions = array('findmember', 'helpadmin', 'printpage', 'quotefast'); if (isset($_REQUEST['xml'])) { loadLanguage('index+Modifications'); loadTemplate('Xml'); $context['template_layers'] = array(); } elseif (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], $simpleActions)) { loadLanguage('index+Modifications'); $context['template_layers'] = array(); } else { loadLanguage('index+Modifications'); // Custom templates to load, or just default? $is_admin = isset($_REQUEST['action']) && $_REQUEST['action'] === 'admin'; $templates = array('index'); // Load each template... foreach ($templates as $template) { if (!$is_admin) { loadTemplate($template); } else { loadAdminTemplate($template); } } $context['template_layers'] = array('html', 'body'); } if (isset($db_show_debug) && !empty($db_show_debug)) { loadLanguage('Debug'); } if (file_exists($settings['theme_dir'] . '/theme_support.php')) { @(require_once $settings['theme_dir'] . '/theme_support.php'); } else { @(require_once $settings['default_theme_dir'] . '/theme_support.php'); } // Guests may still need a name. if ($context['user']['is_guest'] && empty($context['user']['name'])) { $context['user']['name'] = $txt['guest_title']; } // Any theme-related strings that need to be loaded? if (!empty($settings['require_theme_strings'])) { loadLanguage('ThemeStrings', '', false); } // We allow theme variants, because we're cool. $context['theme_variant'] = ''; $context['theme_variant_url'] = ''; if (empty($settings['theme_variants'])) { $settings['theme_variants'] = array('default'); } // Overriding - for previews and that ilk. if (!empty($_REQUEST['variant'])) { $_SESSION['id_variant'] = $_REQUEST['variant']; } // User selection? if (empty($settings['disable_user_variant']) || allowedTo('admin_forum')) { $context['theme_variant'] = !empty($_SESSION['id_variant']) ? $_SESSION['id_variant'] : (!empty($options['theme_variant']) ? $options['theme_variant'] : ''); } // If not a user variant, select the default. if ($context['theme_variant'] == '' || !in_array($context['theme_variant'], $settings['theme_variants'])) { $context['theme_variant'] = !empty($settings['default_variant']) && in_array($settings['default_variant'], $settings['theme_variants']) ? $settings['default_variant'] : $settings['theme_variants'][0]; } if (!in_array($context['theme_variant'], $settings['theme_variants'])) { $context['theme_variant'] = 'default'; } // Do this to keep things easier in the templates. $context['theme_variant'] = '_' . $context['theme_variant']; $context['theme_variant_url'] = $context['theme_variant'] . '/'; /* if(!empty($context['theme_variant']) && $context['theme_variant'] != '_default') { if(!empty($settings['base_theme_dir'])) $settings['template_dirs'][] = $settings['base_theme_dir'] . '/variants/' . $context['theme_variant']; else $settings['template_dirs'][] = $settings['default_theme_dir'] . '/variants/' . $context['theme_variant']; } */ // Allow overriding the board wide time/number formats. if (empty($user_settings['time_format']) && !empty($txt['time_format'])) { $user_info['time_format'] = $txt['time_format']; } $txt['number_format'] = empty($txt['number_format']) ? empty($modSettings['number_format']) ? '' : $modSettings['number_format'] : $txt['number_format']; if (isset($settings['use_default_images']) && $settings['use_default_images'] == 'always') { $settings['theme_url'] = $settings['default_theme_url']; $settings['images_url'] = $settings['default_images_url']; $settings['theme_dir'] = $settings['default_theme_dir']; } // Make a special URL for the language. $settings['lang_images_url'] = $settings['images_url'] . '/' . (!empty($txt['image_lang']) ? $txt['image_lang'] : $user_info['language']); // Set the character set from the template. $context['character_set'] = 'UTF-8'; $context['utf8'] = true; $context['right_to_left'] = !empty($txt['lang_rtl']); $context['tabindex'] = 1; // Compatibility. if (!isset($settings['theme_version'])) { $modSettings['memberCount'] = $modSettings['totalMembers']; } // This allows us to change the way things look for the admin. $context['admin_features'] = isset($modSettings['admin_features']) ? explode(',', $modSettings['admin_features']) : array('cd,cp,k,w,rg,ml,pm'); // If we think we have mail to send, let's offer up some possibilities... robots get pain (Now with scheduled task support!) if (!empty($modSettings['mail_next_send']) && $modSettings['mail_next_send'] < time() && empty($modSettings['mail_queue_use_cron']) || empty($modSettings['next_task_time']) || $modSettings['next_task_time'] < time()) { if ($context['browser']['possibly_robot']) { //!!! Maybe move this somewhere better?! require_once $sourcedir . '/ScheduledTasks.php'; // What to do, what to do?! if (empty($modSettings['next_task_time']) || $modSettings['next_task_time'] < time()) { AutoTask(); } else { ReduceMailQueue(); } } else { $type = empty($modSettings['next_task_time']) || $modSettings['next_task_time'] < time() ? 'task' : 'mailq'; $ts = $type == 'mailq' ? $modSettings['mail_next_send'] : $modSettings['next_task_time']; $context['html_headers'] .= ' <script type="text/javascript"> function smfAutoTask() { var tempImage = new Image(); tempImage.src = "' . $scripturl . '?scheduled=' . $type . ';ts=' . $ts . '"; } window.setTimeout("smfAutoTask();", 1); </script>'; } } // Any files to include at this point? if (!empty($modSettings['integrate_theme_include'])) { $theme_includes = explode(',', $modSettings['integrate_theme_include']); foreach ($theme_includes as $include) { $include = strtr(trim($include), array('$boarddir' => $boarddir, '$sourcedir' => $sourcedir, '$themedir' => $settings['theme_dir'])); if (file_exists($include)) { require_once $include; } } } $settings['primary_css'] = $settings['theme_url'] . MOBILE_SUBDIR . '/css/' . CSS_PRIMARY_BASE . $context['theme_variant']; $context['theme_scripts'] = array(); $context['inline_footer_script'] = ''; $context['news_item_count'] = 0; $context['hot_topic_message'] = sprintf($txt['hot_topics'], $modSettings['hotTopicPosts']); $context['very_hot_topic_message'] = sprintf($txt['very_hot_topics'], $modSettings['hotTopicVeryPosts']); $context['old_topic_message'] = sprintf($txt['old_topic_message'], $modSettings['oldTopicDays']); // Call load theme integration functions. HookAPI::callHook('integrate_load_theme'); // We are ready to go. $context['theme_loaded'] = true; }
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 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 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 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 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 editIgnoreList($memID) { global $txt, $scripturl, $modSettings; global $context, $user_profile, $memberContext, $smcFunc; EoS_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'profile/edit_ignore'); // For making changes! $ignoreArray = explode(',', $user_profile[$memID]['pm_ignore_list']); foreach ($ignoreArray as $k => $dummy) { if ($dummy == '') { unset($ignoreArray[$k]); } } // Removing a member from the ignore list? if (isset($_GET['remove'])) { checkSession('get'); // Heh, I'm lazy, do it the easy way... foreach ($ignoreArray as $key => $id_remove) { if ($id_remove == (int) $_GET['remove']) { unset($ignoreArray[$key]); } } // Make the changes. $user_profile[$memID]['pm_ignore_list'] = implode(',', $ignoreArray); updateMemberData($memID, array('pm_ignore_list' => $user_profile[$memID]['pm_ignore_list'])); // Redirect off the page because we don't like all this ugly query stuff to stick in the history. redirectexit('action=profile;area=lists;sa=ignore;u=' . $memID); } elseif (isset($_POST['new_ignore'])) { // Prepare the string for extraction... $_POST['new_ignore'] = strtr(commonAPI::htmlspecialchars($_POST['new_ignore'], ENT_QUOTES), array('"' => '"')); preg_match_all('~"([^"]+)"~', $_POST['new_ignore'], $matches); $new_entries = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_POST['new_ignore'])))); foreach ($new_entries as $k => $dummy) { $new_entries[$k] = strtr(trim($new_entries[$k]), array('\'' => ''')); if (strlen($new_entries[$k]) == 0 || in_array($new_entries[$k], array($user_profile[$memID]['member_name'], $user_profile[$memID]['real_name']))) { unset($new_entries[$k]); } } if (!empty($new_entries)) { // Now find out the id_member for the members in question. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE member_name IN ({array_string:new_entries}) OR real_name IN ({array_string:new_entries}) LIMIT {int:count_new_entries}', array('new_entries' => $new_entries, 'count_new_entries' => count($new_entries))); // Add the new member to the buddies array. while ($row = mysql_fetch_assoc($request)) { $ignoreArray[] = (int) $row['id_member']; } mysql_free_result($request); // Now update the current users buddy list. $user_profile[$memID]['pm_ignore_list'] = implode(',', $ignoreArray); updateMemberData($memID, array('pm_ignore_list' => $user_profile[$memID]['pm_ignore_list'])); } // Back to the list of pityful people! redirectexit('action=profile;area=lists;sa=ignore;u=' . $memID); } // Initialise the list of members we're ignoring. $ignored = array(); if (!empty($ignoreArray)) { $result = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE id_member IN ({array_int:ignore_list}) ORDER BY real_name LIMIT {int:ignore_list_count}', array('ignore_list' => $ignoreArray, 'ignore_list_count' => substr_count($user_profile[$memID]['pm_ignore_list'], ',') + 1)); while ($row = mysql_fetch_assoc($result)) { $ignored[] = $row['id_member']; } mysql_free_result($result); } $context['ignore_count'] = count($ignored); // Load all the members up. loadMemberData($ignored, false, 'profile'); // Setup the context for each buddy. $context['ignore_list'] = array(); foreach ($ignored as $ignore_member) { loadMemberContext($ignore_member); $context['ignore_list'][$ignore_member] = $memberContext[$ignore_member]; } }
function htmlspecialchars__recursive($var, $level = 0) { if (!is_array($var)) { return commonAPI::htmlspecialchars($var, ENT_QUOTES); } // Add the htmlspecialchars to every element. foreach ($var as $k => $v) { $var[$k] = $level > 25 ? null : htmlspecialchars__recursive($v, $level + 1); } return $var; }
function prepareSearchContext($reset = false) { global $txt, $modSettings, $scripturl, $user_info, $sourcedir; global $memberContext, $context, $options, $messages_request; global $boards_can, $participants, $output; // Remember which message this is. (ie. reply #83) static $counter = null; if ($counter == null || $reset) { $counter = $_REQUEST['start'] + 1; } // If the query returned false, bail. if ($messages_request == false) { return false; } // Start from the beginning... if ($reset) { return @mysql_data_seek($messages_request, 0); } // Attempt to get the next message. $message = mysql_fetch_assoc($messages_request); if (!$message) { return false; } // Can't have an empty subject can we? $message['subject'] = $message['subject'] != '' ? $message['subject'] : $txt['no_subject']; $message['first_subject'] = $message['first_subject'] != '' ? $message['first_subject'] : $txt['no_subject']; $message['last_subject'] = $message['last_subject'] != '' ? $message['last_subject'] : $txt['no_subject']; // If it couldn't load, or the user was a guest.... someday may be done with a guest table. if (!loadMemberContext($message['id_member'])) { // Notice this information isn't used anywhere else.... *cough guest table cough*. $memberContext[$message['id_member']]['name'] = $message['poster_name']; $memberContext[$message['id_member']]['id'] = 0; $memberContext[$message['id_member']]['group'] = $txt['guest_title']; $memberContext[$message['id_member']]['link'] = $message['poster_name']; $memberContext[$message['id_member']]['email'] = $message['poster_email']; } $memberContext[$message['id_member']]['ip'] = $message['poster_ip']; // Do the censor thang... censorText($message['body']); censorText($message['subject']); censorText($message['first_subject']); censorText($message['last_subject']); // Shorten this message if necessary. if ($context['compact']) { // Set the number of characters before and after the searched keyword. $charLimit = 50; $message['body'] = strtr($message['body'], array("\n" => ' ', '<br />' => "\n")); $message['body'] = parse_bbc($message['body'], $message['smileys_enabled'], $message['id_msg']); $message['body'] = strip_tags(strtr($message['body'], array('</div>' => '<br />', '</li>' => '<br />')), '<br>'); if (commonAPI::strlen($message['body']) > $charLimit) { if (empty($context['key_words'])) { $message['body'] = commonAPI::substr($message['body'], 0, $charLimit) . '<strong>...</strong>'; } else { $matchString = ''; $force_partial_word = false; foreach ($context['key_words'] as $keyword) { $keyword = preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~e', 'commonAPI::entity_fix(\'\\1\')', strtr($keyword, array('\\\'' => '\'', '&' => '&'))); if (preg_match('~[\'\\.,/@%&;:(){}\\[\\]_\\-+\\\\]$~', $keyword) != 0 || preg_match('~^[\'\\.,/@%&;:(){}\\[\\]_\\-+\\\\]~', $keyword) != 0) { $force_partial_word = true; } $matchString .= strtr(preg_quote($keyword, '/'), array('\\*' => '.+?')) . '|'; } $matchString = substr($matchString, 0, -1); $message['body'] = un_htmlspecialchars(strtr($message['body'], array(' ' => ' ', '<br />' => "\n", '[' => '[', ']' => ']', ':' => ':', '@' => '@'))); if (empty($modSettings['search_method']) || $force_partial_word) { preg_match_all('/([^\\s\\W]{' . $charLimit . '}[\\s\\W]|[\\s\\W].{0,' . $charLimit . '}?|^)(' . $matchString . ')(.{0,' . $charLimit . '}[\\s\\W]|[^\\s\\W]{' . $charLimit . '})/isu', $message['body'], $matches); } else { preg_match_all('/([^\\s\\W]{' . $charLimit . '}[\\s\\W]|[\\s\\W].{0,' . $charLimit . '}?[\\s\\W]|^)(' . $matchString . ')([\\s\\W].{0,' . $charLimit . '}[\\s\\W]|[\\s\\W][^\\s\\W]{' . $charLimit . '})/isu', $message['body'], $matches); } $message['body'] = ''; foreach ($matches[0] as $index => $match) { $match = strtr(htmlspecialchars($match, ENT_QUOTES), array("\n" => ' ')); $message['body'] .= '<strong>......</strong> ' . $match . ' <strong>......</strong>'; } } // Re-fix the international characters. $message['body'] = preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~e', 'commonAPI::entity_fix(\'\\1\')', $message['body']); } } else { // Run BBC interpreter on the message. $message['body'] = parse_bbc($message['body'], $message['smileys_enabled'], $message['id_msg']); } // Make sure we don't end up with a practically empty message body. $message['body'] = preg_replace('~^(?: )+$~', '', $message['body']); // Do we have quote tag enabled? $quote_enabled = empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC'])); $href = URL::topic($message['id_topic'], $message['first_subject'], 0); $mhref = URL::user($message['first_member_id'], $message['first_member_name']); $lhref = URL::topic($message['id_topic'], $message['last_subject'], 0, $message['num_replies'] == 0 ? true : false, $message['num_replies'] == 0 ? '' : '.msg' . $message['last_msg'], $message['num_replies'] == 0 ? '' : '#msg' . $message['last_msg']); $lmhref = URL::user($message['last_member_id'], $message['last_member_name']); $bhref = URL::board($message['id_board'], $message['board_name'], 0, true); $output = array_merge($context['topics'][$message['id_msg']], array('id' => $message['id_topic'], 'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($message['is_sticky']), 'is_locked' => !empty($message['locked']), 'is_poll' => $modSettings['pollMode'] == '1' && $message['id_poll'] > 0, 'is_hot' => $message['num_replies'] >= $modSettings['hotTopicPosts'], 'is_very_hot' => $message['num_replies'] >= $modSettings['hotTopicVeryPosts'], 'posted_in' => !empty($participants[$message['id_topic']]), 'views' => $message['num_views'], 'replies' => $message['num_replies'], 'can_reply' => in_array($message['id_board'], $boards_can['post_reply_any']) || in_array(0, $boards_can['post_reply_any']), 'can_quote' => (in_array($message['id_board'], $boards_can['post_reply_any']) || in_array(0, $boards_can['post_reply_any'])) && $quote_enabled, 'can_mark_notify' => in_array($message['id_board'], $boards_can['mark_any_notify']) || in_array(0, $boards_can['mark_any_notify']) && !$context['user']['is_guest'], 'first_post' => array('id' => $message['first_msg'], 'time' => timeformat($message['first_poster_time']), 'timestamp' => forum_time(true, $message['first_poster_time']), 'subject' => $message['first_subject'], 'href' => $href, 'link' => '<a href="' . $href . '">' . $message['first_subject'] . '</a>', 'icon' => $message['first_icon'], 'icon_url' => getPostIcon($message['first_icon']), 'member' => array('id' => $message['first_member_id'], 'name' => $message['first_member_name'], 'href' => !empty($message['first_member_id']) ? $mhref : '', 'link' => !empty($message['first_member_id']) ? '<a href="' . $mhref . '" title="' . $txt['profile_of'] . ' ' . $message['first_member_name'] . '">' . $message['first_member_name'] . '</a>' : $message['first_member_name'])), 'last_post' => array('id' => $message['last_msg'], 'time' => timeformat($message['last_poster_time']), 'timestamp' => forum_time(true, $message['last_poster_time']), 'subject' => $message['last_subject'], 'href' => $lhref, 'link' => '<a href="' . $lhref . '">' . $message['last_subject'] . '</a>', 'icon' => $message['last_icon'], 'icon_url' => getPostIcon($message['last_icon']), 'member' => array('id' => $message['last_member_id'], 'name' => $message['last_member_name'], 'href' => !empty($message['last_member_id']) ? $lmhref : '', 'link' => !empty($message['last_member_id']) ? '<a href="' . $lmhref . '" title="' . $txt['profile_of'] . ' ' . $message['last_member_name'] . '">' . $message['last_member_name'] . '</a>' : $message['last_member_name'])), 'board' => array('id' => $message['id_board'], 'name' => $message['board_name'], 'href' => $bhref, 'link' => '<a href="' . $bhref . '">' . $message['board_name'] . '</a>'), 'category' => array('id' => $message['id_cat'], 'name' => $message['cat_name'], 'href' => $scripturl . '#c' . $message['id_cat'], 'link' => '<a href="' . $scripturl . '#c' . $message['id_cat'] . '">' . $message['cat_name'] . '</a>'))); determineTopicClass($output); if ($output['posted_in']) { $output['class'] = 'my_' . $output['class']; } $body_highlighted = $message['body']; $subject_highlighted = $message['subject']; if (!empty($options['display_quick_mod'])) { $started = $output['first_post']['member']['id'] == $user_info['id']; $output['quick_mod'] = array('lock' => in_array(0, $boards_can['lock_any']) || in_array($output['board']['id'], $boards_can['lock_any']) || $started && (in_array(0, $boards_can['lock_own']) || in_array($output['board']['id'], $boards_can['lock_own'])), 'sticky' => (in_array(0, $boards_can['make_sticky']) || in_array($output['board']['id'], $boards_can['make_sticky'])) && !empty($modSettings['enableStickyTopics']), 'move' => in_array(0, $boards_can['move_any']) || in_array($output['board']['id'], $boards_can['move_any']) || $started && (in_array(0, $boards_can['move_own']) || in_array($output['board']['id'], $boards_can['move_own'])), 'remove' => in_array(0, $boards_can['remove_any']) || in_array($output['board']['id'], $boards_can['remove_any']) || $started && (in_array(0, $boards_can['remove_own']) || in_array($output['board']['id'], $boards_can['remove_own']))); $context['can_lock'] |= $output['quick_mod']['lock']; $context['can_sticky'] |= $output['quick_mod']['sticky']; $context['can_move'] |= $output['quick_mod']['move']; $context['can_remove'] |= $output['quick_mod']['remove']; $context['can_merge'] |= in_array($output['board']['id'], $boards_can['merge_any']); // If we've found a message we can move, and we don't already have it, load the destinations. if ($options['display_quick_mod'] && !isset($context['move_to_boards']) && $context['can_move']) { require_once $sourcedir . '/lib/Subs-MessageIndex.php'; $boardListOptions = array('use_permissions' => true, 'not_redirection' => true, 'selected_board' => empty($_SESSION['move_to_topic']) ? null : $_SESSION['move_to_topic']); $context['move_to_boards'] = getBoardList($boardListOptions); } } foreach ($context['key_words'] as $query) { // Fix the international characters in the keyword too. $query = strtr(commonAPI::htmlspecialchars($query), array('\\\'' => '\'')); $body_highlighted = preg_replace('/((<[^>]*)|' . preg_quote(strtr($query, array('\'' => ''')), '/') . ')/ieu', "'\$2' == '\$1' ? stripslashes('\$1') : '<strong class=\"highlight\">\$1</strong>'", $body_highlighted); $subject_highlighted = preg_replace('/(' . preg_quote($query, '/') . ')/iu', '<strong class="highlight">$1</strong>', $subject_highlighted); } $mhref = URL::topic($message['id_topic'], $message['subject'], 0, false, '.msg' . $message['id_msg'], '#msg' . $message['id_msg']); $output['matches'][] = array('id' => $message['id_msg'], 'attachment' => loadAttachmentContext($message['id_msg']), 'alternate' => $counter % 2, 'member' => &$memberContext[$message['id_member']], 'icon' => $message['icon'], 'icon_url' => getPostIcon($message['icon']), 'subject' => $message['subject'], 'subject_highlighted' => $subject_highlighted, 'time' => timeformat($message['poster_time']), 'timestamp' => forum_time(true, $message['poster_time']), 'counter' => $counter, 'modified' => array('time' => timeformat($message['modified_time']), 'timestamp' => forum_time(true, $message['modified_time']), 'name' => $message['modified_name']), 'body' => $body_highlighted, 'body_highlighted' => $body_highlighted, 'start' => 'msg' . $message['id_msg'], 'href' => $mhref, 'link' => '<a href="' . $mhref . '">' . $message['subject'] . '</a>'); $counter++; return $output; }
function MergeExecute($topics = array()) { global $user_info, $txt, $context, $scripturl, $sourcedir; global $smcFunc, $language, $modSettings; // Check the session. checkSession('request'); // Handle URLs from MergeIndex. if (!empty($_GET['from']) && !empty($_GET['to'])) { $topics = array((int) $_GET['from'], (int) $_GET['to']); } // If we came from a form, the topic IDs came by post. if (!empty($_POST['topics']) && is_array($_POST['topics'])) { $topics = $_POST['topics']; } // There's nothing to merge with just one topic... if (empty($topics) || !is_array($topics) || count($topics) == 1) { fatal_lang_error('merge_need_more_topics'); } // Make sure every topic is numeric, or some nasty things could be done with the DB. foreach ($topics as $id => $topic) { $topics[$id] = (int) $topic; } // Joy of all joys, make sure they're not pi**ing about with unapproved topics they can't see :P if ($modSettings['postmod_active']) { $can_approve_boards = boardsAllowedTo('approve_posts'); } // Get info about the topics and polls that will be merged. $request = smf_db_query(' SELECT t.id_topic, t.id_board, t.id_poll, t.num_views, t.is_sticky, t.approved, t.num_replies, t.unapproved_posts, m1.subject, m1.poster_time AS time_started, IFNULL(mem1.id_member, 0) AS id_member_started, IFNULL(mem1.real_name, m1.poster_name) AS name_started, m2.poster_time AS time_updated, IFNULL(mem2.id_member, 0) AS id_member_updated, IFNULL(mem2.real_name, m2.poster_name) AS name_updated FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg) INNER JOIN {db_prefix}messages AS m2 ON (m2.id_msg = t.id_last_msg) LEFT JOIN {db_prefix}members AS mem1 ON (mem1.id_member = m1.id_member) LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = m2.id_member) WHERE t.id_topic IN ({array_int:topic_list}) ORDER BY t.id_first_msg LIMIT ' . count($topics), array('topic_list' => $topics)); if (mysql_num_rows($request) < 2) { fatal_lang_error('no_topic_id'); } $num_views = 0; $is_sticky = 0; $boardTotals = array(); $boards = array(); $polls = array(); while ($row = mysql_fetch_assoc($request)) { // Make a note for the board counts... if (!isset($boardTotals[$row['id_board']])) { $boardTotals[$row['id_board']] = array('posts' => 0, 'topics' => 0, 'unapproved_posts' => 0, 'unapproved_topics' => 0); } // We can't see unapproved topics here? if ($modSettings['postmod_active'] && !$row['approved'] && $can_approve_boards != array(0) && in_array($row['id_board'], $can_approve_boards)) { continue; } elseif (!$row['approved']) { $boardTotals[$row['id_board']]['unapproved_topics']++; } else { $boardTotals[$row['id_board']]['topics']++; } $boardTotals[$row['id_board']]['unapproved_posts'] += $row['unapproved_posts']; $boardTotals[$row['id_board']]['posts'] += $row['num_replies'] + ($row['approved'] ? 1 : 0); $topic_data[$row['id_topic']] = array('id' => $row['id_topic'], 'board' => $row['id_board'], 'poll' => $row['id_poll'], 'num_views' => $row['num_views'], 'subject' => $row['subject'], 'started' => array('time' => timeformat($row['time_started']), 'timestamp' => forum_time(true, $row['time_started']), 'href' => empty($row['id_member_started']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member_started'], 'link' => empty($row['id_member_started']) ? $row['name_started'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_started'] . '">' . $row['name_started'] . '</a>'), 'updated' => array('time' => timeformat($row['time_updated']), 'timestamp' => forum_time(true, $row['time_updated']), 'href' => empty($row['id_member_updated']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member_updated'], 'link' => empty($row['id_member_updated']) ? $row['name_updated'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_updated'] . '">' . $row['name_updated'] . '</a>')); $num_views += $row['num_views']; $boards[] = $row['id_board']; // If there's no poll, id_poll == 0... if ($row['id_poll'] > 0) { $polls[] = $row['id_poll']; } // Store the id_topic with the lowest id_first_msg. if (empty($firstTopic)) { $firstTopic = $row['id_topic']; } $is_sticky = max($is_sticky, $row['is_sticky']); } mysql_free_result($request); // If we didn't get any topics then they've been messing with unapproved stuff. if (empty($topic_data)) { fatal_lang_error('no_topic_id'); } $boards = array_values(array_unique($boards)); // The parameters of MergeExecute were set, so this must've been an internal call. if (!empty($topics)) { isAllowedTo('merge_any', $boards); loadTemplate('SplitTopics'); } // Get the boards a user is allowed to merge in. $merge_boards = boardsAllowedTo('merge_any'); if (empty($merge_boards)) { fatal_lang_error('cannot_merge_any', 'user'); } // Make sure they can see all boards.... $request = smf_db_query(' SELECT b.id_board FROM {db_prefix}boards AS b WHERE b.id_board IN ({array_int:boards}) AND {query_see_board}' . (!in_array(0, $merge_boards) ? ' AND b.id_board IN ({array_int:merge_boards})' : '') . ' LIMIT ' . count($boards), array('boards' => $boards, 'merge_boards' => $merge_boards)); // If the number of boards that's in the output isn't exactly the same as we've put in there, you're in trouble. if (mysql_num_rows($request) != count($boards)) { fatal_lang_error('no_board'); } mysql_free_result($request); if (empty($_REQUEST['sa']) || $_REQUEST['sa'] == 'options') { if (count($polls) > 1) { $request = smf_db_query(' SELECT t.id_topic, t.id_poll, m.subject, p.question FROM {db_prefix}polls AS p INNER JOIN {db_prefix}topics AS t ON (t.id_poll = p.id_poll) INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) WHERE p.id_poll IN ({array_int:polls}) LIMIT ' . count($polls), array('polls' => $polls)); while ($row = mysql_fetch_assoc($request)) { $context['polls'][] = array('id' => $row['id_poll'], 'topic' => array('id' => $row['id_topic'], 'subject' => $row['subject']), 'question' => $row['question'], 'selected' => $row['id_topic'] == $firstTopic); } mysql_free_result($request); } if (count($boards) > 1) { $request = smf_db_query(' SELECT id_board, name FROM {db_prefix}boards WHERE id_board IN ({array_int:boards}) ORDER BY name LIMIT ' . count($boards), array('boards' => $boards)); while ($row = mysql_fetch_assoc($request)) { $context['boards'][] = array('id' => $row['id_board'], 'name' => $row['name'], 'selected' => $row['id_board'] == $topic_data[$firstTopic]['board']); } mysql_free_result($request); } $context['topics'] = $topic_data; foreach ($topic_data as $id => $topic) { $context['topics'][$id]['selected'] = $topic['id'] == $firstTopic; } $context['page_title'] = $txt['merge']; $context['sub_template'] = 'merge_extra_options'; return; } // Determine target board. $target_board = count($boards) > 1 ? (int) $_REQUEST['board'] : $boards[0]; if (!in_array($target_board, $boards)) { fatal_lang_error('no_board'); } // Determine which poll will survive and which polls won't. $target_poll = count($polls) > 1 ? (int) $_POST['poll'] : (count($polls) == 1 ? $polls[0] : 0); if ($target_poll > 0 && !in_array($target_poll, $polls)) { fatal_lang_error('no_access', false); } $deleted_polls = empty($target_poll) ? $polls : array_diff($polls, array($target_poll)); // Determine the subject of the newly merged topic - was a custom subject specified? if (empty($_POST['subject']) && isset($_POST['custom_subject']) && $_POST['custom_subject'] != '') { $target_subject = strtr(commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['custom_subject'])), array("\r" => '', "\n" => '', "\t" => '')); // Keep checking the length. if (commonAPI::strlen($target_subject) > 100) { $target_subject = commonAPI::substr($target_subject, 0, 100); } // Nothing left - odd but pick the first topics subject. if ($target_subject == '') { $target_subject = $topic_data[$firstTopic]['subject']; } } elseif (!empty($topic_data[(int) $_POST['subject']]['subject'])) { $target_subject = $topic_data[(int) $_POST['subject']]['subject']; } else { $target_subject = $topic_data[$firstTopic]['subject']; } // Get the first and last message and the number of messages.... $request = smf_db_query(' SELECT approved, MIN(id_msg) AS first_msg, MAX(id_msg) AS last_msg, COUNT(*) AS message_count FROM {db_prefix}messages WHERE id_topic IN ({array_int:topics}) GROUP BY approved ORDER BY approved DESC', array('topics' => $topics)); $topic_approved = 1; while ($row = mysql_fetch_assoc($request)) { // If this is approved, or is fully unapproved. if ($row['approved'] || !isset($first_msg)) { $first_msg = $row['first_msg']; $last_msg = $row['last_msg']; if ($row['approved']) { $num_replies = $row['message_count'] - 1; $num_unapproved = 0; } else { $topic_approved = 0; $num_replies = 0; $num_unapproved = $row['message_count']; } } else { // If this has a lower first_msg then the first post is not approved and hence the number of replies was wrong! if ($first_msg > $row['first_msg']) { $first_msg = $row['first_msg']; $num_replies++; $topic_approved = 0; } $num_unapproved = $row['message_count']; } } mysql_free_result($request); // Ensure we have a board stat for the target board. if (!isset($boardTotals[$target_board])) { $boardTotals[$target_board] = array('posts' => 0, 'topics' => 0, 'unapproved_posts' => 0, 'unapproved_topics' => 0); } // Fix the topic count stuff depending on what the new one counts as. if ($topic_approved) { $boardTotals[$target_board]['topics']--; } else { $boardTotals[$target_board]['unapproved_topics']--; } $boardTotals[$target_board]['unapproved_posts'] -= $num_unapproved; $boardTotals[$target_board]['posts'] -= $topic_approved ? $num_replies + 1 : $num_replies; // Get the member ID of the first and last message. $request = smf_db_query(' SELECT id_member FROM {db_prefix}messages WHERE id_msg IN ({int:first_msg}, {int:last_msg}) ORDER BY id_msg LIMIT 2', array('first_msg' => $first_msg, 'last_msg' => $last_msg)); list($member_started) = mysql_fetch_row($request); list($member_updated) = mysql_fetch_row($request); // First and last message are the same, so only row was returned. if ($member_updated === NULL) { $member_updated = $member_started; } mysql_free_result($request); // Assign the first topic ID to be the merged topic. $id_topic = min($topics); // Delete the remaining topics. $deleted_topics = array_diff($topics, array($id_topic)); smf_db_query(' DELETE FROM {db_prefix}topics WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); smf_db_query(' DELETE FROM {db_prefix}log_search_subjects WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); // Asssign the properties of the newly merged topic. smf_db_query(' UPDATE {db_prefix}topics SET id_board = {int:id_board}, id_member_started = {int:id_member_started}, id_member_updated = {int:id_member_updated}, id_first_msg = {int:id_first_msg}, id_last_msg = {int:id_last_msg}, id_poll = {int:id_poll}, num_replies = {int:num_replies}, unapproved_posts = {int:unapproved_posts}, num_views = {int:num_views}, is_sticky = {int:is_sticky}, approved = {int:approved} WHERE id_topic = {int:id_topic}', array('id_board' => $target_board, 'is_sticky' => $is_sticky, 'approved' => $topic_approved, 'id_topic' => $id_topic, 'id_member_started' => $member_started, 'id_member_updated' => $member_updated, 'id_first_msg' => $first_msg, 'id_last_msg' => $last_msg, 'id_poll' => $target_poll, 'num_replies' => $num_replies, 'unapproved_posts' => $num_unapproved, 'num_views' => $num_views)); // Grab the response prefix (like 'Re: ') in the default forum 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); } // Change the topic IDs of all messages that will be merged. Also adjust subjects if 'enforce subject' was checked. smf_db_query(' UPDATE {db_prefix}messages SET id_topic = {int:id_topic}, id_board = {int:target_board}' . (empty($_POST['enforce_subject']) ? '' : ', subject = {string:subject}') . ' WHERE id_topic IN ({array_int:topic_list})', array('topic_list' => $topics, 'id_topic' => $id_topic, 'target_board' => $target_board, 'subject' => $context['response_prefix'] . $target_subject)); // Any reported posts should reflect the new board. smf_db_query(' UPDATE {db_prefix}log_reported SET id_topic = {int:id_topic}, id_board = {int:target_board} WHERE id_topic IN ({array_int:topics_list})', array('topics_list' => $topics, 'id_topic' => $id_topic, 'target_board' => $target_board)); // Change the subject of the first message... smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:target_subject} WHERE id_msg = {int:first_msg}', array('first_msg' => $first_msg, 'target_subject' => $target_subject)); // Adjust all calendar events to point to the new topic. smf_db_query(' UPDATE {db_prefix}calendar SET id_topic = {int:id_topic}, id_board = {int:target_board} WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics, 'id_topic' => $id_topic, 'target_board' => $target_board)); // Merge log topic entries. $request = smf_db_query(' SELECT id_member, MIN(id_msg) AS new_id_msg FROM {db_prefix}log_topics WHERE id_topic IN ({array_int:topics}) GROUP BY id_member', array('topics' => $topics)); if (mysql_num_rows($request) > 0) { $replaceEntries = array(); while ($row = mysql_fetch_assoc($request)) { $replaceEntries[] = array($row['id_member'], $id_topic, $row['new_id_msg']); } smf_db_insert('replace', '{db_prefix}log_topics', array('id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int'), $replaceEntries, array('id_member', 'id_topic')); unset($replaceEntries); // Get rid of the old log entries. smf_db_query(' DELETE FROM {db_prefix}log_topics WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); } mysql_free_result($request); // Merge topic notifications. $notifications = isset($_POST['notifications']) && is_array($_POST['notifications']) ? array_intersect($topics, $_POST['notifications']) : array(); if (!empty($notifications)) { $request = smf_db_query(' SELECT id_member, MAX(sent) AS sent FROM {db_prefix}log_notify WHERE id_topic IN ({array_int:topics_list}) GROUP BY id_member', array('topics_list' => $notifications)); if (mysql_num_rows($request) > 0) { $replaceEntries = array(); while ($row = mysql_fetch_assoc($request)) { $replaceEntries[] = array($row['id_member'], $id_topic, 0, $row['sent']); } smf_db_insert('replace', '{db_prefix}log_notify', array('id_member' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'sent' => 'int'), $replaceEntries, array('id_member', 'id_topic', 'id_board')); unset($replaceEntries); smf_db_query(' DELETE FROM {db_prefix}log_topics WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); } mysql_free_result($request); } // Get rid of the redundant polls. if (!empty($deleted_polls)) { smf_db_query(' DELETE FROM {db_prefix}polls WHERE id_poll IN ({array_int:deleted_polls})', array('deleted_polls' => $deleted_polls)); smf_db_query(' DELETE FROM {db_prefix}poll_choices WHERE id_poll IN ({array_int:deleted_polls})', array('deleted_polls' => $deleted_polls)); smf_db_query(' DELETE FROM {db_prefix}log_polls WHERE id_poll IN ({array_int:deleted_polls})', array('deleted_polls' => $deleted_polls)); } // Cycle through each board... foreach ($boardTotals as $id_board => $stats) { smf_db_query(' UPDATE {db_prefix}boards SET num_topics = CASE WHEN {int:topics} > num_topics THEN 0 ELSE num_topics - {int:topics} END, unapproved_topics = CASE WHEN {int:unapproved_topics} > unapproved_topics THEN 0 ELSE unapproved_topics - {int:unapproved_topics} END, num_posts = CASE WHEN {int:posts} > num_posts THEN 0 ELSE num_posts - {int:posts} END, unapproved_posts = CASE WHEN {int:unapproved_posts} > unapproved_posts THEN 0 ELSE unapproved_posts - {int:unapproved_posts} END WHERE id_board = {int:id_board}', array('id_board' => $id_board, 'topics' => $stats['topics'], 'unapproved_topics' => $stats['unapproved_topics'], 'posts' => $stats['posts'], 'unapproved_posts' => $stats['unapproved_posts'])); } // Determine the board the final topic resides in $request = smf_db_query(' SELECT id_board FROM {db_prefix}topics WHERE id_topic = {int:id_topic} LIMIT 1', array('id_topic' => $id_topic)); list($id_board) = mysql_fetch_row($request); mysql_free_result($request); require_once $sourcedir . '/lib/Subs-Post.php'; // Update all the statistics. updateStats('topic'); updateStats('subject', $id_topic, $target_subject); updateLastMessages($boards); logAction('merge', array('topic' => $id_topic, 'board' => $id_board)); // Notify people that these topics have been merged? sendNotifications($id_topic, 'merge'); // Send them to the all done page. redirectexit('action=mergetopics;sa=done;to=' . $id_topic . ';targetboard=' . $target_board); }
function ManageRules() { global $txt, $context, $user_info, $scripturl, $smcFunc; // The link tree - gotta have this :o $context['linktree'][] = array('url' => $scripturl . '?action=pm;sa=manrules', 'name' => $txt['pm_manage_rules']); $_ctx = new PMContext(); $context['page_title'] = $txt['pm_manage_rules']; EoS_Smarty::loadTemplate('pm/base'); // Load them... load them!! LoadRules(); // Likely to need all the groups! $request = smf_db_query(' SELECT mg.id_group, mg.group_name, IFNULL(gm.id_member, 0) AS can_moderate, mg.hidden FROM {db_prefix}membergroups AS mg LEFT JOIN {db_prefix}group_moderators AS gm ON (gm.id_group = mg.id_group AND gm.id_member = {int:current_member}) WHERE mg.min_posts = {int:min_posts} AND mg.id_group != {int:moderator_group} AND mg.hidden = {int:not_hidden} ORDER BY mg.group_name', array('current_member' => $user_info['id'], 'min_posts' => -1, 'moderator_group' => 3, 'not_hidden' => 0)); $context['groups'] = array(); while ($row = mysql_fetch_assoc($request)) { // Hide hidden groups! if ($row['hidden'] && !$row['can_moderate'] && !allowedTo('manage_membergroups')) { continue; } $context['groups'][$row['id_group']] = $row['group_name']; } mysql_free_result($request); // Applying all rules? if (isset($_GET['apply'])) { checkSession('get'); ApplyRules(true); redirectexit('action=pm;sa=manrules'); } // Editing a specific one? if (isset($_GET['add'])) { $context['rid'] = isset($_GET['rid']) && isset($context['rules'][$_GET['rid']]) ? (int) $_GET['rid'] : 0; EoS_Smarty::getConfigInstance()->registerHookTemplate('pm_content_area', 'pm/add_rule'); // Current rule information... if ($context['rid']) { $context['rule'] = $context['rules'][$context['rid']]; $members = array(); // Need to get member names! foreach ($context['rule']['criteria'] as $k => $criteria) { if ($criteria['t'] == 'mid' && !empty($criteria['v'])) { $members[(int) $criteria['v']] = $k; } } if (!empty($members)) { $request = smf_db_query(' SELECT id_member, member_name FROM {db_prefix}members WHERE id_member IN ({array_int:member_list})', array('member_list' => array_keys($members))); while ($row = mysql_fetch_assoc($request)) { $context['rule']['criteria'][$members[$row['id_member']]]['v'] = $row['member_name']; } mysql_free_result($request); } } else { $context['rule'] = array('id' => '', 'name' => '', 'criteria' => array(), 'actions' => array(), 'logic' => 'and'); } $context['rule']['criteria'][] = array('t' => '', 'v' => ''); $context['rule']['actions'][] = array('t' => '', 'v' => ''); } elseif (isset($_GET['save'])) { checkSession('post'); $context['rid'] = isset($_GET['rid']) && isset($context['rules'][$_GET['rid']]) ? (int) $_GET['rid'] : 0; // Name is easy! $ruleName = commonAPI::htmlspecialchars(trim($_POST['rule_name'])); if (empty($ruleName)) { fatal_lang_error('pm_rule_no_name', false); } // Sanity check... if (empty($_POST['ruletype']) || empty($_POST['acttype'])) { fatal_lang_error('pm_rule_no_criteria', false); } // Let's do the criteria first - it's also hardest! $criteria = array(); foreach ($_POST['ruletype'] as $ind => $type) { // Check everything is here... if ($type == 'gid' && (!isset($_POST['ruledefgroup'][$ind]) || !isset($context['groups'][$_POST['ruledefgroup'][$ind]]))) { continue; } elseif ($type != 'bud' && !isset($_POST['ruledef'][$ind])) { continue; } // Members need to be found. if ($type == 'mid') { $name = trim($_POST['ruledef'][$ind]); $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE real_name = {string:member_name} OR member_name = {string:member_name}', array('member_name' => $name)); if (mysql_num_rows($request) == 0) { continue; } list($memID) = mysql_fetch_row($request); mysql_free_result($request); $criteria[] = array('t' => 'mid', 'v' => $memID); } elseif ($type == 'bud') { $criteria[] = array('t' => 'bud', 'v' => 1); } elseif ($type == 'gid') { $criteria[] = array('t' => 'gid', 'v' => (int) $_POST['ruledefgroup'][$ind]); } elseif (in_array($type, array('sub', 'msg')) && trim($_POST['ruledef'][$ind]) != '') { $criteria[] = array('t' => $type, 'v' => commonAPI::htmlspecialchars(trim($_POST['ruledef'][$ind]))); } } // Also do the actions! $actions = array(); $doDelete = 0; $isOr = $_POST['rule_logic'] == 'or' ? 1 : 0; foreach ($_POST['acttype'] as $ind => $type) { // Picking a valid label? if ($type == 'lab' && (!isset($_POST['labdef'][$ind]) || !isset($context['labels'][$_POST['labdef'][$ind] - 1]))) { continue; } // Record what we're doing. if ($type == 'del') { $doDelete = 1; } elseif ($type == 'lab') { $actions[] = array('t' => 'lab', 'v' => (int) $_POST['labdef'][$ind] - 1); } } if (empty($criteria) || empty($actions) && !$doDelete) { fatal_lang_error('pm_rule_no_criteria', false); } // What are we storing? $criteria = serialize($criteria); $actions = serialize($actions); // Create the rule? if (empty($context['rid'])) { smf_db_insert('', '{db_prefix}pm_rules', array('id_member' => 'int', 'rule_name' => 'string', 'criteria' => 'string', 'actions' => 'string', 'delete_pm' => 'int', 'is_or' => 'int'), array($user_info['id'], $ruleName, $criteria, $actions, $doDelete, $isOr), array('id_rule')); } else { smf_db_query(' UPDATE {db_prefix}pm_rules SET rule_name = {string:rule_name}, criteria = {string:criteria}, actions = {string:actions}, delete_pm = {int:delete_pm}, is_or = {int:is_or} WHERE id_rule = {int:id_rule} AND id_member = {int:current_member}', array('current_member' => $user_info['id'], 'delete_pm' => $doDelete, 'is_or' => $isOr, 'id_rule' => $context['rid'], 'rule_name' => $ruleName, 'criteria' => $criteria, 'actions' => $actions)); } redirectexit('action=pm;sa=manrules'); } elseif (isset($_POST['delselected']) && !empty($_POST['delrule'])) { checkSession('post'); $toDelete = array(); foreach ($_POST['delrule'] as $k => $v) { $toDelete[] = (int) $k; } if (!empty($toDelete)) { smf_db_query(' DELETE FROM {db_prefix}pm_rules WHERE id_rule IN ({array_int:delete_list}) AND id_member = {int:current_member}', array('current_member' => $user_info['id'], 'delete_list' => $toDelete)); } redirectexit('action=pm;sa=manrules'); } EoS_Smarty::getConfigInstance()->registerHookTemplate('pm_content_area', 'pm/manage_rules'); }
function modifyEvent($event_id, &$eventOptions) { global $smcFunc; // Properly sanitize the title. $eventOptions['title'] = commonAPI::htmlspecialchars($eventOptions['title'], ENT_QUOTES); // Scan the start date for validity and get its components. if (($num_results = sscanf($eventOptions['start_date'], '%d-%d-%d', $year, $month, $day)) !== 3) { trigger_error('modifyEvent(): invalid start date format given', E_USER_ERROR); } // Default span to 0 days. $eventOptions['span'] = isset($eventOptions['span']) ? (int) $eventOptions['span'] : 0; // Set the end date to the start date + span (if the end date wasn't already given). if (!isset($eventOptions['end_date'])) { $eventOptions['end_date'] = strftime('%Y-%m-%d', mktime(0, 0, 0, $month, $day, $year) + $eventOptions['span'] * 86400); } smf_db_query(' UPDATE {db_prefix}calendar SET start_date = {date:start_date}, end_date = {date:end_date}, title = SUBSTRING({string:title}, 1, 60), id_board = {int:id_board}, id_topic = {int:id_topic} WHERE id_event = {int:id_event}', array('start_date' => $eventOptions['start_date'], 'end_date' => $eventOptions['end_date'], 'title' => $eventOptions['title'], 'id_board' => isset($eventOptions['board']) ? (int) $eventOptions['board'] : 0, 'id_topic' => isset($eventOptions['topic']) ? (int) $eventOptions['topic'] : 0, 'id_event' => $event_id)); updateSettings(array('calendar_updated' => time())); }
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 EditCustomProfiles() { global $txt, $scripturl, $context, $settings, $sc, $smcFunc; // Sort out the context! $context['fid'] = isset($_GET['fid']) ? (int) $_GET['fid'] : 0; $context[$context['admin_menu_name']]['current_subsection'] = 'profile'; $context['page_title'] = $context['fid'] ? $txt['custom_edit_title'] : $txt['custom_add_title']; $context['sub_template'] = 'edit_profile_field'; // Load the profile language for section names. loadLanguage('Profile'); if ($context['fid']) { $request = smf_db_query(' SELECT id_field, col_name, field_name, field_desc, field_type, field_length, field_options, show_reg, show_display, show_profile, private, active, default_value, can_search, bbc, mask, enclose, placement FROM {db_prefix}custom_fields WHERE id_field = {int:current_field}', array('current_field' => $context['fid'])); $context['field'] = array(); while ($row = mysql_fetch_assoc($request)) { if ($row['field_type'] == 'textarea') { @(list($rows, $cols) = @explode(',', $row['default_value'])); } else { $rows = 3; $cols = 30; } $context['field'] = array('name' => $row['field_name'], 'desc' => $row['field_desc'], 'colname' => $row['col_name'], 'profile_area' => $row['show_profile'], 'reg' => $row['show_reg'], 'display' => $row['show_display'], 'type' => $row['field_type'], 'max_length' => $row['field_length'], 'rows' => $rows, 'cols' => $cols, 'bbc' => $row['bbc'] ? true : false, 'default_check' => $row['field_type'] == 'check' && $row['default_value'] ? true : false, 'default_select' => $row['field_type'] == 'select' || $row['field_type'] == 'radio' ? $row['default_value'] : '', 'options' => strlen($row['field_options']) > 1 ? explode(',', $row['field_options']) : array('', '', ''), 'active' => $row['active'], 'private' => $row['private'], 'can_search' => $row['can_search'], 'mask' => $row['mask'], 'regex' => substr($row['mask'], 0, 5) == 'regex' ? substr($row['mask'], 5) : '', 'enclose' => $row['enclose'], 'placement' => $row['placement']); } mysql_free_result($request); } // Setup the default values as needed. if (empty($context['field'])) { $context['field'] = array('name' => '', 'colname' => '???', 'desc' => '', 'profile_area' => 'forumprofile', 'reg' => false, 'display' => false, 'type' => 'text', 'max_length' => 255, 'rows' => 4, 'cols' => 30, 'bbc' => false, 'default_check' => false, 'default_select' => '', 'options' => array('', '', ''), 'active' => true, 'private' => false, 'can_search' => false, 'mask' => 'nohtml', 'regex' => '', 'enclose' => '', 'placement' => 0); } // Are we saving? if (isset($_POST['save'])) { checkSession(); // Everyone needs a name - even the (bracket) unknown... if (trim($_POST['field_name']) == '') { fatal_lang_error('custom_option_need_name'); } $_POST['field_name'] = commonAPI::htmlspecialchars($_POST['field_name']); $_POST['field_desc'] = commonAPI::htmlspecialchars($_POST['field_desc']); // Checkboxes... $show_reg = isset($_POST['reg']) ? (int) $_POST['reg'] : 0; $show_display = isset($_POST['display']) ? 1 : 0; $bbc = isset($_POST['bbc']) ? 1 : 0; $show_profile = $_POST['profile_area']; $active = isset($_POST['active']) ? 1 : 0; $private = isset($_POST['private']) ? (int) $_POST['private'] : 0; $can_search = isset($_POST['can_search']) ? 1 : 0; // Some masking stuff... $mask = isset($_POST['mask']) ? $_POST['mask'] : ''; if ($mask == 'regex' && isset($_POST['regex'])) { $mask .= $_POST['regex']; } $field_length = isset($_POST['max_length']) ? (int) $_POST['max_length'] : 255; $enclose = isset($_POST['enclose']) ? $_POST['enclose'] : ''; $placement = isset($_POST['placement']) ? (int) $_POST['placement'] : 0; // Select options? $field_options = ''; $newOptions = array(); $default = isset($_POST['default_check']) && $_POST['field_type'] == 'check' ? 1 : ''; if (!empty($_POST['select_option']) && ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio')) { foreach ($_POST['select_option'] as $k => $v) { // Clean, clean, clean... $v = commonAPI::htmlspecialchars($v); $v = strtr($v, array(',' => '')); // Nada, zip, etc... if (trim($v) == '') { continue; } // Otherwise, save it boy. $field_options .= $v . ','; // This is just for working out what happened with old options... $newOptions[$k] = $v; // Is it default? if (isset($_POST['default_select']) && $_POST['default_select'] == $k) { $default = $v; } } $field_options = substr($field_options, 0, -1); } // Text area has default has dimensions if ($_POST['field_type'] == 'textarea') { $default = (int) $_POST['rows'] . ',' . (int) $_POST['cols']; } // Come up with the unique name? if (empty($context['fid'])) { $colname = commonAPI::substr(strtr($_POST['field_name'], array(' ' => '')), 0, 6); preg_match('~([\\w\\d_-]+)~', $colname, $matches); // If there is nothing to the name, then let's start out own - for foreign languages etc. if (isset($matches[1])) { $colname = $initial_colname = 'cust_' . strtolower($matches[1]); } else { $colname = $initial_colname = 'cust_' . mt_rand(1, 999); } // Make sure this is unique. // !!! This may not be the most efficient way to do this. $unique = false; for ($i = 0; !$unique && $i < 9; $i++) { $request = smf_db_query(' SELECT id_field FROM {db_prefix}custom_fields WHERE col_name = {string:current_column}', array('current_column' => $colname)); if (mysql_num_rows($request) == 0) { $unique = true; } else { $colname = $initial_colname . $i; } mysql_free_result($request); } // Still not a unique colum name? Leave it up to the user, then. if (!$unique) { fatal_lang_error('custom_option_not_unique'); } } else { // Anything going to check or select is pointless keeping - as is anything coming from check! if ($_POST['field_type'] == 'check' && $context['field']['type'] != 'check' || ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') && $context['field']['type'] != 'select' && $context['field']['type'] != 'radio' || $context['field']['type'] == 'check' && $_POST['field_type'] != 'check') { smf_db_query(' DELETE FROM {db_prefix}themes WHERE variable = {string:current_column} AND id_member > {int:no_member}', array('no_member' => 0, 'current_column' => $context['field']['colname'])); } elseif ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') { $optionChanges = array(); $takenKeys = array(); // Work out what's changed! foreach ($context['field']['options'] as $k => $option) { if (trim($option) == '') { continue; } // Still exists? if (in_array($option, $newOptions)) { $takenKeys[] = $k; continue; } } // Finally - have we renamed it - or is it really gone? foreach ($optionChanges as $k => $option) { // Just been renamed? if (!in_array($k, $takenKeys) && !empty($newOptions[$k])) { smf_db_query(' UPDATE {db_prefix}themes SET value = {string:new_value} WHERE variable = {string:current_column} AND value = {string:old_value} AND id_member > {int:no_member}', array('no_member' => 0, 'new_value' => $newOptions[$k], 'current_column' => $context['field']['colname'], 'old_value' => $option)); } } } //!!! Maybe we should adjust based on new text length limits? } // Do the insertion/updates. if ($context['fid']) { smf_db_query(' UPDATE {db_prefix}custom_fields SET field_name = {string:field_name}, field_desc = {string:field_desc}, field_type = {string:field_type}, field_length = {int:field_length}, field_options = {string:field_options}, show_reg = {int:show_reg}, show_display = {int:show_display}, show_profile = {string:show_profile}, private = {int:private}, active = {int:active}, default_value = {string:default_value}, can_search = {int:can_search}, bbc = {int:bbc}, mask = {string:mask}, enclose = {string:enclose}, placement = {int:placement} WHERE id_field = {int:current_field}', array('field_length' => $field_length, 'show_reg' => $show_reg, 'show_display' => $show_display, 'private' => $private, 'active' => $active, 'can_search' => $can_search, 'bbc' => $bbc, 'current_field' => $context['fid'], 'field_name' => $_POST['field_name'], 'field_desc' => $_POST['field_desc'], 'field_type' => $_POST['field_type'], 'field_options' => $field_options, 'show_profile' => $show_profile, 'default_value' => $default, 'mask' => $mask, 'enclose' => $enclose, 'placement' => $placement)); // Just clean up any old selects - these are a pain! if (($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') && !empty($newOptions)) { smf_db_query(' DELETE FROM {db_prefix}themes WHERE variable = {string:current_column} AND value NOT IN ({array_string:new_option_values}) AND id_member > {int:no_member}', array('no_member' => 0, 'new_option_values' => $newOptions, 'current_column' => $context['field']['colname'])); } } else { smf_db_insert('', '{db_prefix}custom_fields', array('col_name' => 'string', 'field_name' => 'string', 'field_desc' => 'string', 'field_type' => 'string', 'field_length' => 'string', 'field_options' => 'string', 'show_reg' => 'int', 'show_display' => 'int', 'show_profile' => 'string', 'private' => 'int', 'active' => 'int', 'default_value' => 'string', 'can_search' => 'int', 'bbc' => 'int', 'mask' => 'string', 'enclose' => 'string', 'placement' => 'int'), array($colname, $_POST['field_name'], $_POST['field_desc'], $_POST['field_type'], $field_length, $field_options, $show_reg, $show_display, $show_profile, $private, $active, $default, $can_search, $bbc, $mask, $enclose, $placement), array('id_field')); } // As there's currently no option to priorize certain fields over others, let's order them alphabetically. smf_db_query(' ALTER TABLE {db_prefix}custom_fields ORDER BY field_name', array('db_error_skip' => true)); } elseif (isset($_POST['delete']) && $context['field']['colname']) { checkSession(); // Delete the user data first. smf_db_query(' DELETE FROM {db_prefix}themes WHERE variable = {string:current_column} AND id_member > {int:no_member}', array('no_member' => 0, 'current_column' => $context['field']['colname'])); // Finally - the field itself is gone! smf_db_query(' DELETE FROM {db_prefix}custom_fields WHERE id_field = {int:current_field}', array('current_field' => $context['fid'])); } // Rebuild display cache etc. if (isset($_POST['delete']) || isset($_POST['save'])) { checkSession(); $request = smf_db_query(' SELECT col_name, field_name, field_type, bbc, enclose, placement FROM {db_prefix}custom_fields WHERE show_display = {int:is_displayed} AND active = {int:active} AND private != {int:not_owner_only} AND private != {int:not_admin_only}', array('is_displayed' => 1, 'active' => 1, 'not_owner_only' => 2, 'not_admin_only' => 3)); $fields = array(); while ($row = mysql_fetch_assoc($request)) { $fields[] = array('colname' => strtr($row['col_name'], array('|' => '', ';' => '')), 'title' => strtr($row['field_name'], array('|' => '', ';' => '')), 'type' => $row['field_type'], 'bbc' => $row['bbc'] ? '1' : '0', 'placement' => !empty($row['placement']) ? $row['placement'] : '0', 'enclose' => !empty($row['enclose']) ? $row['enclose'] : ''); } mysql_free_result($request); updateSettings(array('displayFields' => serialize($fields))); redirectexit('action=admin;area=featuresettings;sa=profile'); } }
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'])); } }
function ViewMemberlist() { global $txt, $scripturl, $context, $modSettings, $sourcedir, $smcFunc, $user_info; // Set the current sub action. $context['sub_action'] = $_REQUEST['sa']; // Are we performing a delete? if (isset($_POST['delete_members']) && !empty($_POST['delete']) && allowedTo('profile_remove_any')) { checkSession(); // Clean the input. foreach ($_POST['delete'] as $key => $value) { $_POST['delete'][$key] = (int) $value; // Don't delete yourself, idiot. if ($value == $user_info['id']) { unset($_POST['delete'][$key]); } } if (!empty($_POST['delete'])) { // Delete all the selected members. require_once $sourcedir . '/lib/Subs-Members.php'; deleteMembers($_POST['delete'], true); } } if ($context['sub_action'] == 'query' && !empty($_REQUEST['params']) && empty($_POST)) { $_POST += @unserialize(base64_decode($_REQUEST['params'])); } // Check input after a member search has been submitted. if ($context['sub_action'] == 'query') { // Retrieving the membergroups and postgroups. $context['membergroups'] = array(array('id' => 0, 'name' => $txt['membergroups_members'], 'can_be_additional' => false)); $context['postgroups'] = array(); $request = smf_db_query(' SELECT id_group, group_name, min_posts FROM {db_prefix}membergroups WHERE id_group != {int:moderator_group} ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name', array('moderator_group' => 3, 'newbie_group' => 4)); while ($row = mysql_fetch_assoc($request)) { if ($row['min_posts'] == -1) { $context['membergroups'][] = array('id' => $row['id_group'], 'name' => $row['group_name'], 'can_be_additional' => true); } else { $context['postgroups'][] = array('id' => $row['id_group'], 'name' => $row['group_name']); } } mysql_free_result($request); // Some data about the form fields and how they are linked to the database. $params = array('mem_id' => array('db_fields' => array('id_member'), 'type' => 'int', 'range' => true), 'age' => array('db_fields' => array('birthdate'), 'type' => 'age', 'range' => true), 'posts' => array('db_fields' => array('posts'), 'type' => 'int', 'range' => true), 'reg_date' => array('db_fields' => array('date_registered'), 'type' => 'date', 'range' => true), 'last_online' => array('db_fields' => array('last_login'), 'type' => 'date', 'range' => true), 'gender' => array('db_fields' => array('gender'), 'type' => 'checkbox', 'values' => array('0', '1', '2')), 'activated' => array('db_fields' => array('CASE WHEN is_activated IN (1, 11) THEN 1 ELSE 0 END'), 'type' => 'checkbox', 'values' => array('0', '1')), 'membername' => array('db_fields' => array('member_name', 'real_name'), 'type' => 'string'), 'email' => array('db_fields' => array('email_address'), 'type' => 'string'), 'location' => array('db_fields' => array('location'), 'type' => 'string'), 'ip' => array('db_fields' => array('member_ip'), 'type' => 'string')); $range_trans = array('--' => '<', '-' => '<=', '=' => '=', '+' => '>=', '++' => '>'); // !!! Validate a little more. // Loop through every field of the form. $query_parts = array(); $where_params = array(); foreach ($params as $param_name => $param_info) { // Not filled in? if (!isset($_POST[$param_name]) || $_POST[$param_name] === '') { continue; } // Make sure numeric values are really numeric. if (in_array($param_info['type'], array('int', 'age'))) { $_POST[$param_name] = (int) $_POST[$param_name]; } elseif ($param_info['type'] == 'date') { // Check if this date format is valid. if (preg_match('/^\\d{4}-\\d{1,2}-\\d{1,2}$/', $_POST[$param_name]) == 0) { continue; } $_POST[$param_name] = strtotime($_POST[$param_name]); } // Those values that are in some kind of range (<, <=, =, >=, >). if (!empty($param_info['range'])) { // Default to '=', just in case... if (empty($range_trans[$_POST['types'][$param_name]])) { $_POST['types'][$param_name] = '='; } // Handle special case 'age'. if ($param_info['type'] == 'age') { // All people that were born between $lowerlimit and $upperlimit are currently the specified age. $datearray = getdate(forum_time()); $upperlimit = sprintf('%04d-%02d-%02d', $datearray['year'] - $_POST[$param_name], $datearray['mon'], $datearray['mday']); $lowerlimit = sprintf('%04d-%02d-%02d', $datearray['year'] - $_POST[$param_name] - 1, $datearray['mon'], $datearray['mday']); if (in_array($_POST['types'][$param_name], array('-', '--', '='))) { $query_parts[] = $param_info['db_fields'][0] . ' > {string:' . $param_name . '_minlimit}'; $where_params[$param_name . '_minlimit'] = $_POST['types'][$param_name] == '--' ? $upperlimit : $lowerlimit; } if (in_array($_POST['types'][$param_name], array('+', '++', '='))) { $query_parts[] = $param_info['db_fields'][0] . ' <= {string:' . $param_name . '_pluslimit}'; $where_params[$param_name . '_pluslimit'] = $_POST['types'][$param_name] == '++' ? $lowerlimit : $upperlimit; // Make sure that members that didn't set their birth year are not queried. $query_parts[] = $param_info['db_fields'][0] . ' > {date:dec_zero_date}'; $where_params['dec_zero_date'] = '0004-12-31'; } } elseif ($param_info['type'] == 'date' && $_POST['types'][$param_name] == '=') { $query_parts[] = $param_info['db_fields'][0] . ' > ' . $_POST[$param_name] . ' AND ' . $param_info['db_fields'][0] . ' < ' . ($_POST[$param_name] + 86400); } else { $query_parts[] = $param_info['db_fields'][0] . ' ' . $range_trans[$_POST['types'][$param_name]] . ' ' . $_POST[$param_name]; } } elseif ($param_info['type'] == 'checkbox') { // Each checkbox or no checkbox at all is checked -> ignore. if (!is_array($_POST[$param_name]) || count($_POST[$param_name]) == 0 || count($_POST[$param_name]) == count($param_info['values'])) { continue; } $query_parts[] = $param_info['db_fields'][0] . ' IN ({array_string:' . $param_name . '_check})'; $where_params[$param_name . '_check'] = $_POST[$param_name]; } else { // Replace the wildcard characters ('*' and '?') into MySQL ones. $parameter = strtolower(strtr(commonAPI::htmlspecialchars($_POST[$param_name], ENT_QUOTES), array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_'))); $query_parts[] = '(' . implode(' LIKE {string:' . $param_name . '_normal} OR ', $param_info['db_fields']) . ' LIKE {string:' . $param_name . '_normal})'; $where_params[$param_name . '_normal'] = '%' . $parameter . '%'; } } // Set up the membergroup query part. $mg_query_parts = array(); // Primary membergroups, but only if at least was was not selected. if (!empty($_POST['membergroups'][1]) && count($context['membergroups']) != count($_POST['membergroups'][1])) { $mg_query_parts[] = 'mem.id_group IN ({array_int:group_check})'; $where_params['group_check'] = $_POST['membergroups'][1]; } // Additional membergroups (these are only relevant if not all primary groups where selected!). if (!empty($_POST['membergroups'][2]) && (empty($_POST['membergroups'][1]) || count($context['membergroups']) != count($_POST['membergroups'][1]))) { foreach ($_POST['membergroups'][2] as $mg) { $mg_query_parts[] = 'FIND_IN_SET({int:add_group_' . $mg . '}, mem.additional_groups) != 0'; $where_params['add_group_' . $mg] = $mg; } } // Combine the one or two membergroup parts into one query part linked with an OR. if (!empty($mg_query_parts)) { $query_parts[] = '(' . implode(' OR ', $mg_query_parts) . ')'; } // Get all selected post count related membergroups. if (!empty($_POST['postgroups']) && count($_POST['postgroups']) != count($context['postgroups'])) { $query_parts[] = 'id_post_group IN ({array_int:post_groups})'; $where_params['post_groups'] = $_POST['postgroups']; } // Construct the where part of the query. $where = empty($query_parts) ? '1' : implode(' AND ', $query_parts); $search_params = base64_encode(serialize($_POST)); } else { $search_params = null; } // Construct the additional URL part with the query info in it. $context['params_url'] = $context['sub_action'] == 'query' ? ';sa=query;params=' . $search_params : ''; // Get the title and sub template ready.. $context['page_title'] = $txt['admin_members']; $listOptions = array('id' => 'member_list', 'items_per_page' => $modSettings['defaultMaxMembers'], 'base_href' => $scripturl . '?action=admin;area=viewmembers' . $context['params_url'], 'default_sort_col' => 'user_name', 'get_items' => array('file' => $sourcedir . '/lib/Subs-Members.php', 'function' => 'list_getMembers', 'params' => array(isset($where) ? $where : '1=1', isset($where_params) ? $where_params : array())), 'get_count' => array('file' => $sourcedir . '/lib/Subs-Members.php', 'function' => 'list_getNumMembers', 'params' => array(isset($where) ? $where : '1=1', isset($where_params) ? $where_params : array())), 'columns' => array('id_member' => array('header' => array('value' => $txt['member_id']), 'data' => array('db' => 'id_member', 'class' => 'windowbg', 'style' => 'text-align: center;'), 'sort' => array('default' => 'id_member', 'reverse' => 'id_member DESC')), 'user_name' => array('header' => array('value' => $txt['username']), 'data' => array('sprintf' => array('format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=profile;u=%1$d">%2$s</a>', 'params' => array('id_member' => false, 'member_name' => false))), 'sort' => array('default' => 'member_name', 'reverse' => 'member_name DESC')), 'display_name' => array('header' => array('value' => $txt['display_name']), 'data' => array('sprintf' => array('format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=profile;u=%1$d">%2$s</a>', 'params' => array('id_member' => false, 'real_name' => false))), 'sort' => array('default' => 'real_name', 'reverse' => 'real_name DESC')), 'email' => array('header' => array('value' => $txt['email_address']), 'data' => array('sprintf' => array('format' => '<a href="mailto:%1$s">%1$s</a>', 'params' => array('email_address' => true)), 'class' => 'windowbg'), 'sort' => array('default' => 'email_address', 'reverse' => 'email_address DESC')), 'ip' => array('header' => array('value' => $txt['ip_address']), 'data' => array('sprintf' => array('format' => '<a href="' . strtr($scripturl, array('%' => '%%')) . '?action=trackip;searchip=%1$s">%1$s</a>', 'params' => array('member_ip' => false))), 'sort' => array('default' => 'INET_ATON(member_ip)', 'reverse' => 'INET_ATON(member_ip) DESC')), 'last_active' => array('header' => array('value' => $txt['viewmembers_online']), 'data' => array('function' => create_function('$rowData', ' global $txt; // Calculate number of days since last online. if (empty($rowData[\'last_login\'])) $difference = $txt[\'never\']; else { $num_days_difference = jeffsdatediff($rowData[\'last_login\']); // Today. if (empty($num_days_difference)) $difference = $txt[\'viewmembers_today\']; // Yesterday. elseif ($num_days_difference == 1) $difference = sprintf(\'1 %1$s\', $txt[\'viewmembers_day_ago\']); // X days ago. else $difference = sprintf(\'%1$d %2$s\', $num_days_difference, $txt[\'viewmembers_days_ago\']); } // Show it in italics if they\'re not activated... if ($rowData[\'is_activated\'] % 10 != 1) $difference = sprintf(\'<em title="%1$s">%2$s</em>\', $txt[\'not_activated\'], $difference); return $difference; ')), 'sort' => array('default' => 'last_login DESC', 'reverse' => 'last_login')), 'posts' => array('header' => array('value' => $txt['member_postcount']), 'data' => array('db' => 'posts'), 'sort' => array('default' => 'posts', 'reverse' => 'posts DESC')), 'check' => array('header' => array('value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />'), 'data' => array('function' => create_function('$rowData', ' global $user_info; return \'<input type="checkbox" name="delete[]" value="\' . $rowData[\'id_member\'] . \'" class="input_check" \' . ($rowData[\'id_member\'] == $user_info[\'id\'] || $rowData[\'id_group\'] == 1 || in_array(1, explode(\',\', $rowData[\'additional_groups\'])) ? \'disabled="disabled"\' : \'\') . \' />\'; '), 'class' => 'windowbg', 'style' => 'text-align: center'))), 'form' => array('href' => $scripturl . '?action=admin;area=viewmembers' . $context['params_url'], 'include_start' => true, 'include_sort' => true), 'additional_rows' => array(array('position' => 'below_table_data', 'value' => '<input type="submit" name="delete_members" value="' . $txt['admin_delete_members'] . '" onclick="return confirm(\'' . $txt['confirm_delete_members'] . '\');" class="button_submit" />', 'style' => 'text-align: right;'))); // Without not enough permissions, don't show 'delete members' checkboxes. if (!allowedTo('profile_remove_any')) { unset($listOptions['cols']['check'], $listOptions['form'], $listOptions['additional_rows']); } require_once $sourcedir . '/lib/Subs-List.php'; createList($listOptions); $context['sub_template'] = 'show_list'; $context['default_list'] = 'member_list'; }
function RequestMembers() { global $user_info, $txt, $smcFunc; checkSession('get'); $_REQUEST['search'] = commonAPI::htmlspecialchars($_REQUEST['search']) . '*'; $_REQUEST['search'] = trim(commonAPI::strtolower($_REQUEST['search'])); $_REQUEST['search'] = strtr($_REQUEST['search'], array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_', '&' => '&')); if (function_exists('iconv')) { header('Content-Type: text/plain; charset=UTF-8'); } $request = smf_db_query(' SELECT real_name FROM {db_prefix}members WHERE real_name LIKE {string:search}' . (isset($_REQUEST['buddies']) ? ' AND id_member IN ({array_int:buddy_list})' : '') . ' AND is_activated IN (1, 11) LIMIT ' . (commonAPI::strlen($_REQUEST['search']) <= 2 ? '100' : '800'), array('buddy_list' => $user_info['buddies'], 'search' => $_REQUEST['search'])); while ($row = mysql_fetch_assoc($request)) { if (function_exists('iconv')) { $utf8 = iconv($txt['lang_character_set'], 'UTF-8', $row['real_name']); if ($utf8) { $row['real_name'] = $utf8; } } $row['real_name'] = strtr($row['real_name'], array('&' => '&', '<' => '<', '>' => '>', '"' => '"')); if (preg_match('~&#\\d+;~', $row['real_name']) != 0) { $fixchar = create_function('$n', ' if ($n < 128) return chr($n); elseif ($n < 2048) return chr(192 | $n >> 6) . chr(128 | $n & 63); elseif ($n < 65536) return chr(224 | $n >> 12) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63); else return chr(240 | $n >> 18) . chr(128 | $n >> 12 & 63) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63);'); $row['real_name'] = preg_replace('~&#(\\d+);~e', '$fixchar(\'$1\')', $row['real_name']); } echo $row['real_name'], "\n"; } mysql_free_result($request); obExit(false); }
function MLSearch() { global $txt, $scripturl, $context, $user_info, $modSettings, $smcFunc; $context['page_title'] = $txt['mlist_search']; $context['can_moderate_forum'] = allowedTo('moderate_forum'); // Can they search custom fields? $request = smf_db_query(' SELECT col_name, field_name, field_desc FROM {db_prefix}custom_fields WHERE active = {int:active} ' . (allowedTo('admin_forum') ? '' : ' AND private < {int:private_level}') . ' AND can_search = {int:can_search} AND (field_type = {string:field_type_text} OR field_type = {string:field_type_textarea})', array('active' => 1, 'can_search' => 1, 'private_level' => 2, 'field_type_text' => 'text', 'field_type_textarea' => 'textarea')); $context['custom_search_fields'] = array(); while ($row = mysql_fetch_assoc($request)) { $context['custom_search_fields'][$row['col_name']] = array('colname' => $row['col_name'], 'name' => $row['field_name'], 'desc' => $row['field_desc']); } mysql_free_result($request); // They're searching.. if (isset($_REQUEST['search']) && isset($_REQUEST['fields'])) { $_POST['search'] = trim(isset($_GET['search']) ? $_GET['search'] : $_POST['search']); $_POST['fields'] = isset($_GET['fields']) ? explode(',', $_GET['fields']) : $_POST['fields']; $context['old_search'] = $_REQUEST['search']; $context['old_search_value'] = urlencode($_REQUEST['search']); // No fields? Use default... if (empty($_POST['fields'])) { $_POST['fields'] = array('name'); } $query_parameters = array('regular_id_group' => 0, 'is_activated' => 1, 'blank_string' => '', 'search' => '%' . strtr(commonAPI::htmlspecialchars($_POST['search'], ENT_QUOTES), array('_' => '\\_', '%' => '\\%', '*' => '%')) . '%'); // Search for a name? if (in_array('name', $_POST['fields'])) { $fields = array('member_name', 'real_name'); } else { $fields = array(); } // Search for groups. if (in_array('group', $_POST['fields'])) { $fields += array(9 => 'IFNULL(group_name, {string:blank_string})'); } // Search for an email address? if (in_array('email', $_POST['fields'])) { $fields += array(2 => allowedTo('moderate_forum') ? 'email_address' : '(hide_email = 0 AND email_address'); $condition = allowedTo('moderate_forum') ? '' : ')'; } else { $condition = ''; } $customJoin = array(); $customCount = 10; // Any custom fields to search for - these being tricky? foreach ($_POST['fields'] as $field) { $curField = substr($field, 5); if (substr($field, 0, 5) == 'cust_' && isset($context['custom_search_fields'][$curField])) { $customJoin[] = 'LEFT JOIN {db_prefix}themes AS t' . $curField . ' ON (t' . $curField . '.variable = {string:t' . $curField . '} AND t' . $curField . '.id_theme = 1 AND t' . $curField . '.id_member = mem.id_member)'; $query_parameters['t' . $curField] = $curField; $fields += array($customCount++ => 'IFNULL(t' . $curField . '.value, {string:blank_string})'); } } $query = $_POST['search'] == '' ? '= {string:blank_string}' : 'LIKE {string:search}'; $request = smf_db_query(' SELECT COUNT(*) FROM {db_prefix}members AS mem LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_id_group} THEN mem.id_post_group ELSE mem.id_group END)' . (empty($customJoin) ? '' : implode(' ', $customJoin)) . ' WHERE (' . implode(' ' . $query . ' OR ', $fields) . ' ' . $query . $condition . ') AND mem.is_activated = {int:is_activated}', $query_parameters); list($numResults) = mysql_fetch_row($request); mysql_free_result($request); $context['page_index'] = constructPageIndex($scripturl . '?action=mlist;sa=search;search=' . $_POST['search'] . ';fields=' . implode(',', $_POST['fields']), $_REQUEST['start'], $numResults, $modSettings['defaultMaxMembers']); // Find the members from the database. // !!!SLOW This query is slow. $request = smf_db_query(' SELECT mem.id_member FROM {db_prefix}members AS mem LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member) LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_id_group} THEN mem.id_post_group ELSE mem.id_group END)' . (empty($customJoin) ? '' : implode(' ', $customJoin)) . ' WHERE (' . implode(' ' . $query . ' OR ', $fields) . ' ' . $query . $condition . ') AND mem.is_activated = {int:is_activated} LIMIT ' . $_REQUEST['start'] . ', ' . $modSettings['defaultMaxMembers'], $query_parameters); printMemberListRows($request); mysql_free_result($request); } else { // These are all the possible fields. $context['search_fields'] = array('name' => $txt['mlist_search_name'], 'email' => $txt['mlist_search_email'], 'messenger' => $txt['mlist_search_messenger'], 'group' => $txt['mlist_search_group']); foreach ($context['custom_search_fields'] as $field) { $context['search_fields']['cust_' . $field['colname']] = sprintf($txt['mlist_search_by'], $field['name']); } // What do we search for by default? $context['search_defaults'] = array('name', 'email'); //$context['sub_template'] = 'search'; $context['old_search'] = isset($_GET['search']) ? $_GET['search'] : (isset($_POST['search']) ? htmlspecialchars($_POST['search']) : ''); } $context['linktree'][] = array('url' => $scripturl . '?action=mlist;sa=search', 'name' => &$context['page_title']); }
function Register2($verifiedOpenID = false) { global $txt, $modSettings, $context, $sourcedir; // Start collecting together any errors. $reg_errors = array(); // Did we save some open ID fields? if ($verifiedOpenID && !empty($context['openid_save_fields'])) { foreach ($context['openid_save_fields'] as $id => $value) { $_POST[$id] = $value; } } // You can't register if it's disabled. if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 3) { fatal_lang_error('registration_disabled', false); } // Things we don't do for people who have already confirmed their OpenID allegances via register. if (!$verifiedOpenID) { // Well, if you don't agree, you can't register. if (!empty($modSettings['requireAgreement']) && empty($_SESSION['registration_agreed'])) { redirectexit(); } // Make sure they came from *somewhere*, have a session. if (!isset($_SESSION['old_url'])) { redirectexit('action=register'); } // Are they under age, and under age users are banned? if (!empty($modSettings['coppaAge']) && empty($modSettings['coppaType']) && empty($_SESSION['skip_coppa'])) { // !!! This should be put in Errors, imho. loadLanguage('Login'); fatal_lang_error('under_age_registration_prohibited', false, array($modSettings['coppaAge'])); } // Check whether the visual verification code was entered correctly. if (!empty($modSettings['reg_verification'])) { require_once $sourcedir . '/lib/Subs-Editor.php'; $verificationOptions = array('id' => 'register'); $context['visual_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['visual_verification'])) { loadLanguage('Errors'); foreach ($context['visual_verification'] as $error) { $reg_errors[] = $txt['error_' . $error]; } } } } foreach ($_POST as $key => $value) { if (!is_array($_POST[$key])) { $_POST[$key] = htmltrim__recursive(str_replace(array("\n", "\r"), '', $_POST[$key])); } } // Collect all extra registration fields someone might have filled in. $possible_strings = array('location', 'birthdate', 'time_format', 'buddy_list', 'pm_ignore_list', 'smiley_set', 'signature', 'personal_text', 'avatar', 'lngfile', 'secret_question', 'secret_answer'); $possible_ints = array('pm_email_notify', 'notify_types', 'gender', 'id_theme'); $possible_floats = array('time_offset'); $possible_bools = array('notify_announcements', 'notify_regularity', 'notify_send_body', 'hide_email', 'show_online'); if (isset($_POST['secret_answer']) && $_POST['secret_answer'] != '') { $_POST['secret_answer'] = md5($_POST['secret_answer']); } // Needed for isReservedName() and registerMember(). require_once $sourcedir . '/lib/Subs-Members.php'; // Validation... even if we're not a mall. if (isset($_POST['real_name']) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum'))) { $_POST['real_name'] = trim(preg_replace('~[\\s]~u', ' ', $_POST['real_name'])); if (trim($_POST['real_name']) != '' && !isReservedName($_POST['real_name']) && commonAPI::strlen($_POST['real_name']) < 60) { $possible_strings[] = 'real_name'; } } // Handle a string as a birthdate... if (isset($_POST['birthdate']) && $_POST['birthdate'] != '') { $_POST['birthdate'] = strftime('%Y-%m-%d', strtotime($_POST['birthdate'])); } elseif (!empty($_POST['bday1']) && !empty($_POST['bday2'])) { $_POST['birthdate'] = sprintf('%04d-%02d-%02d', empty($_POST['bday3']) ? 0 : (int) $_POST['bday3'], (int) $_POST['bday1'], (int) $_POST['bday2']); } // By default assume email is hidden, only show it if we tell it to. $_POST['hide_email'] = !empty($_POST['allow_email']) ? 0 : 1; // Validate the passed language file. if (isset($_POST['lngfile']) && !empty($modSettings['userLanguage'])) { // Do we have any languages? if (empty($context['languages'])) { getLanguages(); } // Did we find it? if (isset($context['languages'][$_POST['lngfile']])) { $_SESSION['language'] = $_POST['lngfile']; } else { unset($_POST['lngfile']); } } else { unset($_POST['lngfile']); } // Set the options needed for registration. $regOptions = array('interface' => 'guest', 'username' => !empty($_POST['user']) ? $_POST['user'] : '', 'email' => !empty($_POST['email']) ? $_POST['email'] : '', 'password' => !empty($_POST['passwrd1']) ? $_POST['passwrd1'] : '', 'password_check' => !empty($_POST['passwrd2']) ? $_POST['passwrd2'] : '', 'openid' => !empty($_POST['openid_identifier']) ? $_POST['openid_identifier'] : '', 'auth_method' => !empty($_POST['authenticate']) ? $_POST['authenticate'] : '', 'check_reserved_name' => true, 'check_password_strength' => true, 'check_email_ban' => true, 'send_welcome_email' => !empty($modSettings['send_welcomeEmail']), 'require' => !empty($modSettings['coppaAge']) && !$verifiedOpenID && empty($_SESSION['skip_coppa']) ? 'coppa' : (empty($modSettings['registration_method']) ? 'nothing' : ($modSettings['registration_method'] == 1 ? 'activation' : 'approval')), 'extra_register_vars' => array(), 'theme_vars' => array()); // Include the additional options that might have been filled in. foreach ($possible_strings as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = commonAPI::htmlspecialchars($_POST[$var], ENT_QUOTES); } } foreach ($possible_ints as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = (int) $_POST[$var]; } } foreach ($possible_floats as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = (double) $_POST[$var]; } } foreach ($possible_bools as $var) { if (isset($_POST[$var])) { $regOptions['extra_register_vars'][$var] = empty($_POST[$var]) ? 0 : 1; } } // Registration options are always default options... if (isset($_POST['default_options'])) { $_POST['options'] = isset($_POST['options']) ? $_POST['options'] + $_POST['default_options'] : $_POST['default_options']; } $regOptions['theme_vars'] = isset($_POST['options']) && is_array($_POST['options']) ? $_POST['options'] : array(); // Make sure they are clean, dammit! $regOptions['theme_vars'] = htmlspecialchars__recursive($regOptions['theme_vars']); // If Quick Reply hasn't been set then set it to be shown but collapsed. if (!isset($regOptions['theme_vars']['display_quick_reply'])) { $regOptions['theme_vars']['display_quick_reply'] = 1; } // Check whether we have fields that simply MUST be displayed? $request = smf_db_query(' SELECT col_name, field_name, field_type, field_length, mask, show_reg FROM {db_prefix}custom_fields WHERE active = {int:is_active}', array('is_active' => 1)); $custom_field_errors = array(); while ($row = mysql_fetch_assoc($request)) { // Don't allow overriding of the theme variables. if (isset($regOptions['theme_vars'][$row['col_name']])) { unset($regOptions['theme_vars'][$row['col_name']]); } // Not actually showing it then? if (!$row['show_reg']) { continue; } // Prepare the value! $value = isset($_POST['customfield'][$row['col_name']]) ? trim($_POST['customfield'][$row['col_name']]) : ''; // We only care for text fields as the others are valid to be empty. if (!in_array($row['field_type'], array('check', 'select', 'radio'))) { // Is it too long? if ($row['field_length'] && $row['field_length'] < commonAPI::strlen($value)) { $custom_field_errors[] = array('custom_field_too_long', array($row['field_name'], $row['field_length'])); } // Any masks to apply? if ($row['field_type'] == 'text' && !empty($row['mask']) && $row['mask'] != 'none') { //!!! We never error on this - just ignore it at the moment... if ($row['mask'] == 'email' && (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $value) === 0 || strlen($value) > 255)) { $custom_field_errors[] = array('custom_field_invalid_email', array($row['field_name'])); } elseif ($row['mask'] == 'number' && preg_match('~[^\\d]~', $value)) { $custom_field_errors[] = array('custom_field_not_number', array($row['field_name'])); } elseif (substr($row['mask'], 0, 5) == 'regex' && preg_match(substr($row['mask'], 5), $value) === 0) { $custom_field_errors[] = array('custom_field_inproper_format', array($row['field_name'])); } } } // Is this required but not there? if (trim($value) == '' && $row['show_reg'] > 1) { $custom_field_errors[] = array('custom_field_empty', array($row['field_name'])); } } mysql_free_result($request); // Process any errors. if (!empty($custom_field_errors)) { loadLanguage('Errors'); foreach ($custom_field_errors as $error) { $reg_errors[] = vsprintf($txt['error_' . $error[0]], $error[1]); } } // Lets check for other errors before trying to register the member. if (!empty($reg_errors)) { $_REQUEST['step'] = 2; return Register($reg_errors); } // If they're wanting to use OpenID we need to validate them first. if (empty($_SESSION['openid']['verified']) && !empty($_POST['authenticate']) && $_POST['authenticate'] == 'openid') { // What do we need to save? $save_variables = array(); foreach ($_POST as $k => $v) { if (!in_array($k, array('sc', 'sesc', $context['session_var'], 'passwrd1', 'passwrd2', 'regSubmit'))) { $save_variables[$k] = $v; } } require_once $sourcedir . '/lib/Subs-OpenID.php'; smf_openID_validate($_POST['openid_identifier'], false, $save_variables); } elseif ($verifiedOpenID || !empty($_POST['openid_identifier']) && $_POST['authenticate'] == 'openid') { $regOptions['username'] = !empty($_POST['user']) && trim($_POST['user']) != '' ? $_POST['user'] : $_SESSION['openid']['nickname']; $regOptions['email'] = !empty($_POST['email']) && trim($_POST['email']) != '' ? $_POST['email'] : $_SESSION['openid']['email']; $regOptions['auth_method'] = 'openid'; $regOptions['openid'] = !empty($_POST['openid_identifier']) ? $_POST['openid_identifier'] : $_SESSION['openid']['openid_uri']; } $memberID = registerMember($regOptions, true); // What there actually an error of some kind dear boy? if (is_array($memberID)) { $reg_errors = array_merge($reg_errors, $memberID); $_REQUEST['step'] = 2; return Register($reg_errors); } // Do our spam protection now. spamProtection('register'); HookAPI::callHook('register_process'); // We'll do custom fields after as then we get to use the helper function! if (!empty($_POST['customfield'])) { require_once $sourcedir . '/Profile.php'; require_once $sourcedir . '/Profile-Modify.php'; makeCustomFieldChanges($memberID, 'register'); } // If COPPA has been selected then things get complicated, setup the template. if (!empty($modSettings['coppaAge']) && empty($_SESSION['skip_coppa'])) { redirectexit('action=coppa;member=' . $memberID); } elseif (!empty($modSettings['registration_method'])) { EoS_Smarty::loadTemplate('register/base'); EoS_Smarty::getConfigInstance()->registerHookTemplate('register_content_area', 'register/done'); $context += array('page_title' => $txt['register'], 'title' => $txt['registration_successful'], 'description' => $modSettings['registration_method'] == 2 ? $txt['approval_after_registration'] : $txt['activate_after_registration']); } else { HookAPI::callHook('integrate_activate', array($row['member_name'])); setLoginCookie(60 * $modSettings['cookieTime'], $memberID, sha1(sha1(strtolower($regOptions['username']) . $regOptions['password']) . $regOptions['register_vars']['password_salt'])); redirectexit('action=login2;sa=check;member=' . $memberID, $context['server']['needs_login_fix']); } }
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 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 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'); } }
function registerMember(&$regOptions, $return_errors = false) { global $scripturl, $txt, $modSettings, $context, $sourcedir; global $user_info, $options, $settings, $smcFunc; loadLanguage('Login'); // We'll need some external functions. require_once $sourcedir . '/lib/Subs-Auth.php'; require_once $sourcedir . '/lib/Subs-Post.php'; // Put any errors in here. $reg_errors = array(); // Registration from the admin center, let them sweat a little more. if ($regOptions['interface'] == 'admin') { is_not_guest(); isAllowedTo('moderate_forum'); } elseif ($regOptions['interface'] == 'guest') { // You cannot register twice... if (empty($user_info['is_guest'])) { redirectexit(); } // Make sure they didn't just register with this session. if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) { fatal_lang_error('register_only_once', false); } } // What method of authorization are we going to use? if (empty($regOptions['auth_method']) || !in_array($regOptions['auth_method'], array('password', 'openid'))) { if (!empty($regOptions['openid'])) { $regOptions['auth_method'] = 'openid'; } else { $regOptions['auth_method'] = 'password'; } } // No name?! How can you register with no name? if (empty($regOptions['username'])) { $reg_errors[] = array('lang', 'need_username'); } // Spaces and other odd characters are evil... $regOptions['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : " ") . ']+~u', ' ', $regOptions['username']); // Don't use too long a name. if (commonAPI::strlen($regOptions['username']) > 25) { $reg_errors[] = array('lang', 'error_long_name'); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $regOptions['username'])) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false) { $reg_errors[] = array('lang', 'error_invalid_characters_username'); } if (commonAPI::strtolower($regOptions['username']) === commonAPI::strtolower($txt['guest_title'])) { $reg_errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title'])); } // !!! Separate the sprintf? if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $regOptions['email']) === 0 || strlen($regOptions['email']) > 255) { $reg_errors[] = array('done', sprintf($txt['valid_email_needed'], commonAPI::htmlspecialchars($regOptions['username']))); } if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false)) { if ($regOptions['password'] == 'chocolate cake') { $reg_errors[] = array('done', 'Sorry, I don\'t take bribes... you\'ll need to come up with a different name.'); } $reg_errors[] = array('done', '(' . htmlspecialchars($regOptions['username']) . ') ' . $txt['name_in_use']); } // Generate a validation code if it's supposed to be emailed. $validation_code = ''; if ($regOptions['require'] == 'activation') { $validation_code = generateValidationCode(); } // If you haven't put in a password generate one. if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '' && $regOptions['auth_method'] == 'password') { mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; } elseif ($regOptions['password'] != $regOptions['password_check'] && $regOptions['auth_method'] == 'password') { $reg_errors[] = array('lang', 'passwords_dont_match'); } // That's kind of easy to guess... if ($regOptions['password'] == '') { if ($regOptions['auth_method'] == 'password') { $reg_errors[] = array('lang', 'no_password'); } else { $regOptions['password'] = sha1(mt_rand()); } } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength'])) { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { $reg_errors[] = array('lang', 'profile_error_password_' . $passwordError); } } // If they are using an OpenID that hasn't been verified yet error out. // !!! Change this so they can register without having to attempt a login first if ($regOptions['auth_method'] == 'openid' && (empty($_SESSION['openid']['verified']) || $_SESSION['openid']['openid_uri'] != $regOptions['openid'])) { $reg_errors[] = array('lang', 'openid_not_verified'); } // You may not be allowed to register this email. if (!empty($regOptions['check_email_ban'])) { isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); } // Check if the email address is in use. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE email_address = {string:email_address} OR email_address = {string:username} LIMIT 1', array('email_address' => $regOptions['email'], 'username' => $regOptions['username'])); // !!! Separate the sprintf? if (mysql_num_rows($request) != 0) { $reg_errors[] = array('lang', 'email_in_use', false, array(htmlspecialchars($regOptions['email']))); } mysql_free_result($request); // If we found any errors we need to do something about it right away! foreach ($reg_errors as $key => $error) { /* Note for each error: 0 = 'lang' if it's an index, 'done' if it's clear text. 1 = The text/index. 2 = Whether to log. 3 = sprintf data if necessary. */ if ($error[0] == 'lang') { loadLanguage('Errors'); } $message = $error[0] == 'lang' ? empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3]) : $error[1]; // What to do, what to do, what to do. if ($return_errors) { if (!empty($error[2])) { log_error($message, $error[2]); } $reg_errors[$key] = $message; } else { fatal_error($message, empty($error[2]) ? false : $error[2]); } } // If there's any errors left return them at once! if (!empty($reg_errors)) { return $reg_errors; } $reservedVars = array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url'); // Can't change reserved vars. if (isset($regOptions['theme_vars']) && array_intersect($regOptions['theme_vars'], $reservedVars) != array()) { fatal_lang_error('no_theme'); } // Some of these might be overwritten. (the lower ones that are in the arrays below.) $regOptions['register_vars'] = array('member_name' => $regOptions['username'], 'email_address' => $regOptions['email'], 'passwd' => sha1(strtolower($regOptions['username']) . $regOptions['password']), 'password_salt' => substr(md5(mt_rand()), 0, 4), 'posts' => 0, 'date_registered' => time(), 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $user_info['ip'], 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $_SERVER['BAN_CHECK_IP'], 'validation_code' => $validation_code, 'real_name' => $regOptions['username'], 'personal_text' => $modSettings['default_personal_text'], 'pm_email_notify' => 1, 'id_theme' => 0, 'id_post_group' => 4, 'lngfile' => '', 'buddy_list' => '', 'pm_ignore_list' => '', 'message_labels' => '', 'location' => '', 'time_format' => '', 'signature' => '', 'avatar' => '', 'usertitle' => '', 'secret_question' => '', 'secret_answer' => '', 'additional_groups' => '', 'ignore_boards' => '', 'smiley_set' => '', 'openid_uri' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); // Setup the activation status on this new account so it is correct - firstly is it an under age account? if ($regOptions['require'] == 'coppa') { $regOptions['register_vars']['is_activated'] = 5; // !!! This should be changed. To what should be it be changed?? $regOptions['register_vars']['validation_code'] = ''; } elseif ($regOptions['require'] == 'nothing') { $regOptions['register_vars']['is_activated'] = 1; } elseif ($regOptions['require'] == 'activation') { $regOptions['register_vars']['is_activated'] = 0; } else { $regOptions['register_vars']['is_activated'] = 3; } if (isset($regOptions['memberGroup'])) { // Make sure the id_group will be valid, if this is an administator. $regOptions['register_vars']['id_group'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; // Check if this group is assignable. $unassignableGroups = array(-1, 3); $request = smf_db_query(' SELECT id_group FROM {db_prefix}membergroups WHERE min_posts != {int:min_posts}' . (allowedTo('admin_forum') ? '' : ' OR group_type = {int:is_protected}'), array('min_posts' => -1, 'is_protected' => 1)); while ($row = mysql_fetch_assoc($request)) { $unassignableGroups[] = $row['id_group']; } mysql_free_result($request); if (in_array($regOptions['register_vars']['id_group'], $unassignableGroups)) { $regOptions['register_vars']['id_group'] = 0; } } // Integrate optional member settings to be set. if (!empty($regOptions['extra_register_vars'])) { foreach ($regOptions['extra_register_vars'] as $var => $value) { $regOptions['register_vars'][$var] = $value; } } // Integrate optional user theme options to be set. $theme_vars = array(); if (!empty($regOptions['theme_vars'])) { foreach ($regOptions['theme_vars'] as $var => $value) { $theme_vars[$var] = $value; } } // Call an optional function to validate the users' input. HookAPI::callHook('integrate_register', array(&$regOptions, &$theme_vars)); // Right, now let's prepare for insertion. $knownInts = array('date_registered', 'posts', 'id_group', 'last_login', 'instant_messages', 'unread_messages', 'new_pm', 'pm_prefs', 'gender', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad', 'notify_announcements', 'notify_send_body', 'notify_regularity', 'notify_types', 'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning'); $knownFloats = array('time_offset'); $column_names = array(); $values = array(); foreach ($regOptions['register_vars'] as $var => $val) { $type = 'string'; if (in_array($var, $knownInts)) { $type = 'int'; } elseif (in_array($var, $knownFloats)) { $type = 'float'; } elseif ($var == 'birthdate') { $type = 'date'; } $column_names[$var] = $type; $values[$var] = $val; } // Register them into the database. smf_db_insert('', '{db_prefix}members', $column_names, $values, array('id_member')); $memberID = smf_db_insert_id('{db_prefix}members', 'id_member'); // Update the number of members and latest member's info - and pass the name, but remove the 's. if ($regOptions['register_vars']['is_activated'] == 1) { updateStats('member', $memberID, $regOptions['register_vars']['real_name']); } else { updateStats('member'); } // Theme variables too? if (!empty($theme_vars)) { $inserts = array(); foreach ($theme_vars as $var => $val) { $inserts[] = array($memberID, $var, $val); } smf_db_insert('insert', '{db_prefix}themes', array('id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), $inserts, array('id_member', 'variable')); } // If it's enabled, increase the registrations for today. trackStats(array('registers' => '+')); // Administrative registrations are a bit different... if ($regOptions['interface'] == 'admin') { if ($regOptions['require'] == 'activation') { $email_message = 'admin_register_activate'; } elseif (!empty($regOptions['send_welcome_email'])) { $email_message = 'admin_register_immediate'; } if (isset($email_message)) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); $emaildata = loadEmailTemplate($email_message, $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // All admins are finished here. return $memberID; } // Can post straight away - welcome them to your fantastic community... if ($regOptions['require'] == 'nothing') { if (!empty($regOptions['send_welcome_email'])) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'immediate', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // Send admin their notification. adminNotify('standard', $memberID, $regOptions['username']); } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); if ($regOptions['require'] == 'activation') { $replacements += array('ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); } else { $replacements += array('COPPALINK' => $scripturl . '?action=coppa;u=' . $memberID); } $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . ($regOptions['require'] == 'activation' ? 'activate' : 'coppa'), $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } else { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'pending', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); // Admin gets informed here... adminNotify('approval', $memberID, $regOptions['username']); } // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) $_SESSION['just_registered'] = 1; return $memberID; }
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 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 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'); } }
function create_control_verification(&$verificationOptions, $do_test = false) { global $txt, $modSettings, $options, $smcFunc; global $context, $settings, $user_info, $sourcedir, $scripturl; // First verification means we need to set up some bits... if (empty($context['controls']['verification'])) { // The template //if(!isset($verificationOptions['skip_template'])) // loadTemplate('GenericControls'); // Some javascript ma'am? if (!empty($verificationOptions['override_visual']) || !empty($modSettings['visual_verification_type']) && !isset($verificationOptions['override_visual'])) { $context['html_headers'] .= ' <script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/captcha.js"></script>'; } $context['use_graphic_library'] = in_array('gd', get_loaded_extensions()); // Skip I, J, L, O, Q, S and Z. $context['standard_captcha_range'] = array_merge(range('A', 'H'), array('K', 'M', 'N', 'P', 'R'), range('T', 'Y')); } // Always have an ID. assert(isset($verificationOptions['id'])); $isNew = !isset($context['controls']['verification'][$verificationOptions['id']]); // Log this into our collection. if ($isNew) { $context['controls']['verification'][$verificationOptions['id']] = array('id' => $verificationOptions['id'], 'show_visual' => !empty($verificationOptions['override_visual']) || !empty($modSettings['visual_verification_type']) && !isset($verificationOptions['override_visual']), 'number_questions' => isset($verificationOptions['override_qs']) ? $verificationOptions['override_qs'] : (!empty($modSettings['qa_verification_number']) ? $modSettings['qa_verification_number'] : 0), 'max_errors' => isset($verificationOptions['max_errors']) ? $verificationOptions['max_errors'] : 3, 'image_href' => $scripturl . '?action=verificationcode;vid=' . $verificationOptions['id'] . ';rand=' . md5(mt_rand()), 'text_value' => '', 'questions' => array()); } $thisVerification =& $context['controls']['verification'][$verificationOptions['id']]; // Add javascript for the object. if ($context['controls']['verification'][$verificationOptions['id']]['show_visual']) { $context['inline_footer_script'] .= ' var verification' . $verificationOptions['id'] . 'Handle = new smfCaptcha("' . $thisVerification['image_href'] . '", "' . $verificationOptions['id'] . '", ' . ($context['use_graphic_library'] ? 1 : 0) . ');'; } // Is there actually going to be anything? if (empty($thisVerification['show_visual']) && empty($thisVerification['number_questions'])) { return false; } elseif (!$isNew && !$do_test) { return true; } // If we want questions do we have a cache of all the IDs? if (!empty($thisVerification['number_questions']) && empty($modSettings['question_id_cache'])) { if (($modSettings['question_id_cache'] = CacheAPI::getCache('verificationQuestionIds', 300)) == null) { $request = smf_db_query(' SELECT id_comment FROM {db_prefix}log_comments WHERE comment_type = {string:ver_test}', array('ver_test' => 'ver_test')); $modSettings['question_id_cache'] = array(); while ($row = mysql_fetch_assoc($request)) { $modSettings['question_id_cache'][] = $row['id_comment']; } mysql_free_result($request); if (!empty($modSettings['cache_enable'])) { CacheAPI::putCache('verificationQuestionIds', $modSettings['question_id_cache'], 300); } } } if (!isset($_SESSION[$verificationOptions['id'] . '_vv'])) { $_SESSION[$verificationOptions['id'] . '_vv'] = array(); } // Do we need to refresh the verification? if (!$do_test && (!empty($_SESSION[$verificationOptions['id'] . '_vv']['did_pass']) || empty($_SESSION[$verificationOptions['id'] . '_vv']['count']) || $_SESSION[$verificationOptions['id'] . '_vv']['count'] > 3) && empty($verificationOptions['dont_refresh'])) { $force_refresh = true; } else { $force_refresh = false; } // This can also force a fresh, although unlikely. if ($thisVerification['show_visual'] && empty($_SESSION[$verificationOptions['id'] . '_vv']['code']) || $thisVerification['number_questions'] && empty($_SESSION[$verificationOptions['id'] . '_vv']['q'])) { $force_refresh = true; } $verification_errors = array(); // Start with any testing. if ($do_test) { // This cannot happen! if (!isset($_SESSION[$verificationOptions['id'] . '_vv']['count'])) { fatal_lang_error('no_access', false); } // ... nor this! if ($thisVerification['number_questions'] && (!isset($_SESSION[$verificationOptions['id'] . '_vv']['q']) || !isset($_REQUEST[$verificationOptions['id'] . '_vv']['q']))) { fatal_lang_error('no_access', false); } if ($thisVerification['show_visual'] && (empty($_REQUEST[$verificationOptions['id'] . '_vv']['code']) || empty($_SESSION[$verificationOptions['id'] . '_vv']['code']) || strtoupper($_REQUEST[$verificationOptions['id'] . '_vv']['code']) !== $_SESSION[$verificationOptions['id'] . '_vv']['code'])) { $verification_errors[] = 'wrong_verification_code'; } if ($thisVerification['number_questions']) { // Get the answers and see if they are all right! $request = smf_db_query(' SELECT id_comment, recipient_name AS answer FROM {db_prefix}log_comments WHERE comment_type = {string:ver_test} AND id_comment IN ({array_int:comment_ids})', array('ver_test' => 'ver_test', 'comment_ids' => $_SESSION[$verificationOptions['id'] . '_vv']['q'])); $incorrectQuestions = array(); while ($row = mysql_fetch_assoc($request)) { if (empty($_REQUEST[$verificationOptions['id'] . '_vv']['q'][$row['id_comment']]) || trim(commonAPI::htmlspecialchars(strtolower($_REQUEST[$verificationOptions['id'] . '_vv']['q'][$row['id_comment']]))) != strtolower($row['answer'])) { $incorrectQuestions[] = $row['id_comment']; } } mysql_free_result($request); if (!empty($incorrectQuestions)) { $verification_errors[] = 'wrong_verification_answer'; } } } // Any errors means we refresh potentially. if (!empty($verification_errors)) { if (empty($_SESSION[$verificationOptions['id'] . '_vv']['errors'])) { $_SESSION[$verificationOptions['id'] . '_vv']['errors'] = 0; } elseif ($_SESSION[$verificationOptions['id'] . '_vv']['errors'] > $thisVerification['max_errors']) { $force_refresh = true; } // Keep a track of these. $_SESSION[$verificationOptions['id'] . '_vv']['errors']++; } // Are we refreshing then? if ($force_refresh) { // Assume nothing went before. $_SESSION[$verificationOptions['id'] . '_vv']['count'] = 0; $_SESSION[$verificationOptions['id'] . '_vv']['errors'] = 0; $_SESSION[$verificationOptions['id'] . '_vv']['did_pass'] = false; $_SESSION[$verificationOptions['id'] . '_vv']['q'] = array(); $_SESSION[$verificationOptions['id'] . '_vv']['code'] = ''; // Generating a new image. if ($thisVerification['show_visual']) { // Are we overriding the range? $character_range = !empty($verificationOptions['override_range']) ? $verificationOptions['override_range'] : $context['standard_captcha_range']; for ($i = 0; $i < 6; $i++) { $_SESSION[$verificationOptions['id'] . '_vv']['code'] .= $character_range[array_rand($character_range)]; } } // Getting some new questions? if ($thisVerification['number_questions']) { // Pick some random IDs $questionIDs = array(); if ($thisVerification['number_questions'] == 1) { $questionIDs[] = $modSettings['question_id_cache'][array_rand($modSettings['question_id_cache'], $thisVerification['number_questions'])]; } else { foreach (array_rand($modSettings['question_id_cache'], $thisVerification['number_questions']) as $index) { $questionIDs[] = $modSettings['question_id_cache'][$index]; } } } } else { // Same questions as before. $questionIDs = !empty($_SESSION[$verificationOptions['id'] . '_vv']['q']) ? $_SESSION[$verificationOptions['id'] . '_vv']['q'] : array(); $thisVerification['text_value'] = !empty($_REQUEST[$verificationOptions['id'] . '_vv']['code']) ? commonAPI::htmlspecialchars($_REQUEST[$verificationOptions['id'] . '_vv']['code']) : ''; } // Have we got some questions to load? if (!empty($questionIDs)) { $request = smf_db_query(' SELECT id_comment, body AS question FROM {db_prefix}log_comments WHERE comment_type = {string:ver_test} AND id_comment IN ({array_int:comment_ids})', array('ver_test' => 'ver_test', 'comment_ids' => $questionIDs)); $_SESSION[$verificationOptions['id'] . '_vv']['q'] = array(); while ($row = mysql_fetch_assoc($request)) { $thisVerification['questions'][] = array('id' => $row['id_comment'], 'q' => parse_bbc($row['question']), 'is_error' => !empty($incorrectQuestions) && in_array($row['id_comment'], $incorrectQuestions), 'a' => isset($_REQUEST[$verificationOptions['id'] . '_vv'], $_REQUEST[$verificationOptions['id'] . '_vv']['q'], $_REQUEST[$verificationOptions['id'] . '_vv']['q'][$row['id_comment']]) ? commonAPI::htmlspecialchars($_REQUEST[$verificationOptions['id'] . '_vv']['q'][$row['id_comment']]) : ''); $_SESSION[$verificationOptions['id'] . '_vv']['q'][] = $row['id_comment']; } mysql_free_result($request); } $_SESSION[$verificationOptions['id'] . '_vv']['count'] = empty($_SESSION[$verificationOptions['id'] . '_vv']['count']) ? 1 : $_SESSION[$verificationOptions['id'] . '_vv']['count'] + 1; // Return errors if we have them. if (!empty($verification_errors)) { return $verification_errors; } elseif ($do_test) { $_SESSION[$verificationOptions['id'] . '_vv']['did_pass'] = true; } // Say that everything went well chaps. return true; }
function EditPermissionProfiles() { global $context, $txt, $smcFunc; // Setup the template, first for fun. $context['page_title'] = $txt['permissions_profile_edit']; $context['sub_template'] = 'edit_profiles'; // If we're creating a new one do it first. if (isset($_POST['create']) && trim($_POST['profile_name']) != '') { checkSession(); $_POST['copy_from'] = (int) $_POST['copy_from']; $_POST['profile_name'] = commonAPI::htmlspecialchars($_POST['profile_name']); // Insert the profile itself. smf_db_insert('', '{db_prefix}permission_profiles', array('profile_name' => 'string'), array($_POST['profile_name']), array('id_profile')); $profile_id = smf_db_insert_id('{db_prefix}permission_profiles', 'id_profile'); // Load the permissions from the one it's being copied from. $request = smf_db_query(' SELECT id_group, permission, add_deny FROM {db_prefix}board_permissions WHERE id_profile = {int:copy_from}', array('copy_from' => $_POST['copy_from'])); $inserts = array(); while ($row = mysql_fetch_assoc($request)) { $inserts[] = array($profile_id, $row['id_group'], $row['permission'], $row['add_deny']); } mysql_free_result($request); if (!empty($inserts)) { smf_db_insert('insert', '{db_prefix}board_permissions', array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string', 'add_deny' => 'int'), $inserts, array('id_profile', 'id_group', 'permission')); } } elseif (isset($_POST['rename'])) { checkSession(); // Just showing the boxes? if (!isset($_POST['rename_profile'])) { $context['show_rename_boxes'] = true; } else { foreach ($_POST['rename_profile'] as $id => $value) { $value = commonAPI::htmlspecialchars($value); if (trim($value) != '' && $id > 4) { smf_db_query(' UPDATE {db_prefix}permission_profiles SET profile_name = {string:profile_name} WHERE id_profile = {int:current_profile}', array('current_profile' => (int) $id, 'profile_name' => $value)); } } } } elseif (isset($_POST['delete']) && !empty($_POST['delete_profile'])) { checkSession('post'); $profiles = array(); foreach ($_POST['delete_profile'] as $profile) { if ($profile > 4) { $profiles[] = (int) $profile; } } // Verify it's not in use... $request = smf_db_query(' SELECT id_board FROM {db_prefix}boards WHERE id_profile IN ({array_int:profile_list}) LIMIT 1', array('profile_list' => $profiles)); if (mysql_num_rows($request) != 0) { fatal_lang_error('no_access', false); } mysql_free_result($request); // Oh well, delete. smf_db_query(' DELETE FROM {db_prefix}permission_profiles WHERE id_profile IN ({array_int:profile_list})', array('profile_list' => $profiles)); } // Clearly, we'll need this! loadPermissionProfiles(); // Work out what ones are in use. $request = smf_db_query(' SELECT id_profile, COUNT(id_board) AS board_count FROM {db_prefix}boards GROUP BY id_profile', array()); while ($row = mysql_fetch_assoc($request)) { if (isset($context['profiles'][$row['id_profile']])) { $context['profiles'][$row['id_profile']]['in_use'] = true; $context['profiles'][$row['id_profile']]['boards'] = $row['board_count']; $context['profiles'][$row['id_profile']]['boards_text'] = $row['board_count'] > 1 ? sprintf($txt['permissions_profile_used_by_many'], $row['board_count']) : $txt['permissions_profile_used_by_' . ($row['board_count'] ? 'one' : 'none')]; } } mysql_free_result($request); // What can we do with these? $context['can_edit_something'] = false; foreach ($context['profiles'] as $id => $profile) { // Can't delete special ones. $context['profiles'][$id]['can_edit'] = isset($txt['permissions_profile_' . $profile['unformatted_name']]) ? false : true; if ($context['profiles'][$id]['can_edit']) { $context['can_edit_something'] = true; } // You can only delete it if you can edit it AND it's not in use. $context['profiles'][$id]['can_delete'] = $context['profiles'][$id]['can_edit'] && empty($profile['in_use']) ? true : false; } }