/** * This is the main method for markasread controller when using APIs. * @uses Xml template generic_xml_buttons sub template */ public function action_index_api() { global $context, $txt, $user_info, $scripturl; loadTemplate('Xml'); Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'generic_xml_buttons'; // Guests can't mark things. if ($user_info['is_guest']) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['not_guests']); return; } if (checkSession('get', '', false)) { // Again, this is a special case, someone will deal with the others later :P if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'all') { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'url' => $scripturl . '?action=markasread;sa=all;' . $context['session_var'] . '=' . $context['session_id']); return; } else { obExit(false); } } $this->_dispatch(); // For the time being this is a special case, but in BoardIndex no, we don't want it if (isset($_REQUEST['sa']) && ($_REQUEST['sa'] == 'all' || $_REQUEST['sa'] == 'board') && !isset($_REQUEST['bi'])) { $context['xml_data'] = array('text' => $txt['topic_alert_none'], 'body' => str_replace('{unread_all_url}', $scripturl . '?action=unread;all' . sprintf($this->_querystring_board_limits, 0) . $this->_querystring_sort_limits, $txt['unread_topics_visit_none'])); } else { obExit(false); } }
/** * Handling function for generating reports. * - Requires the admin_forum permission. * - Loads the Reports template and language files. * - Decides which type of report to generate, if this isn't passed * through the querystring it will set the report_type sub-template to * force the user to choose which type. * - When generating a report chooses which sub_template to use. * - Depends on the cal_enabled setting, and many of the other cal_ settings. * - Will call the relevant report generation function. * - If generating report will call finishTables before returning. * * Accessed through ?action=admin;area=reports. * * @see Action_Controller::action_index() */ public function action_index() { global $txt, $context, $scripturl; // Only admins, only EVER admins! isAllowedTo('admin_forum'); // Let's get our things running... loadTemplate('Reports'); loadLanguage('Reports'); $context['page_title'] = $txt['generate_reports']; // These are the types of reports which exist - and the functions to generate them. $context['report_types'] = array('boards' => 'action_boards', 'board_perms' => 'action_board_perms', 'member_groups' => 'action_member_groups', 'group_perms' => 'action_group_perms', 'staff' => 'action_staff'); call_integration_hook('integrate_report_types'); // Load up all the tabs... $context[$context['admin_menu_name']]['tab_data'] = array('title' => $txt['generate_reports'], 'help' => '', 'description' => $txt['generate_reports_desc']); $is_first = 0; foreach ($context['report_types'] as $k => $temp) { $context['report_types'][$k] = array('id' => $k, 'title' => isset($txt['gr_type_' . $k]) ? $txt['gr_type_' . $k] : $k, 'description' => isset($txt['gr_type_desc_' . $k]) ? $txt['gr_type_desc_' . $k] : null, 'function' => $temp, 'is_first' => $is_first++ == 0); } // If they haven't choosen a report type which is valid, send them off to the report type chooser! if (empty($_REQUEST['rt']) || !isset($context['report_types'][$_REQUEST['rt']])) { $context['sub_template'] = 'report_type'; return; } $context['report_type'] = $_REQUEST['rt']; $context['sub_template'] = 'generate_report'; // What are valid templates for showing reports? $reportTemplates = array('main' => array('layers' => null), 'print' => array('layers' => array('print'))); // Specific template? Use that instead of main! if (isset($_REQUEST['st']) && isset($reportTemplates[$_REQUEST['st']])) { $context['sub_template'] = $_REQUEST['st']; // Are we disabling the other layers - print friendly for example? if ($reportTemplates[$_REQUEST['st']]['layers'] !== null) { $template_layers = Template_Layers::getInstance(); $template_layers->removeAll(); foreach ($reportTemplates[$_REQUEST['st']]['layers'] as $layer) { $template_layers->add($layer); } } } // Make the page title more descriptive. $context['page_title'] .= ' - ' . (isset($txt['gr_type_' . $context['report_type']]) ? $txt['gr_type_' . $context['report_type']] : $context['report_type']); // Build the reports button array. $context['report_buttons'] = array('generate_reports' => array('text' => 'generate_reports', 'image' => 'print.png', 'lang' => true, 'url' => $scripturl . '?action=admin;area=reports', 'active' => true), 'print' => array('text' => 'print', 'image' => 'print.png', 'lang' => true, 'url' => $scripturl . '?action=admin;area=reports;rt=' . $context['report_type'] . ';st=print', 'custom' => 'target="_blank"')); // Allow mods to add additional buttons here call_integration_hook('integrate_report_buttons'); // Now generate the data. $this->{$context['report_types'][$context['report_type']]['function']}(); // Finish the tables before exiting - this is to help the templates a little more. finishTables(); }
protected static function buildTemplate($notices) { global $context, $user_info; loadTemplate('DismissibleNotices'); loadLanguage('DismissibleNotices'); Template_Layers::getInstance()->addAfter('notices', 'body'); loadJavascriptFile('notify.js', array('defer' => true)); loadCSSFile('notify.css'); foreach ($notices as $key => $notice) { $notice['body'] = str_replace('{username}', $user_info['name'], $notice['body']); $context['notices'][$key] = $notice; } $context['notices'] = $notices; }
/** * Handy shortcut to prepare the "system" * @param string $language_file */ private function _prepareLocale($language_file) { global $modSettings; if (!empty($language_file)) { loadLanguage($language_file); } Template_Layers::getInstance()->removeAll(); // Lets make sure we aren't going to output anything nasty. @ob_end_clean(); if (!empty($modSettings['enableCompressedOutput'])) { ob_start('ob_gzhandler'); } else { ob_start(); } }
public function action_index_api() { Template_Layers::getInstance()->removeAll(); loadTemplate('DismissibleNotices'); loadLanguage('DismissibleNotices'); if (isset($_GET['edit'])) { return $this->action_edit(); } elseif (isset($_GET['save'])) { return $this->action_save(); } elseif (isset($_GET['new'])) { return $this->action_new(); } elseif (isset($_GET['reset'])) { return $this->action_reset(); } }
/** * Turn off/on unread replies subscription for a topic * Intended for use in XML or JSON calls */ public function action_unwatchtopic_api() { global $user_info, $topic, $modSettings, $txt, $context, $scripturl; loadTemplate('Xml'); Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'generic_xml_buttons'; if ($user_info['is_guest']) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['not_guests']); return; } // Let's do something only if the function is enabled if (empty($modSettings['enable_unwatch'])) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['feature_disabled']); return; } if (checkSession('get', '', false)) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'url' => $scripturl . '?action=unwatchtopic;sa=' . ($_GET['sa'] == 'on' ? 'on' : 'off') . ';topic=' . $topic . '.' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id']); return; } // our topic functions are here require_once SUBSDIR . '/Topic.subs.php'; setTopicWatch($user_info['id'], $topic, $_GET['sa'] == 'on'); $context['xml_data'] = array('text' => $_GET['sa'] == 'on' ? $txt['watch'] : $txt['unwatch'], 'url' => $scripturl . '?action=unwatchtopic;topic=' . $context['current_topic'] . '.' . $_REQUEST['start'] . ';sa=' . ($_GET['sa'] == 'on' ? 'off' : 'on') . ';' . $context['session_var'] . '=' . $context['session_id'] . ';api' . (isset($_REQUEST['json']) ? ';json' : '')); }
/** * This function shows the board index. * * What it does: * - It uses the BoardIndex template, and main sub template. * - It updates the most online statistics. * - It is accessed by ?action=boardindex. */ public function action_boardindex() { global $txt, $user_info, $modSettings, $context, $settings, $scripturl; loadTemplate('BoardIndex'); // Set a canonical URL for this page. $context['canonical_url'] = $scripturl; Template_Layers::getInstance()->add('boardindex_outer'); // Do not let search engines index anything if there is a random thing in $_GET. if (!empty($_GET)) { $context['robot_no_index'] = true; } // Retrieve the categories and boards. require_once SUBSDIR . '/BoardsList.class.php'; $boardIndexOptions = array('include_categories' => true, 'base_level' => 0, 'parent_id' => 0, 'set_latest_post' => true, 'countChildPosts' => !empty($modSettings['countChildPosts'])); $boardlist = new Boards_List($boardIndexOptions); $context['categories'] = $boardlist->getBoards(); $context['latest_post'] = $boardlist->getLatestPost(); // Get the user online list. require_once SUBSDIR . '/MembersOnline.subs.php'; $membersOnlineOptions = array('show_hidden' => allowedTo('moderate_forum'), 'sort' => 'log_time', 'reverse_sort' => true); $context += getMembersOnlineStats($membersOnlineOptions); $context['show_buddies'] = !empty($user_info['buddies']); // Are we showing all membergroups on the board index? if (!empty($settings['show_group_key'])) { $context['membergroups'] = cache_quick_get('membergroup_list', 'subs/Membergroups.subs.php', 'cache_getMembergroupList', array()); } // Track most online statistics? (subs/Members.subs.phpOnline.php) if (!empty($modSettings['trackStats'])) { trackStatsUsersOnline($context['num_guests'] + $context['num_users_online']); } // Retrieve the latest posts if the theme settings require it. if (isset($settings['number_recent_posts']) && $settings['number_recent_posts'] > 1) { $latestPostOptions = array('number_posts' => $settings['number_recent_posts']); $context['latest_posts'] = cache_quick_get('boardindex-latest_posts:' . md5($user_info['query_wanna_see_board'] . $user_info['language']), 'subs/Recent.subs.php', 'cache_getLastPosts', array($latestPostOptions)); } // Let the template know what the members can do if the theme enables these options $context['show_stats'] = allowedTo('view_stats') && !empty($modSettings['trackStats']); $context['show_member_list'] = allowedTo('view_mlist'); $context['show_who'] = allowedTo('who_view') && !empty($modSettings['who_enabled']); // Load the calendar? if (!empty($modSettings['cal_enabled']) && allowedTo('calendar_view')) { // Retrieve the calendar data (events, birthdays, holidays). $eventOptions = array('include_holidays' => $modSettings['cal_showholidays'] > 1, 'include_birthdays' => $modSettings['cal_showbdays'] > 1, 'include_events' => $modSettings['cal_showevents'] > 1, 'num_days_shown' => empty($modSettings['cal_days_for_index']) || $modSettings['cal_days_for_index'] < 1 ? 1 : $modSettings['cal_days_for_index']); $context += cache_quick_get('calendar_index_offset_' . ($user_info['time_offset'] + $modSettings['time_offset']), 'subs/Calendar.subs.php', 'cache_getRecentEvents', array($eventOptions)); // Whether one or multiple days are shown on the board index. $context['calendar_only_today'] = $modSettings['cal_days_for_index'] == 1; // This is used to show the "how-do-I-edit" help. $context['calendar_can_edit'] = allowedTo('calendar_edit_any'); $show_calendar = true; } else { $show_calendar = false; } $context['page_title'] = sprintf($txt['forum_index'], $context['forum_name']); $context['sub_template'] = 'boards_list'; // Mark read button $context['mark_read_button'] = array('markread' => array('text' => 'mark_as_read', 'image' => 'markread.png', 'lang' => true, 'custom' => 'onclick="return markallreadButton(this);"', 'url' => $scripturl . '?action=markasread;sa=all;bi;' . $context['session_var'] . '=' . $context['session_id'])); $context['info_center_callbacks'] = array(); if (!empty($settings['number_recent_posts']) && (!empty($context['latest_posts']) || !empty($context['latest_post']))) { $context['info_center_callbacks'][] = 'recent_posts'; } if ($show_calendar) { $context['info_center_callbacks'][] = 'show_events'; } if (!empty($settings['show_stats_index'])) { $context['info_center_callbacks'][] = 'show_stats'; } $context['info_center_callbacks'][] = 'show_users'; // Allow mods to add additional buttons here call_integration_hook('integrate_mark_read_button'); }
/** * Shows an interface to set and test censored words. * * - It uses the censor_vulgar, censor_proper, censorWholeWord, and * censorIgnoreCase settings. * - Requires the admin_forum permission. * - Accessed from ?action=admin;area=postsettings;sa=censor. * * @uses the Admin template and the edit_censored sub template. */ public function action_censor() { global $txt, $modSettings, $context; if (!empty($_POST['save_censor'])) { // Make sure censoring is something they can do. checkSession(); validateToken('admin-censor'); $censored_vulgar = array(); $censored_proper = array(); // Rip it apart, then split it into two arrays. if (isset($_POST['censortext'])) { $_POST['censortext'] = explode("\n", strtr($_POST['censortext'], array("\r" => ''))); foreach ($_POST['censortext'] as $c) { list($censored_vulgar[], $censored_proper[]) = array_pad(explode('=', trim($c)), 2, ''); } } elseif (isset($_POST['censor_vulgar'], $_POST['censor_proper'])) { if (is_array($_POST['censor_vulgar'])) { foreach ($_POST['censor_vulgar'] as $i => $value) { if (trim(strtr($value, '*', ' ')) == '') { unset($_POST['censor_vulgar'][$i], $_POST['censor_proper'][$i]); } } $censored_vulgar = $_POST['censor_vulgar']; $censored_proper = $_POST['censor_proper']; } else { $censored_vulgar = explode("\n", strtr($_POST['censor_vulgar'], array("\r" => ''))); $censored_proper = explode("\n", strtr($_POST['censor_proper'], array("\r" => ''))); } } // Set the new arrays and settings in the database. $updates = array('censor_vulgar' => implode("\n", $censored_vulgar), 'censor_proper' => implode("\n", $censored_proper), 'censorWholeWord' => empty($_POST['censorWholeWord']) ? '0' : '1', 'censorIgnoreCase' => empty($_POST['censorIgnoreCase']) ? '0' : '1'); call_integration_hook('integrate_save_censors', array(&$updates)); updateSettings($updates); } // Testing a word to see how it will be censored? if (isset($_POST['censortest'])) { require_once SUBSDIR . '/Post.subs.php'; $censorText = htmlspecialchars($_POST['censortest'], ENT_QUOTES, 'UTF-8'); preparsecode($censorText); $pre_censor = $censorText; $context['censor_test'] = strtr(censorText($censorText), array('"' => '"')); } // Set everything up for the template to do its thang. $censor_vulgar = explode("\n", $modSettings['censor_vulgar']); $censor_proper = explode("\n", $modSettings['censor_proper']); $context['censored_words'] = array(); for ($i = 0, $n = count($censor_vulgar); $i < $n; $i++) { if (empty($censor_vulgar[$i])) { continue; } // Skip it, it's either spaces or stars only. if (trim(strtr($censor_vulgar[$i], '*', ' ')) == '') { continue; } $context['censored_words'][htmlspecialchars(trim($censor_vulgar[$i]))] = isset($censor_proper[$i]) ? htmlspecialchars($censor_proper[$i], ENT_COMPAT, 'UTF-8') : ''; } call_integration_hook('integrate_censors'); createToken('admin-censor'); // Using ajax? if (isset($_REQUEST['xml'], $_POST['censortest'])) { // Clear the templates $template_layers = Template_Layers::getInstance(); $template_layers->removeAll(); // Send back a response loadTemplate('Json'); $context['sub_template'] = 'send_json'; $context['json_data'] = array('result' => true, 'censor' => $pre_censor . ' <i class="fa fa-arrow-circle-right"></i> ' . $context['censor_test'], 'token_val' => $context['admin-censor_token_var'], 'token' => $context['admin-censor_token']); } else { $context['sub_template'] = 'edit_censored'; $context['page_title'] = $txt['admin_censored_words']; } }
/** * Allow the change or view of profiles. * Loads the profile menu. * * @see Action_Controller::action_index() */ public function action_index() { global $txt, $scripturl, $user_info, $context, $user_profile, $cur_profile; global $modSettings, $memberContext, $profile_vars, $post_errors, $user_settings; // Don't reload this as we may have processed error strings. if (empty($post_errors)) { loadLanguage('Profile+Drafts'); } loadTemplate('Profile'); require_once SUBSDIR . '/Menu.subs.php'; require_once SUBSDIR . '/Profile.subs.php'; $memID = currentMemberID(); $context['id_member'] = $memID; $cur_profile = $user_profile[$memID]; // Let's have some information about this member ready, too. loadMemberContext($memID); $context['member'] = $memberContext[$memID]; // Is this the profile of the user himself or herself? $context['user']['is_owner'] = $memID == $user_info['id']; /** * Define all the sections within the profile area! * We start by defining the permission required - then we take this and turn * it into the relevant context ;) * * Possible fields: * For Section: * - string $title: Section title. * - array $areas: Array of areas within this section. * * For Areas: * - string $label: Text string that will be used to show the area in the menu. * - string $file: Optional text string that may contain a file name that's needed for inclusion in order to display the area properly. * - string $custom_url: Optional href for area. * - string $function: Function to execute for this section. * - bool $enabled: Should area be shown? * - string $sc: Session check validation to do on save - note without this save will get unset - if set. * - bool $hidden: Does this not actually appear on the menu? * - bool $password: Whether to require the user's password in order to save the data in the area. * - array $subsections: Array of subsections, in order of appearance. * - array $permission: Array of permissions to determine who can access this area. Should contain arrays $own and $any. */ $profile_areas = array('info' => array('title' => $txt['profileInfo'], 'areas' => array('summary' => array('label' => $txt['summary'], 'file' => 'ProfileInfo.controller.php', 'controller' => 'ProfileInfo_Controller', 'function' => 'action_summary', 'token' => 'profile-aa%u', 'token_type' => 'get', 'permission' => array('own' => 'profile_view_own', 'any' => 'profile_view_any')), 'statistics' => array('label' => $txt['statPanel'], 'file' => 'ProfileInfo.controller.php', 'controller' => 'ProfileInfo_Controller', 'function' => 'action_statPanel', 'permission' => array('own' => 'profile_view_own', 'any' => 'profile_view_any')), 'showposts' => array('label' => $txt['showPosts'], 'file' => 'ProfileInfo.controller.php', 'controller' => 'ProfileInfo_Controller', 'function' => 'action_showPosts', 'subsections' => array('messages' => array($txt['showMessages'], array('profile_view_own', 'profile_view_any')), 'topics' => array($txt['showTopics'], array('profile_view_own', 'profile_view_any')), 'unwatchedtopics' => array($txt['showUnwatched'], array('profile_view_own', 'profile_view_any'), 'enabled' => $modSettings['enable_unwatch'] && $context['user']['is_owner']), 'attach' => array($txt['showAttachments'], array('profile_view_own', 'profile_view_any'))), 'permission' => array('own' => 'profile_view_own', 'any' => 'profile_view_any')), 'showdrafts' => array('label' => $txt['drafts_show'], 'file' => 'Draft.controller.php', 'controller' => 'Draft_Controller', 'function' => 'action_showProfileDrafts', 'enabled' => !empty($modSettings['drafts_enabled']) && $context['user']['is_owner'], 'permission' => array('own' => 'profile_view_own', 'any' => array())), 'showlikes' => array('label' => $txt['likes_show'], 'file' => 'Likes.controller.php', 'controller' => 'Likes_Controller', 'function' => 'action_showProfileLikes', 'enabled' => !empty($modSettings['likes_enabled']) && $context['user']['is_owner'], 'subsections' => array('given' => array($txt['likes_given'], array('profile_view_own')), 'received' => array($txt['likes_received'], array('profile_view_own'))), 'permission' => array('own' => 'profile_view_own', 'any' => array())), 'permissions' => array('label' => $txt['showPermissions'], 'file' => 'ProfileInfo.controller.php', 'controller' => 'ProfileInfo_Controller', 'function' => 'action_showPermissions', 'permission' => array('own' => 'manage_permissions', 'any' => 'manage_permissions')), 'history' => array('label' => $txt['history'], 'file' => 'ProfileHistory.controller.php', 'controller' => 'ProfileHistory_Controller', 'function' => 'action_index', 'subsections' => array('activity' => array($txt['trackActivity'], 'moderate_forum'), 'ip' => array($txt['trackIP'], 'moderate_forum'), 'edits' => array($txt['trackEdits'], 'moderate_forum'), 'logins' => array($txt['trackLogins'], array('profile_view_own', 'moderate_forum'))), 'permission' => array('own' => 'moderate_forum', 'any' => 'moderate_forum')), 'viewwarning' => array('label' => $txt['profile_view_warnings'], 'enabled' => in_array('w', $context['admin_features']) && !empty($modSettings['warning_enable']) && $cur_profile['warning'] && (!empty($modSettings['warning_show']) && ($context['user']['is_owner'] || $modSettings['warning_show'] == 2)), 'file' => 'ProfileInfo.controller.php', 'controller' => 'ProfileInfo_Controller', 'function' => 'action_viewWarning', 'permission' => array('own' => 'profile_view_own', 'any' => 'issue_warning')))), 'edit_profile' => array('title' => $txt['profileEdit'], 'areas' => array('account' => array('label' => $txt['account'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_account', 'enabled' => $context['user']['is_admin'] || $cur_profile['id_group'] != 1 && !in_array(1, explode(',', $cur_profile['additional_groups'])), 'sc' => 'post', 'token' => 'profile-ac%u', 'password' => true, 'permission' => array('own' => array('profile_identity_any', 'profile_identity_own', 'manage_membergroups'), 'any' => array('profile_identity_any', 'manage_membergroups'))), 'forumprofile' => array('label' => $txt['forumprofile'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_forumProfile', 'sc' => 'post', 'token' => 'profile-fp%u', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own', 'profile_title_own', 'profile_title_any'), 'any' => array('profile_extra_any', 'profile_title_any'))), 'theme' => array('label' => $txt['theme'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_themepick', 'sc' => 'post', 'token' => 'profile-th%u', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array('profile_extra_any'))), 'authentication' => array('label' => $txt['authentication'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_authentication', 'enabled' => !empty($modSettings['enableOpenID']) || !empty($cur_profile['openid_uri']), 'sc' => 'post', 'token' => 'profile-au%u', 'hidden' => empty($modSettings['enableOpenID']) && empty($cur_profile['openid_uri']), 'password' => true, 'permission' => array('own' => array('profile_identity_any', 'profile_identity_own'), 'any' => array('profile_identity_any'))), 'notification' => array('label' => $txt['notifications'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_notification', 'sc' => 'post', 'token' => 'profile-nt%u', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array('profile_extra_any'))), 'contactprefs' => array('label' => $txt['contactprefs'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_pmprefs', 'enabled' => allowedTo(array('profile_extra_own', 'profile_extra_any')), 'sc' => 'post', 'token' => 'profile-pm%u', 'permission' => array('own' => array('pm_read'), 'any' => array('profile_extra_any'))), 'ignoreboards' => array('label' => $txt['ignoreboards'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_ignoreboards', 'enabled' => !empty($modSettings['allow_ignore_boards']), 'sc' => 'post', 'token' => 'profile-ib%u', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array('profile_extra_any'))), 'lists' => array('label' => $txt['editBuddyIgnoreLists'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_editBuddyIgnoreLists', 'enabled' => !empty($modSettings['enable_buddylist']) && $context['user']['is_owner'], 'sc' => 'post', 'token' => 'profile-bl%u', 'subsections' => array('buddies' => array($txt['editBuddies']), 'ignore' => array($txt['editIgnoreList'])), 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array())), 'groupmembership' => array('label' => $txt['groupmembership'], 'file' => 'ProfileOptions.controller.php', 'controller' => 'ProfileOptions_Controller', 'function' => 'action_groupMembership', 'enabled' => !empty($modSettings['show_group_membership']) && $context['user']['is_owner'], 'sc' => 'request', 'token' => 'profile-gm%u', 'token_type' => 'request', 'permission' => array('own' => array('profile_view_own'), 'any' => array('manage_membergroups'))))), 'profile_action' => array('title' => $txt['profileAction'], 'areas' => array('sendpm' => array('label' => $txt['profileSendIm'], 'custom_url' => $scripturl . '?action=pm;sa=send', 'permission' => array('own' => array(), 'any' => array('pm_send'))), 'issuewarning' => array('label' => $txt['profile_issue_warning'], 'enabled' => in_array('w', $context['admin_features']) && !empty($modSettings['warning_enable']) && (!$context['user']['is_owner'] || $context['user']['is_admin']), 'file' => 'ProfileAccount.controller.php', 'controller' => 'ProfileAccount_Controller', 'function' => 'action_issuewarning', 'token' => 'profile-iw%u', 'permission' => array('own' => array(), 'any' => array('issue_warning'))), 'banuser' => array('label' => $txt['profileBanUser'], 'custom_url' => $scripturl . '?action=admin;area=ban;sa=add', 'enabled' => $cur_profile['id_group'] != 1 && !in_array(1, explode(',', $cur_profile['additional_groups'])), 'permission' => array('own' => array(), 'any' => array('manage_bans'))), 'subscriptions' => array('label' => $txt['subscriptions'], 'file' => 'ProfileSubscriptions.controller.php', 'controller' => 'ProfileSubscriptions_Controller', 'function' => 'action_subscriptions', 'enabled' => !empty($modSettings['paid_enabled']), 'permission' => array('own' => array('profile_view_own'), 'any' => array('moderate_forum'))), 'deleteaccount' => array('label' => $txt['deleteAccount'], 'file' => 'ProfileAccount.controller.php', 'controller' => 'ProfileAccount_Controller', 'function' => 'action_deleteaccount', 'sc' => 'post', 'token' => 'profile-da%u', 'password' => true, 'permission' => array('own' => array('profile_remove_any', 'profile_remove_own'), 'any' => array('profile_remove_any'))), 'activateaccount' => array('file' => 'ProfileAccount.controller.php', 'controller' => 'ProfileAccount_Controller', 'function' => 'action_activateaccount', 'sc' => 'get', 'token' => 'profile-aa%u', 'permission' => array('own' => array(), 'any' => array('moderate_forum')))))); // Is there an updated message to show? if (isset($_GET['updated'])) { $context['profile_updated'] = $txt['profile_updated_own']; } // Set a few options for the menu. $menuOptions = array('disable_url_session_check' => true, 'hook' => 'profile', 'extra_url_parameters' => array('u' => $context['id_member']), 'default_include_dir' => CONTROLLERDIR); // Actually create the menu! $profile_include_data = createMenu($profile_areas, $menuOptions); unset($profile_areas); // If it said no permissions that meant it wasn't valid! if ($profile_include_data && empty($profile_include_data['permission'])) { $profile_include_data['enabled'] = false; } // No menu and guest? A warm welcome to register if (!$profile_include_data && $user_info['is_guest']) { is_not_guest(); } // No menu means no access. if (!$profile_include_data || isset($profile_include_data['enabled']) && $profile_include_data['enabled'] === false) { fatal_lang_error('no_access', false); } // Make a note of the Unique ID for this menu. $context['profile_menu_id'] = $context['max_menu_id']; $context['profile_menu_name'] = 'menu_data_' . $context['profile_menu_id']; // Set the selected item - now it's been validated. $current_area = $profile_include_data['current_area']; $context['menu_item_selected'] = $current_area; // Before we go any further, let's work on the area we've said is valid. // Note this is done here just in case we ever compromise the menu function in error! $this->_completed_save = false; $context['do_preview'] = isset($_REQUEST['preview_signature']); // Are we saving data in a valid area? if (isset($profile_include_data['sc']) && (isset($_REQUEST['save']) || $context['do_preview'])) { checkSession($profile_include_data['sc']); $this->_completed_save = true; } // Does this require session validating? if (!empty($area['validate']) || isset($_REQUEST['save']) && !$context['user']['is_owner']) { validateSession(); } // Do we need to perform a token check? if (!empty($profile_include_data['token'])) { if ($profile_include_data['token'] !== true) { $token_name = str_replace('%u', $context['id_member'], $profile_include_data['token']); } else { $token_name = 'profile-u' . $context['id_member']; } if (isset($profile_include_data['token_type']) && in_array($profile_include_data['token_type'], array('request', 'post', 'get'))) { $token_type = $profile_include_data['token_type']; } else { $token_type = 'post'; } if (isset($_REQUEST['save'])) { validateToken($token_name, $token_type); } } // Permissions for good measure. if (!empty($profile_include_data['permission'])) { isAllowedTo($profile_include_data['permission'][$context['user']['is_owner'] ? 'own' : 'any']); } // Create a token if needed. if (!empty($profile_include_data['token'])) { createToken($token_name, $token_type); $context['token_check'] = $token_name; } // Build the link tree. $context['linktree'][] = array('url' => $scripturl . '?action=profile' . ($memID != $user_info['id'] ? ';u=' . $memID : ''), 'name' => sprintf($txt['profile_of_username'], $context['member']['name'])); if (!empty($profile_include_data['label'])) { $context['linktree'][] = array('url' => $scripturl . '?action=profile' . ($memID != $user_info['id'] ? ';u=' . $memID : '') . ';area=' . $profile_include_data['current_area'], 'name' => $profile_include_data['label']); } if (!empty($profile_include_data['current_subsection']) && $profile_include_data['subsections'][$profile_include_data['current_subsection']][0] != $profile_include_data['label']) { $context['linktree'][] = array('url' => $scripturl . '?action=profile' . ($memID != $user_info['id'] ? ';u=' . $memID : '') . ';area=' . $profile_include_data['current_area'] . ';sa=' . $profile_include_data['current_subsection'], 'name' => $profile_include_data['subsections'][$profile_include_data['current_subsection']][0]); } // Set the template for this area... if you still can :P // and add the profile layer. $context['sub_template'] = $profile_include_data['function']; Template_Layers::getInstance()->add('profile'); loadJavascriptFile('profile.js'); // All the subactions that require a user password in order to validate. $check_password = $context['user']['is_owner'] && !empty($profile_include_data['password']); $context['require_password'] = $check_password && empty($user_settings['openid_uri']); // These will get populated soon! $post_errors = array(); $profile_vars = array(); // Right - are we saving - if so let's save the old data first. if ($this->_completed_save) { // Clean up the POST variables. $_POST = htmltrim__recursive($_POST); $_POST = htmlspecialchars__recursive($_POST); if ($check_password) { // If we're using OpenID try to revalidate. if (!empty($user_settings['openid_uri'])) { require_once SUBSDIR . '/OpenID.subs.php'; $openID = new OpenID(); $openID->revalidate(); } else { // You didn't even enter a password! if (trim($_POST['oldpasswrd']) == '') { $post_errors[] = 'no_password'; } // Since the password got modified due to all the $_POST cleaning, lets undo it so we can get the correct password $_POST['oldpasswrd'] = un_htmlspecialchars($_POST['oldpasswrd']); // Does the integration want to check passwords? $good_password = in_array(true, call_integration_hook('integrate_verify_password', array($cur_profile['member_name'], $_POST['oldpasswrd'], false)), true); // Start up the password checker, we have work to do require_once SUBSDIR . '/Auth.subs.php'; // Bad password!!! if (!$good_password && !validateLoginPassword($_POST['oldpasswrd'], $user_info['passwd'], $user_profile[$memID]['member_name'])) { $post_errors[] = 'bad_password'; } // Warn other elements not to jump the gun and do custom changes! if (in_array('bad_password', $post_errors)) { $context['password_auth_failed'] = true; } } } // Change the IP address in the database. if ($context['user']['is_owner']) { $profile_vars['member_ip'] = $user_info['ip']; } // Now call the sub-action function... if ($current_area == 'activateaccount') { if (empty($post_errors)) { require_once CONTROLLERDIR . '/ProfileAccount.controller.php'; $controller = new ProfileAccount_Controller(); $controller->action_activateaccount(); } } elseif ($current_area == 'deleteaccount') { if (empty($post_errors)) { require_once CONTROLLERDIR . '/ProfileAccount.controller.php'; $controller = new ProfileAccount_Controller(); $controller->action_deleteaccount2(); redirectexit(); } } elseif ($current_area == 'groupmembership' && empty($post_errors)) { require_once CONTROLLERDIR . '/ProfileOptions.controller.php'; $controller = new Profileoptions_Controller(); $msg = $controller->action_groupMembership2(); // Whatever we've done, we have nothing else to do here... redirectexit('action=profile' . ($context['user']['is_owner'] ? '' : ';u=' . $memID) . ';area=groupmembership' . (!empty($msg) ? ';msg=' . $msg : '')); } elseif ($current_area == 'authentication') { require_once CONTROLLERDIR . '/ProfileOptions.controller.php'; $controller = new ProfileOptions_Controller(); $controller->action_authentication(true); } elseif (in_array($current_area, array('account', 'forumprofile', 'theme', 'contactprefs'))) { saveProfileFields(); } else { $force_redirect = true; saveProfileChanges($profile_vars, $memID); } call_integration_hook('integrate_profile_save', array(&$profile_vars, &$post_errors, $memID)); // There was a problem, let them try to re-enter. if (!empty($post_errors)) { // Load the language file so we can give a nice explanation of the errors. loadLanguage('Errors'); $context['post_errors'] = $post_errors; } elseif (!empty($profile_vars)) { // If we've changed the password, notify any integration that may be listening in. if (isset($profile_vars['passwd'])) { call_integration_hook('integrate_reset_pass', array($cur_profile['member_name'], $cur_profile['member_name'], $_POST['passwrd2'])); } updateMemberData($memID, $profile_vars); // What if this is the newest member? if ($modSettings['latestMember'] == $memID) { updateStats('member'); } elseif (isset($profile_vars['real_name'])) { updateSettings(array('memberlist_updated' => time())); } // If the member changed his/her birthdate, update calendar statistics. if (isset($profile_vars['birthdate']) || isset($profile_vars['real_name'])) { updateSettings(array('calendar_updated' => time())); } // Anything worth logging? if (!empty($context['log_changes']) && !empty($modSettings['modlog_enabled'])) { $log_changes = array(); foreach ($context['log_changes'] as $k => $v) { $log_changes[] = array('action' => $k, 'log_type' => 'user', 'extra' => array_merge($v, array('applicator' => $user_info['id'], 'member_affected' => $memID))); } logActions($log_changes); } // Have we got any post save functions to execute? if (!empty($context['profile_execute_on_save'])) { foreach ($context['profile_execute_on_save'] as $saveFunc) { $saveFunc(); } } // Let them know it worked! $context['profile_updated'] = $context['user']['is_owner'] ? $txt['profile_updated_own'] : sprintf($txt['profile_updated_else'], $cur_profile['member_name']); // Invalidate any cached data. cache_put_data('member_data-profile-' . $memID, null, 0); } } // Have some errors for some reason? if (!empty($post_errors)) { // Set all the errors so the template knows what went wrong. foreach ($post_errors as $error_type) { $context['modify_error'][$error_type] = true; } } elseif (!empty($profile_vars) && $context['user']['is_owner'] && !$context['do_preview']) { redirectexit('action=profile;area=' . $current_area . ';updated'); } elseif (!empty($force_redirect)) { redirectexit('action=profile' . ($context['user']['is_owner'] ? '' : ';u=' . $memID) . ';area=' . $current_area); } // Let go to the right place if (isset($profile_include_data['file'])) { require_once $profile_include_data['file']; } callMenu($profile_include_data); // Set the page title if it's not already set... if (!isset($context['page_title'])) { $context['page_title'] = $txt['profile'] . (isset($txt[$current_area]) ? ' - ' . $txt[$current_area] : ''); } }
/** * Show the verification code or let it hear. * Accessed by ?action=verificationcode */ public function action_verificationcode() { global $context, $scripturl; $verification_id = isset($_GET['vid']) ? $_GET['vid'] : ''; $code = $verification_id && isset($_SESSION[$verification_id . '_vv']) ? $_SESSION[$verification_id . '_vv']['code'] : (isset($_SESSION['visual_verification_code']) ? $_SESSION['visual_verification_code'] : ''); // Somehow no code was generated or the session was lost. if (empty($code)) { header('Content-Type: image/gif'); die("GIF89a€!ù,D;"); } elseif (isset($_REQUEST['sound'])) { loadLanguage('Login'); loadTemplate('Register'); $context['verification_sound_href'] = $scripturl . '?action=verificationcode;rand=' . md5(mt_rand()) . ($verification_id ? ';vid=' . $verification_id : '') . ';format=.wav'; $context['sub_template'] = 'verification_sound'; Template_Layers::getInstance()->removeAll(); obExit(); } elseif (empty($_REQUEST['format'])) { require_once SUBSDIR . '/Graphics.subs.php'; if (in_array('gd', get_loaded_extensions()) && !showCodeImage($code)) { header('HTTP/1.1 400 Bad Request'); } elseif (isset($_REQUEST['letter'])) { $_REQUEST['letter'] = (int) $_REQUEST['letter']; if ($_REQUEST['letter'] > 0 && $_REQUEST['letter'] <= strlen($code) && !showLetterImage(strtolower($code[$_REQUEST['letter'] - 1]))) { header('Content-Type: image/gif'); die("GIF89a€!ù,D;"); } } else { header('Content-Type: image/gif'); die("GIF89a€!ù,D;"); } } elseif ($_REQUEST['format'] === '.wav') { require_once SUBSDIR . '/Sound.subs.php'; if (!createWaveFile($code)) { header('HTTP/1.1 400 Bad Request'); } } // We all die one day... die; }
/** * Find and return Template_Layers instance if it exists, * or create a new instance if it didn't already exist. * * @param boolean $error_safe if error mode is on or off * @return Template_Layers instance of the class */ public static function getInstance($error_safe = false) { if (self::$_instance === null) { self::$_instance = new Template_Layers(); } self::$_error_safe = $error_safe; return self::$_instance; }
/** * Do some important security checks: * * What it does: * - checks the existence of critical files e.g. install.php * - checks for an active admin session. * - checks cache directory is writable. * - calls secureDirectory to protect attachments & cache. * - checks if the forum is in maintance mode. */ function doSecurityChecks() { global $modSettings, $context, $maintenance, $user_info, $txt, $scripturl, $user_settings, $options; $show_warnings = false; if (allowedTo('admin_forum') && !$user_info['is_guest']) { // If agreement is enabled, at least the english version shall exists if ($modSettings['requireAgreement'] && !file_exists(BOARDDIR . '/agreement.txt')) { $context['security_controls_files']['title'] = $txt['generic_warning']; $context['security_controls_files']['errors']['agreement'] = $txt['agreement_missing']; $show_warnings = true; } // Cache directory writeable? if (!empty($modSettings['cache_enable']) && !is_writable(CACHEDIR)) { $context['security_controls_files']['title'] = $txt['generic_warning']; $context['security_controls_files']['errors']['cache'] = $txt['cache_writable']; $show_warnings = true; } // @todo add a hook here $securityFiles = array('install.php', 'upgrade.php', 'convert.php', 'repair_paths.php', 'repair_settings.php', 'Settings.php~', 'Settings_bak.php~'); foreach ($securityFiles as $securityFile) { if (file_exists(BOARDDIR . '/' . $securityFile)) { $context['security_controls_files']['title'] = $txt['security_risk']; $context['security_controls_files']['errors'][$securityFile] = sprintf($txt['not_removed'], $securityFile); $show_warnings = true; if ($securityFile == 'Settings.php~' || $securityFile == 'Settings_bak.php~') { $context['security_controls_files']['errors'][$securityFile] .= '<span class="smalltext">' . sprintf($txt['not_removed_extra'], $securityFile, substr($securityFile, 0, -1)) . '</span>'; } } } // We are already checking so many files...just few more doesn't make any difference! :P require_once SUBSDIR . '/Attachments.subs.php'; $path = getAttachmentPath(); secureDirectory($path, true); secureDirectory(CACHEDIR); // Active admin session? if (empty($modSettings['securityDisable']) && (isset($_SESSION['admin_time']) && $_SESSION['admin_time'] + $modSettings['admin_session_lifetime'] * 60 > time())) { $context['warning_controls']['admin_session'] = sprintf($txt['admin_session_active'], $scripturl . '?action=admin;area=adminlogoff;redir;' . $context['session_var'] . '=' . $context['session_id']); } // Maintenance mode enabled? if (!empty($maintenance)) { $context['warning_controls']['maintenance'] = sprintf($txt['admin_maintenance_active'], $scripturl . '?action=admin;area=serversettings;' . $context['session_var'] . '=' . $context['session_id']); } // New updates if (defined('FORUM_VERSION')) { $index = 'new_in_' . str_replace(array('ElkArte ', '.'), array('', '_'), FORUM_VERSION); if (!empty($modSettings[$index]) && empty($options['dismissed_' . $index])) { $show_warnings = true; $context['new_version_updates'] = array('title' => $txt['new_version_updates'], 'errors' => array(replaceBasicActionUrl($txt['new_version_updates_text']))); } } } // Check for database errors. if (!empty($_SESSION['query_command_denied'])) { if ($user_info['is_admin']) { $context['security_controls_query']['title'] = $txt['query_command_denied']; $show_warnings = true; foreach ($_SESSION['query_command_denied'] as $command => $error) { $context['security_controls_query']['errors'][$command] = '<pre>' . Util::htmlspecialchars($error) . '</pre>'; } } else { $context['security_controls_query']['title'] = $txt['query_command_denied_guests']; foreach ($_SESSION['query_command_denied'] as $command => $error) { $context['security_controls_query']['errors'][$command] = '<pre>' . sprintf($txt['query_command_denied_guests_msg'], Util::htmlspecialchars($command)) . '</pre>'; } } } // Are there any members waiting for approval? if (allowedTo('moderate_forum') && (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2 || !empty($modSettings['approveAccountDeletion'])) && !empty($modSettings['unapprovedMembers'])) { $context['warning_controls']['unapproved_members'] = sprintf($txt[$modSettings['unapprovedMembers'] == 1 ? 'approve_one_member_waiting' : 'approve_many_members_waiting'], $scripturl . '?action=admin;area=viewmembers;sa=browse;type=approve', $modSettings['unapprovedMembers']); } if (!empty($context['open_mod_reports']) && (empty($user_settings['mod_prefs']) || $user_settings['mod_prefs'][0] == 1)) { $context['warning_controls']['open_mod_reports'] = '<a href="' . $scripturl . '?action=moderate;area=reports">' . sprintf($txt['mod_reports_waiting'], $context['open_mod_reports']) . '</a>'; } if (isset($_SESSION['ban']['cannot_post'])) { // An admin cannot be banned (technically he could), and if it is better he knows. $context['security_controls_ban']['title'] = sprintf($txt['you_are_post_banned'], $user_info['is_guest'] ? $txt['guest_title'] : $user_info['name']); $show_warnings = true; $context['security_controls_ban']['errors']['reason'] = ''; if (!empty($_SESSION['ban']['cannot_post']['reason'])) { $context['security_controls_ban']['errors']['reason'] = $_SESSION['ban']['cannot_post']['reason']; } if (!empty($_SESSION['ban']['expire_time'])) { $context['security_controls_ban']['errors']['reason'] .= '<span class="smalltext">' . sprintf($txt['your_ban_expires'], standardTime($_SESSION['ban']['expire_time'], false)) . '</span>'; } else { $context['security_controls_ban']['errors']['reason'] .= '<span class="smalltext">' . $txt['your_ban_expires_never'] . '</span>'; } } // Finally, let's show the layer. if ($show_warnings || !empty($context['warning_controls'])) { Template_Layers::getInstance()->addAfter('admin_warning', 'body'); } }
header('Content-Type: text/html; charset=UTF-8'); } // Take care of any banning that needs to be done. if (isset($_REQUEST['ssi_ban']) || isset($ssi_ban) && $ssi_ban === true) { is_not_banned(); } // Do we allow guests in here? if (empty($ssi_guest_access) && empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && basename($_SERVER['PHP_SELF']) != 'SSI.php') { require_once CONTROLLERDIR . '/Auth.controller.php'; $controller = new Auth_Controller(); $controller->action_kickguest(); obExit(null, true); } // Load the stuff like the menu bar, etc. if (isset($ssi_layers)) { $template_layers = Template_Layers::getInstance(); $template_layers->removeAll(); foreach ($ssi_layers as $layer) { $template_layers->addBegin($layer); } template_header(); } else { setupThemeContext(); } // We need to set up user agent, and make more checks on the request $req = request(); // Make sure they didn't muss around with the settings... but only if it's not cli. if (isset($_SERVER['REMOTE_ADDR']) && session_id() == '') { trigger_error($txt['ssi_session_broken'], E_USER_NOTICE); } // Without visiting the forum this session variable might not be set on submit.
/** * The Shoutbox ... allows for the adding, editing, deleting and viewing of shouts */ public function action_sportal_shoutbox() { global $context, $scripturl, $user_info; // ID of the shoutbox we are working on and timestamp $shoutbox_id = !empty($_REQUEST['shoutbox_id']) ? (int) $_REQUEST['shoutbox_id'] : 0; $request_time = !empty($_REQUEST['time']) ? (int) $_REQUEST['time'] : 0; // We need to know which shoutbox this is for/from $context['SPortal']['shoutbox'] = sportal_get_shoutbox($shoutbox_id, true, true); if (empty($context['SPortal']['shoutbox'])) { if (isset($_REQUEST['xml'])) { obExit(false, false); } else { fatal_lang_error('error_sp_shoutbox_not_exist', false); } } // Any warning title for the shoutbox, like Not For Support ;P $context['SPortal']['shoutbox']['warning'] = parse_bbc($context['SPortal']['shoutbox']['warning']); $can_moderate = allowedTo('sp_admin') || allowedTo('sp_manage_shoutbox'); if (!$can_moderate && !empty($context['SPortal']['shoutbox']['moderator_groups'])) { $can_moderate = count(array_intersect($user_info['groups'], $context['SPortal']['shoutbox']['moderator_groups'])) > 0; } // Adding a shout if (!empty($_REQUEST['shout'])) { // Pretty basic is_not_guest(); checkSession('request'); // If you are not flooding the system, add the shout to the box if (!($flood = sp_prevent_flood('spsbp', false))) { require_once SUBSDIR . '/Post.subs.php'; $_REQUEST['shout'] = Util::htmlspecialchars(trim($_REQUEST['shout'])); preparsecode($_REQUEST['shout']); if (!empty($_REQUEST['shout'])) { sportal_create_shout($context['SPortal']['shoutbox'], $_REQUEST['shout']); } } else { $context['SPortal']['shoutbox']['warning'] = $flood; } } // Removing a shout, regret saying that do you :P if (!empty($_REQUEST['delete'])) { checkSession('request'); if (!$can_moderate) { fatal_lang_error('error_sp_cannot_shoutbox_moderate', false); } $delete = (int) $_REQUEST['delete']; if (!empty($delete)) { sportal_delete_shout($shoutbox_id, $delete); } } // Responding to an ajax request if (isset($_REQUEST['xml'])) { $shout_parameters = array('limit' => $context['SPortal']['shoutbox']['num_show'], 'bbc' => $context['SPortal']['shoutbox']['allowed_bbc'], 'reverse' => $context['SPortal']['shoutbox']['reverse'], 'cache' => $context['SPortal']['shoutbox']['caching'], 'can_moderate' => $can_moderate); // Get all the shouts for this box $context['SPortal']['shouts'] = sportal_get_shouts($shoutbox_id, $shout_parameters); // Return a clean xml response Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'shoutbox_xml'; $context['SPortal']['updated'] = empty($context['SPortal']['shoutbox']['last_update']) || $context['SPortal']['shoutbox']['last_update'] > $request_time; return; } // Show all the shouts in this box $total_shouts = sportal_get_shoutbox_count($shoutbox_id); $context['per_page'] = $context['SPortal']['shoutbox']['num_show']; $context['start'] = !empty($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; $context['page_index'] = constructPageIndex($scripturl . '?action=shoutbox;shoutbox_id=' . $shoutbox_id, $context['start'], $total_shouts, $context['per_page']); $shout_parameters = array('start' => $context['start'], 'limit' => $context['per_page'], 'bbc' => $context['SPortal']['shoutbox']['allowed_bbc'], 'cache' => $context['SPortal']['shoutbox']['caching'], 'can_moderate' => $can_moderate); $context['SPortal']['shouts_history'] = sportal_get_shouts($shoutbox_id, $shout_parameters); $context['SPortal']['shoutbox_id'] = $shoutbox_id; $context['sub_template'] = 'shoutbox_all'; $context['page_title'] = $context['SPortal']['shoutbox']['name']; }
/** * Format a topic to be printer friendly. * Must be called with a topic specified. * Accessed via ?action=topic;sa=printpage. * * @uses Printpage template, main sub-template. * @uses print_above/print_below later without the main layer. */ public function action_printpage() { global $topic, $scripturl, $context, $user_info, $board_info, $modSettings; // Redirect to the boardindex if no valid topic id is provided. if (empty($topic)) { redirectexit(); } $template_layers = Template_Layers::getInstance(); $template_layers->removeAll(); if (!empty($modSettings['disable_print_topic'])) { unset($_REQUEST['action']); $context['theme_loaded'] = false; fatal_lang_error('feature_disabled', false); } require_once SUBSDIR . '/Topic.subs.php'; // Get the topic starter information. $topicinfo = getTopicInfo($topic, 'starter'); $context['user']['started'] = $user_info['id'] == $topicinfo['id_member'] && !$user_info['is_guest']; // Whatever happens don't index this. $context['robot_no_index'] = true; // Redirect to the boardindex if no valid topic id is provided. if (empty($topicinfo)) { redirectexit(); } // @todo this code is almost the same as the one in Display.controller.php if ($topicinfo['id_poll'] > 0 && !empty($modSettings['pollMode']) && allowedTo('poll_view')) { loadLanguage('Post'); require_once SUBSDIR . '/Poll.subs.php'; loadPollContext($topicinfo['id_poll']); $template_layers->addAfter('print_poll', 'print'); } // Lets "output" all that info. loadTemplate('Printpage'); $template_layers->add('print'); $context['sub_template'] = 'print_page'; $context['board_name'] = $board_info['name']; $context['category_name'] = $board_info['cat']['name']; $context['poster_name'] = $topicinfo['poster_name']; $context['post_time'] = standardTime($topicinfo['poster_time'], false); $context['parent_boards'] = array(); foreach ($board_info['parent_boards'] as $parent) { $context['parent_boards'][] = $parent['name']; } // Split the topics up so we can print them. $context['posts'] = topicMessages($topic); $posts_id = array_keys($context['posts']); if (!isset($context['topic_subject'])) { $context['topic_subject'] = $context['posts'][min($posts_id)]['subject']; } // Fetch attachments so we can print them if asked, enabled and allowed if (isset($_REQUEST['images']) && !empty($modSettings['attachmentEnable']) && allowedTo('view_attachments')) { require_once SUBSDIR . '/Topic.subs.php'; $context['printattach'] = messagesAttachments(array_keys($context['posts'])); $context['viewing_attach'] = true; } // Set a canonical URL for this page. $context['canonical_url'] = $scripturl . '?topic=' . $topic . '.0'; $context['view_attach_mode'] = array('text' => $scripturl . '?action=topic;sa=printpage;topic=' . $topic . '.0', 'images' => $scripturl . '?action=topic;sa=printpage;topic=' . $topic . '.0;images'); }
/** * The only reason of this function is to build the poll UI and send it back in an XML form */ public function action_interface() { global $context, $board, $db_show_debug; loadTemplate('Poll'); loadLanguage('Post'); Template_Layers::getInstance()->removeAll(); if (isset($db_show_debug)) { $db_show_debug = false; } $context['sub_template'] = 'poll_edit'; require_once SUBSDIR . '/Members.subs.php'; $allowedVoteGroups = groupsAllowedTo('poll_vote', $board); // Set up the poll options. $context['poll'] = array('max_votes' => 1, 'hide_results' => 0, 'expiration' => '', 'change_vote' => false, 'guest_vote' => false, 'guest_vote_allowed' => in_array(-1, $allowedVoteGroups['allowed'])); $context['can_moderate_poll'] = true; // Make all five poll choices empty. $context['choices'] = array(array('id' => 0, 'number' => 1, 'label' => '', 'is_last' => false), array('id' => 1, 'number' => 2, 'label' => '', 'is_last' => false), array('id' => 2, 'number' => 3, 'label' => '', 'is_last' => false), array('id' => 3, 'number' => 4, 'label' => '', 'is_last' => false), array('id' => 4, 'number' => 5, 'label' => '', 'is_last' => true)); $context['last_choice_id'] = 4; }
/** * Sets up the context for showing a listing of registered members. * For the handlers in this file, it requires the view_mlist permission. * Accessed by ?action_memberlist. * @uses Memberlist template, main sub-template. * * @see Action_Controller::action_index() */ public function action_index() { global $scripturl, $txt, $modSettings, $context; // Make sure they can view the memberlist. isAllowedTo('view_mlist'); loadTemplate('Memberlist'); $context['sub_template'] = 'memberlist'; Template_Layers::getInstance()->add('mlsearch'); $context['listing_by'] = !empty($_GET['sa']) ? $_GET['sa'] : 'all'; // $subActions array format: // 'subaction' => array('label', 'function', 'is_selected') $subActions = array('all' => array($txt['view_all_members'], 'action_mlall', $context['listing_by'] == 'all'), 'search' => array($txt['mlist_search'], 'action_mlsearch', $context['listing_by'] == 'search')); // Set up the sort links. $context['sort_links'] = array(); foreach ($subActions as $act => $text) { $context['sort_links'][] = array('label' => $text[0], 'action' => $act, 'selected' => $text[2]); } $context['num_members'] = $modSettings['totalMembers']; // Set up the standard columns... $context['columns'] = array('online' => array('label' => $txt['status'], 'class' => 'status', 'sort' => array('down' => allowedTo('moderate_forum') ? 'IFNULL(lo.log_time, 1) ASC, real_name ASC' : 'CASE WHEN mem.show_online THEN IFNULL(lo.log_time, 1) ELSE 1 END ASC, real_name ASC', 'up' => allowedTo('moderate_forum') ? 'IFNULL(lo.log_time, 1) DESC, real_name DESC' : 'CASE WHEN mem.show_online THEN IFNULL(lo.log_time, 1) ELSE 1 END DESC, real_name DESC')), 'real_name' => array('label' => $txt['username'], 'class' => 'username', 'sort' => array('down' => 'mem.real_name DESC', 'up' => 'mem.real_name ASC')), 'email_address' => array('label' => $txt['email'], 'class' => 'email', 'sort' => array('down' => allowedTo('moderate_forum') ? 'mem.email_address DESC' : 'mem.hide_email DESC, mem.email_address DESC', 'up' => allowedTo('moderate_forum') ? 'mem.email_address ASC' : 'mem.hide_email ASC, mem.email_address ASC')), 'website_url' => array('label' => $txt['website'], 'class' => 'website', 'link_with' => 'website', 'sort' => array('down' => 'LENGTH(mem.website_url) > 0 ASC, IFNULL(mem.website_url, 1=1) DESC, mem.website_url DESC', 'up' => 'LENGTH(mem.website_url) > 0 DESC, IFNULL(mem.website_url, 1=1) ASC, mem.website_url ASC')), 'id_group' => array('label' => $txt['position'], 'class' => 'group', 'sort' => array('down' => 'IFNULL(mg.group_name, 1=1) DESC, mg.group_name DESC', 'up' => 'IFNULL(mg.group_name, 1=1) ASC, mg.group_name ASC')), 'date_registered' => array('label' => $txt['date_registered'], 'class' => 'date_registered', 'sort' => array('down' => 'mem.date_registered DESC', 'up' => 'mem.date_registered ASC')), 'posts' => array('label' => $txt['posts'], 'class' => 'posts', 'default_sort_rev' => true, 'sort' => array('down' => 'mem.posts DESC', 'up' => 'mem.posts ASC'))); // Add in any custom profile columns require_once SUBSDIR . '/Memberlist.subs.php'; if (ml_CustomProfile()) { $context['columns'] += $context['custom_profile_fields']['columns']; } // The template may appreciate how many columns it needs to display $context['colspan'] = 0; $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array(); foreach ($context['columns'] as $key => $column) { if (isset($context['disabled_fields'][$key]) || isset($column['link_with']) && isset($context['disabled_fields'][$column['link_with']])) { unset($context['columns'][$key]); continue; } $context['colspan'] += isset($column['colspan']) ? $column['colspan'] : 1; } $context['linktree'][] = array('url' => $scripturl . '?action=memberlist', 'name' => $txt['members_list']); $context['can_send_pm'] = allowedTo('pm_send'); // Build the memberlist button array. $context['memberlist_buttons'] = array('view_all_members' => array('text' => 'view_all_members', 'image' => 'mlist.png', 'lang' => true, 'url' => $scripturl . '?action=memberlist;sa=all', 'active' => true)); // Are there custom fields they can search? ml_findSearchableCustomFields(); // These are all the possible fields. $context['search_fields'] = array('name' => $txt['mlist_search_name'], 'email' => $txt['mlist_search_email'], 'website' => $txt['mlist_search_website'], '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'); // Allow mods to add additional buttons here call_integration_hook('integrate_memberlist_buttons'); if (!allowedTo('send_email_to_members')) { unset($context['columns']['email_address']); } if (isset($context['disabled_fields']['website'])) { unset($context['columns']['website']); } if (isset($context['disabled_fields']['posts'])) { unset($context['columns']['posts']); } // Jump to the sub action. if (isset($subActions[$context['listing_by']])) { $this->{$subActions[$context['listing_by']][1]}(); } else { $this->{$subActions['all'][1]}(); } }
/** * Called by index.php?action=findmember. * This function result is used as a popup for searching members. * * @deprecated since 1.0 * @uses sub template find_members of the Members template. */ public function action_findmember() { global $context, $scripturl, $user_info, $settings; checkSession('get'); // Load members template loadTemplate('Members'); loadTemplate('index'); Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'find_members'; if (isset($_REQUEST['search'])) { $context['last_search'] = Util::htmlspecialchars($_REQUEST['search'], ENT_QUOTES); } else { $_REQUEST['start'] = 0; } // Allow the user to pass the input to be added to to the box. $context['input_box_name'] = isset($_REQUEST['input']) && preg_match('~^[\\w-]+$~', $_REQUEST['input']) === 1 ? $_REQUEST['input'] : 'to'; // Take the delimiter over GET in case it's \n or something. $context['delimiter'] = isset($_REQUEST['delim']) ? $_REQUEST['delim'] == 'LB' ? "\n" : $_REQUEST['delim'] : ', '; $context['quote_results'] = !empty($_REQUEST['quote']); // List all the results. $context['results'] = array(); // Some buddy related settings ;) $context['show_buddies'] = !empty($user_info['buddies']); $context['buddy_search'] = isset($_REQUEST['buddies']); // If the user has done a search, well - search. if (isset($_REQUEST['search'])) { require_once SUBSDIR . '/Auth.subs.php'; $_REQUEST['search'] = Util::htmlspecialchars($_REQUEST['search'], ENT_QUOTES); $context['results'] = findMembers(array($_REQUEST['search']), true, $context['buddy_search']); $total_results = count($context['results']); $_REQUEST['start'] = (int) $_REQUEST['start']; // This is a bit hacky, but its defined in index template, and this is a popup $settings['page_index_template'] = array('base_link' => '<li class="linavPages"><a class="navPages" href="{base_link}" role="menuitem">%2$s</a></li>', 'previous_page' => '<span class="previous_page" role="menuitem">{prev_txt}</span>', 'current_page' => '<li class="linavPages"><strong class="current_page" role="menuitem">%1$s</strong></li>', 'next_page' => '<span class="next_page" role="menuitem">{next_txt}</span>', 'expand_pages' => '<li class="linavPages expand_pages" role="menuitem" {custom}> <a href="#">...</a> </li>', 'all' => '<li class="linavPages all_pages" role="menuitem">{all_txt}</li>'); $context['page_index'] = constructPageIndex($scripturl . '?action=findmember;search=' . $context['last_search'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';input=' . $context['input_box_name'] . ($context['quote_results'] ? ';quote=1' : '') . ($context['buddy_search'] ? ';buddies' : ''), $_REQUEST['start'], $total_results, 7); // Determine the navigation context $base_url = $scripturl . '?action=findmember;search=' . urlencode($context['last_search']) . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']) . ';' . $context['session_var'] . '=' . $context['session_id']; $context['links'] += array('prev' => $_REQUEST['start'] >= 7 ? $base_url . ';start=' . ($_REQUEST['start'] - 7) : '', 'next' => $_REQUEST['start'] + 7 < $total_results ? $base_url . ';start=' . ($_REQUEST['start'] + 7) : ''); $context['page_info'] = array('current_page' => $_REQUEST['start'] / 7 + 1, 'num_pages' => floor(($total_results - 1) / 7) + 1); $context['results'] = array_slice($context['results'], $_REQUEST['start'], 7); } }
/** * Shows a fatal error with a message stored in the language file. * * What it does: * - This function stops execution and displays an error message by key. * - uses the string with the error_message_key key. * - logs the error in the forum's default language while displaying the error * message in the user's language. * - uses Errors language file and applies the $sprintf information if specified. * - the information is logged if log is specified. * * @param string $error * @param string|boolean $log defaults to 'general' false will skip logging, true will use general * @param string[] $sprintf defaults to empty array() */ function fatal_lang_error($error, $log = 'general', $sprintf = array()) { global $txt, $language, $modSettings, $user_info, $context; static $fatal_error_called = false; // Try to load a theme if we don't have one. if (empty($context['theme_loaded']) && empty($fatal_error_called)) { $fatal_error_called = true; loadTheme(); } // If we have no theme stuff we can't have the language file... if (empty($context['theme_loaded'])) { die($error); } if (class_exists('Template_Layers')) { Template_Layers::getInstance()->isError(); } $reload_lang_file = true; // Log the error in the forum's language, but don't waste the time if we aren't logging if ($log || !empty($modSettings['enableErrorLogging']) && $modSettings['enableErrorLogging'] == 2) { loadLanguage('Errors', $language); $reload_lang_file = $language != $user_info['language']; $error_message = empty($sprintf) ? $txt[$error] : vsprintf($txt[$error], $sprintf); log_error($error_message, $log); } // Load the language file, only if it needs to be reloaded if ($reload_lang_file) { loadLanguage('Errors'); $error_message = empty($sprintf) ? $txt[$error] : vsprintf($txt[$error], $sprintf); } setup_fatal_error_context($error_message, $error); }
/** * Responds to an ajax button request, currently only for remove * * @uses generic_xml_buttons sub template */ public function action_index_api() { global $txt, $context, $user_info; loadTemplate('Xml'); // Remove any template layers that may have been created, this is XML! Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'generic_xml_buttons'; // No guests in here. if ($user_info['is_guest']) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['not_guests']); return; } // Theme administration, removal, choice, or installation... // Of all the actions we currently know only this $subActions = array('remove' => 'action_remove_api'); // Follow the sa or just go to administration. if (isset($_GET['sa']) && !empty($subActions[$_GET['sa']])) { $this->{$subActions[$_GET['sa']]}(); } else { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['error_sa_not_set']); return; } }
/** * Get admin information from the database. * Accessed by ?action=viewadminfile. */ public function action_viewadminfile() { global $modSettings; require_once SUBSDIR . '/AdminDebug.subs.php'; // Don't allow non-administrators. isAllowedTo('admin_forum'); setMemoryLimit('128M'); if (empty($_REQUEST['filename']) || !is_string($_REQUEST['filename'])) { fatal_lang_error('no_access', false); } $file = adminInfoFile($_REQUEST['filename']); // @todo Temp // Figure out if sesc is still being used. if (strpos($file['file_data'], ';sesc=') !== false) { $file['file_data'] = ' if (!(\'elkForum_sessionvar\' in window)) window.elkForum_sessionvar = \'sesc\'; ' . strtr($file['file_data'], array(';sesc=' => ';\' + window.elkForum_sessionvar + \'=')); } Template_Layers::getInstance()->removeAll(); // Lets make sure we aren't going to output anything nasty. @ob_end_clean(); if (!empty($modSettings['enableCompressedOutput'])) { ob_start('ob_gzhandler'); } else { ob_start(); } // Make sure they know what type of file we are. header('Content-Type: ' . $file['filetype']); echo $file['file_data']; obExit(false); }
/** * Who's online, and what are they doing? * This function prepares the who's online data for the Who template. * It requires the who_view permission. * It is enabled with the who_enabled setting. * It is accessed via ?action=who. * * @uses Who template, main sub-template * @uses Who language file. */ public function action_who() { global $context, $scripturl, $txt, $modSettings, $memberContext; // Permissions, permissions, permissions. isAllowedTo('who_view'); // You can't do anything if this is off. if (empty($modSettings['who_enabled'])) { fatal_lang_error('who_off', false); } // Load the 'Who' template. loadTemplate('Who'); loadLanguage('Who'); // Sort out... the column sorting. $sort_methods = array('user' => 'mem.real_name', 'time' => 'lo.log_time'); $show_methods = array('members' => '(lo.id_member != 0)', 'guests' => '(lo.id_member = 0)', 'all' => '1=1'); // Store the sort methods and the show types for use in the template. $context['sort_methods'] = array('user' => $txt['who_user'], 'time' => $txt['who_time']); $context['show_methods'] = array('all' => $txt['who_show_all'], 'members' => $txt['who_show_members_only'], 'guests' => $txt['who_show_guests_only']); // Can they see spiders too? if (!empty($modSettings['show_spider_online']) && ($modSettings['show_spider_online'] == 2 || allowedTo('admin_forum')) && !empty($modSettings['spider_name_cache'])) { $show_methods['spiders'] = '(lo.id_member = 0 AND lo.id_spider > 0)'; $show_methods['guests'] = '(lo.id_member = 0 AND lo.id_spider = 0)'; $context['show_methods']['spiders'] = $txt['who_show_spiders_only']; } elseif (empty($modSettings['show_spider_online']) && isset($_SESSION['who_online_filter']) && $_SESSION['who_online_filter'] == 'spiders') { unset($_SESSION['who_online_filter']); } // Does the user prefer a different sort direction? if (isset($_REQUEST['sort']) && isset($sort_methods[$_REQUEST['sort']])) { $context['sort_by'] = $_SESSION['who_online_sort_by'] = $_REQUEST['sort']; $sort_method = $sort_methods[$_REQUEST['sort']]; } elseif (isset($_SESSION['who_online_sort_by'])) { $context['sort_by'] = $_SESSION['who_online_sort_by']; $sort_method = $sort_methods[$_SESSION['who_online_sort_by']]; } else { $context['sort_by'] = $_SESSION['who_online_sort_by'] = 'time'; $sort_method = 'lo.log_time'; } $context['sort_direction'] = isset($_REQUEST['asc']) || isset($_REQUEST['sort_dir']) && $_REQUEST['sort_dir'] == 'asc' ? 'up' : 'down'; $conditions = array(); if (!allowedTo('moderate_forum')) { $conditions[] = '(IFNULL(mem.show_online, 1) = 1)'; } // Fallback to top filter? if (isset($_REQUEST['submit_top']) && isset($_REQUEST['show_top'])) { $_REQUEST['show'] = $_REQUEST['show_top']; } // Does the user wish to apply a filter? if (isset($_REQUEST['show']) && isset($show_methods[$_REQUEST['show']])) { $context['show_by'] = $_SESSION['who_online_filter'] = $_REQUEST['show']; $conditions[] = $show_methods[$_REQUEST['show']]; } elseif (isset($_SESSION['who_online_filter'])) { $context['show_by'] = $_SESSION['who_online_filter']; $conditions[] = $show_methods[$_SESSION['who_online_filter']]; } else { $context['show_by'] = $_SESSION['who_online_filter'] = 'all'; } require_once SUBSDIR . '/Members.subs.php'; $totalMembers = countMembersOnline($conditions); // Prepare some page index variables. $context['page_index'] = constructPageIndex($scripturl . '?action=who;sort=' . $context['sort_by'] . ($context['sort_direction'] == 'up' ? ';asc' : '') . ';show=' . $context['show_by'], $_REQUEST['start'], $totalMembers, $modSettings['defaultMaxMembers']); $context['start'] = $_REQUEST['start']; $context['sub_template'] = 'whos_online'; Template_Layers::getInstance()->add('whos_selection'); // Look for people online, provided they don't mind if you see they are. $members = onlineMembers($conditions, $sort_method, $context['sort_direction'], $context['start']); $context['members'] = array(); $member_ids = array(); $url_data = array(); foreach ($members as $row) { $actions = @unserialize($row['url']); if ($actions === false) { continue; } // Send the information to the template. $context['members'][$row['session']] = array('id' => $row['id_member'], 'ip' => allowedTo('moderate_forum') ? $row['ip'] : '', 'time' => standardTime($row['log_time'], true), 'html_time' => htmlTime($row['log_time']), 'timestamp' => forum_time(true, $row['log_time']), 'query' => $actions, 'is_hidden' => $row['show_online'] == 0, 'id_spider' => $row['id_spider'], 'color' => empty($row['online_color']) ? '' : $row['online_color']); $url_data[$row['session']] = array($row['url'], $row['id_member']); $member_ids[] = $row['id_member']; } // Load the user data for these members. loadMemberData($member_ids); // Load up the guest user. $memberContext[0] = array('id' => 0, 'name' => $txt['guest_title'], 'group' => $txt['guest_title'], 'href' => '', 'link' => $txt['guest_title'], 'email' => $txt['guest_title'], 'is_guest' => true); // Are we showing spiders? $spiderContext = array(); if (!empty($modSettings['show_spider_online']) && ($modSettings['show_spider_online'] == 2 || allowedTo('admin_forum')) && !empty($modSettings['spider_name_cache'])) { foreach (unserialize($modSettings['spider_name_cache']) as $id => $name) { $spiderContext[$id] = array('id' => 0, 'name' => $name, 'group' => $txt['spiders'], 'href' => '', 'link' => $name, 'email' => $name, 'is_guest' => true); } } require_once SUBSDIR . '/Who.subs.php'; $url_data = determineActions($url_data); // Setup the linktree and page title (do it down here because the language files are now loaded..) $context['page_title'] = $txt['who_title']; $context['linktree'][] = array('url' => $scripturl . '?action=who', 'name' => $txt['who_title']); // Put it in the context variables. foreach ($context['members'] as $i => $member) { if ($member['id'] != 0) { $member['id'] = loadMemberContext($member['id']) ? $member['id'] : 0; } // Keep the IP that came from the database. $memberContext[$member['id']]['ip'] = $member['ip']; $context['members'][$i]['action'] = isset($url_data[$i]) ? $url_data[$i] : $txt['who_hidden']; if ($member['id'] == 0 && isset($spiderContext[$member['id_spider']])) { $context['members'][$i] += $spiderContext[$member['id_spider']]; } else { $context['members'][$i] += $memberContext[$member['id']]; } } // Some people can't send personal messages... $context['can_send_pm'] = allowedTo('pm_send'); $context['can_send_email'] = allowedTo('send_email_to_members'); // Any profile fields disabled? $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array(); }
/** * The central part of the board - topic display. * * What it does: * - This function loads the posts in a topic up so they can be displayed. * - It uses the main sub template of the Display template. * - It requires a topic, and can go to the previous or next topic from it. * - It jumps to the correct post depending on a number/time/IS_MSG passed. * - It depends on the messages_per_page, defaultMaxMessages and enableAllMessages settings. * - It is accessed by ?topic=id_topic.START. */ public function action_display() { global $scripturl, $txt, $modSettings, $context, $settings; global $options, $user_info, $board_info, $topic, $board; global $attachments, $messages_request; // What are you gonna display if these are empty?! if (empty($topic)) { fatal_lang_error('no_board', false); } // Load the template loadTemplate('Display'); $context['sub_template'] = 'messages'; // And the topic functions require_once SUBSDIR . '/Topic.subs.php'; require_once SUBSDIR . '/Messages.subs.php'; // Not only does a prefetch make things slower for the server, but it makes it impossible to know if they read it. if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') { @ob_end_clean(); header('HTTP/1.1 403 Prefetch Forbidden'); die; } // How much are we sticking on each page? $context['messages_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages']; $template_layers = Template_Layers::getInstance(); $template_layers->addEnd('messages_informations'); $includeUnapproved = !$modSettings['postmod_active'] || allowedTo('approve_posts'); // Let's do some work on what to search index. if (count($_GET) > 2) { foreach ($_GET as $k => $v) { if (!in_array($k, array('topic', 'board', 'start', session_name()))) { $context['robot_no_index'] = true; } } } if (!empty($_REQUEST['start']) && (!is_numeric($_REQUEST['start']) || $_REQUEST['start'] % $context['messages_per_page'] != 0)) { $context['robot_no_index'] = true; } // Find the previous or next topic. Make a fuss if there are no more. if (isset($_REQUEST['prev_next']) && ($_REQUEST['prev_next'] == 'prev' || $_REQUEST['prev_next'] == 'next')) { // No use in calculating the next topic if there's only one. if ($board_info['num_topics'] > 1) { $includeStickies = !empty($modSettings['enableStickyTopics']); $topic = $_REQUEST['prev_next'] === 'prev' ? previousTopic($topic, $board, $user_info['id'], $includeUnapproved, $includeStickies) : nextTopic($topic, $board, $user_info['id'], $includeUnapproved, $includeStickies); $context['current_topic'] = $topic; } // Go to the newest message on this topic. $_REQUEST['start'] = 'new'; } // Add 1 to the number of views of this topic (except for robots). if (!$user_info['possibly_robot'] && (empty($_SESSION['last_read_topic']) || $_SESSION['last_read_topic'] != $topic)) { increaseViewCounter($topic); $_SESSION['last_read_topic'] = $topic; } $topic_selects = array(); $topic_tables = array(); $topic_parameters = array('topic' => $topic, 'member' => $user_info['id'], 'board' => (int) $board); // Allow addons to add additional details to the topic query call_integration_hook('integrate_topic_query', array(&$topic_selects, &$topic_tables, &$topic_parameters)); // Load the topic details $topicinfo = getTopicInfo($topic_parameters, 'all', $topic_selects, $topic_tables); if (empty($topicinfo)) { fatal_lang_error('not_a_topic', false); } // Is this a moved topic that we are redirecting to? if (!empty($topicinfo['id_redirect_topic']) && !isset($_GET['noredir'])) { markTopicsRead(array($user_info['id'], $topic, $topicinfo['id_last_msg'], 0), $topicinfo['new_from'] !== 0); redirectexit('topic=' . $topicinfo['id_redirect_topic'] . '.0;redirfrom=' . $topicinfo['id_topic']); } $context['real_num_replies'] = $context['num_replies'] = $topicinfo['num_replies']; $context['topic_first_message'] = $topicinfo['id_first_msg']; $context['topic_last_message'] = $topicinfo['id_last_msg']; $context['topic_unwatched'] = isset($topicinfo['unwatched']) ? $topicinfo['unwatched'] : 0; if (isset($_GET['redirfrom'])) { $redir_topics = topicsList(array((int) $_GET['redirfrom'])); if (!empty($redir_topics[(int) $_GET['redirfrom']])) { $context['topic_redirected_from'] = $redir_topics[(int) $_GET['redirfrom']]; $context['topic_redirected_from']['redir_href'] = $scripturl . '?topic=' . $context['topic_redirected_from']['id_topic'] . '.0;noredir'; } } // Add up unapproved replies to get real number of replies... if ($modSettings['postmod_active'] && allowedTo('approve_posts')) { $context['real_num_replies'] += $topicinfo['unapproved_posts'] - ($topicinfo['approved'] ? 0 : 1); } // If this topic was derived from another, set the followup details if (!empty($topicinfo['derived_from'])) { require_once SUBSDIR . '/FollowUps.subs.php'; $context['topic_derived_from'] = topicStartedHere($topic, $includeUnapproved); } // If this topic has unapproved posts, we need to work out how many posts the user can see, for page indexing. if (!$includeUnapproved && $topicinfo['unapproved_posts'] && !$user_info['is_guest']) { $myUnapprovedPosts = unapprovedPosts($topic, $user_info['id']); $context['total_visible_posts'] = $context['num_replies'] + $myUnapprovedPosts + ($topicinfo['approved'] ? 1 : 0); } elseif ($user_info['is_guest']) { $context['total_visible_posts'] = $context['num_replies'] + ($topicinfo['approved'] ? 1 : 0); } else { $context['total_visible_posts'] = $context['num_replies'] + $topicinfo['unapproved_posts'] + ($topicinfo['approved'] ? 1 : 0); } // When was the last time this topic was replied to? Should we warn them about it? if (!empty($modSettings['oldTopicDays'])) { $mgsOptions = basicMessageInfo($topicinfo['id_last_msg'], true); $context['oldTopicError'] = $mgsOptions['poster_time'] + $modSettings['oldTopicDays'] * 86400 < time() && empty($topicinfo['is_sticky']); } else { $context['oldTopicError'] = false; } // The start isn't a number; it's information about what to do, where to go. if (!is_numeric($_REQUEST['start'])) { // Redirect to the page and post with new messages, originally by Omar Bazavilvazo. if ($_REQUEST['start'] == 'new') { // Guests automatically go to the last post. if ($user_info['is_guest']) { $context['start_from'] = $context['total_visible_posts'] - 1; $_REQUEST['start'] = $context['start_from']; } else { // Fall through to the next if statement. $_REQUEST['start'] = 'msg' . $topicinfo['new_from']; } } // Start from a certain time index, not a message. if (substr($_REQUEST['start'], 0, 4) == 'from') { $timestamp = (int) substr($_REQUEST['start'], 4); if ($timestamp === 0) { $_REQUEST['start'] = 0; } else { // Find the number of messages posted before said time... $context['start_from'] = countNewPosts($topic, $topicinfo, $timestamp); $_REQUEST['start'] = $context['start_from']; } } elseif (substr($_REQUEST['start'], 0, 3) == 'msg') { $virtual_msg = (int) substr($_REQUEST['start'], 3); if (!$topicinfo['unapproved_posts'] && $virtual_msg >= $topicinfo['id_last_msg']) { $context['start_from'] = $context['total_visible_posts'] - 1; } elseif (!$topicinfo['unapproved_posts'] && $virtual_msg <= $topicinfo['id_first_msg']) { $context['start_from'] = 0; } else { $only_approved = $modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts'); $context['start_from'] = countMessagesBefore($topic, $virtual_msg, false, $only_approved, !$user_info['is_guest']); } // We need to reverse the start as well in this case. $_REQUEST['start'] = $context['start_from']; } } // Mark the mention as read if requested if (isset($_REQUEST['mentionread']) && !empty($virtual_msg)) { require_once CONTROLLERDIR . '/Mentions.controller.php'; $mentions = new Mentions_Controller(); $mentions->setData(array('id_mention' => $_REQUEST['item'], 'mark' => $_REQUEST['mark'])); $mentions->action_markread(); } // Create a previous next string if the selected theme has it as a selected option. if ($modSettings['enablePreviousNext']) { $context['links'] += array('go_prev' => $scripturl . '?topic=' . $topic . '.0;prev_next=prev#new', 'go_next' => $scripturl . '?topic=' . $topic . '.0;prev_next=next#new'); } // Derived from, set the link back if (!empty($context['topic_derived_from'])) { $context['links']['derived_from'] = $scripturl . '?msg=' . $context['topic_derived_from']['derived_from']; } // Check if spellchecking is both enabled and actually working. (for quick reply.) $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new'); if ($context['show_spellchecking']) { loadJavascriptFile('spellcheck.js', array('defer' => true)); } // Do we need to show the visual verification image? $context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1); if ($context['require_verification']) { require_once SUBSDIR . '/VerificationControls.class.php'; $verificationOptions = array('id' => 'post'); $context['require_verification'] = create_control_verification($verificationOptions); $context['visual_verification_id'] = $verificationOptions['id']; } // Are we showing signatures - or disabled fields? $context['signature_enabled'] = substr($modSettings['signature_settings'], 0, 1) == 1; $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array(); // Censor the title... censorText($topicinfo['subject']); $context['page_title'] = $topicinfo['subject']; // Is this topic sticky, or can it even be? $topicinfo['is_sticky'] = empty($modSettings['enableStickyTopics']) ? '0' : $topicinfo['is_sticky']; // Allow addons access to the topicinfo array call_integration_hook('integrate_display_topic', array($topicinfo)); // Default this topic to not marked for notifications... of course... $context['is_marked_notify'] = false; // Did we report a post to a moderator just now? $context['report_sent'] = isset($_GET['reportsent']); if ($context['report_sent']) { $template_layers->add('report_sent'); } // Let's get nosey, who is viewing this topic? if (!empty($settings['display_who_viewing'])) { require_once SUBSDIR . '/Who.subs.php'; formatViewers($topic, 'topic'); } // If all is set, but not allowed... just unset it. $can_show_all = !empty($modSettings['enableAllMessages']) && $context['total_visible_posts'] > $context['messages_per_page'] && $context['total_visible_posts'] < $modSettings['enableAllMessages']; if (isset($_REQUEST['all']) && !$can_show_all) { unset($_REQUEST['all']); } elseif (isset($_REQUEST['all'])) { $_REQUEST['start'] = -1; } // Construct the page index, allowing for the .START method... $context['page_index'] = constructPageIndex($scripturl . '?topic=' . $topic . '.%1$d', $_REQUEST['start'], $context['total_visible_posts'], $context['messages_per_page'], true, array('all' => $can_show_all, 'all_selected' => isset($_REQUEST['all']))); $context['start'] = $_REQUEST['start']; // This is information about which page is current, and which page we're on - in case you don't like the constructed page index. (again, wireles..) $context['page_info'] = array('current_page' => $_REQUEST['start'] / $context['messages_per_page'] + 1, 'num_pages' => floor(($context['total_visible_posts'] - 1) / $context['messages_per_page']) + 1); // Figure out all the link to the next/prev $context['links'] += array('prev' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] - $context['messages_per_page']) : '', 'next' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] + $context['messages_per_page']) : ''); // If they are viewing all the posts, show all the posts, otherwise limit the number. if ($can_show_all && isset($_REQUEST['all'])) { // No limit! (actually, there is a limit, but...) $context['messages_per_page'] = -1; // Set start back to 0... $_REQUEST['start'] = 0; } // Build the link tree. $context['linktree'][] = array('url' => $scripturl . '?topic=' . $topic . '.0', 'name' => $topicinfo['subject']); // Build a list of this board's moderators. $context['moderators'] =& $board_info['moderators']; $context['link_moderators'] = array(); // Information about the current topic... $context['is_locked'] = $topicinfo['locked']; $context['is_sticky'] = $topicinfo['is_sticky']; $context['is_very_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicVeryPosts']; $context['is_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicPosts']; $context['is_approved'] = $topicinfo['approved']; $context['is_poll'] = $topicinfo['id_poll'] > 0 && !empty($modSettings['pollMode']) && allowedTo('poll_view'); determineTopicClass($context); // Did this user start the topic or not? $context['user']['started'] = $user_info['id'] == $topicinfo['id_member_started'] && !$user_info['is_guest']; $context['topic_starter_id'] = $topicinfo['id_member_started']; // Set the topic's information for the template. $context['subject'] = $topicinfo['subject']; $context['num_views'] = $topicinfo['num_views']; $context['num_views_text'] = $context['num_views'] == 1 ? $txt['read_one_time'] : sprintf($txt['read_many_times'], $context['num_views']); $context['mark_unread_time'] = !empty($virtual_msg) ? $virtual_msg : $topicinfo['new_from']; // Set a canonical URL for this page. $context['canonical_url'] = $scripturl . '?topic=' . $topic . '.' . $context['start']; // For quick reply we need a response prefix in the default forum language. $context['response_prefix'] = response_prefix(); // If we want to show event information in the topic, prepare the data. if (allowedTo('calendar_view') && !empty($modSettings['cal_showInTopic']) && !empty($modSettings['cal_enabled'])) { // We need events details and all that jazz require_once SUBSDIR . '/Calendar.subs.php'; // First, try create a better time format, ignoring the "time" elements. if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) { $date_string = $user_info['time_format']; } else { $date_string = $matches[0]; } // Get event information for this topic. $events = eventInfoForTopic($topic); $context['linked_calendar_events'] = array(); foreach ($events as $event) { // Prepare the dates for being formatted. $start_date = sscanf($event['start_date'], '%04d-%02d-%02d'); $start_date = mktime(12, 0, 0, $start_date[1], $start_date[2], $start_date[0]); $end_date = sscanf($event['end_date'], '%04d-%02d-%02d'); $end_date = mktime(12, 0, 0, $end_date[1], $end_date[2], $end_date[0]); $context['linked_calendar_events'][] = array('id' => $event['id_event'], 'title' => $event['title'], 'can_edit' => allowedTo('calendar_edit_any') || $event['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own'), 'modify_href' => $scripturl . '?action=post;msg=' . $topicinfo['id_first_msg'] . ';topic=' . $topic . '.0;calendar;eventid=' . $event['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], 'can_export' => allowedTo('calendar_edit_any') || $event['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own'), 'export_href' => $scripturl . '?action=calendar;sa=ical;eventid=' . $event['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], 'start_date' => standardTime($start_date, $date_string, 'none'), 'start_timestamp' => $start_date, 'end_date' => standardTime($end_date, $date_string, 'none'), 'end_timestamp' => $end_date, 'is_last' => false); } if (!empty($context['linked_calendar_events'])) { $context['linked_calendar_events'][count($context['linked_calendar_events']) - 1]['is_last'] = true; $template_layers->add('display_calendar'); } } // Create the poll info if it exists. if ($context['is_poll']) { $template_layers->add('display_poll'); require_once SUBSDIR . '/Poll.subs.php'; loadPollContext($topicinfo['id_poll']); // Build the poll moderation button array. $context['poll_buttons'] = array('vote' => array('test' => 'allow_return_vote', 'text' => 'poll_return_vote', 'image' => 'poll_options.png', 'lang' => true, 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start']), 'results' => array('test' => 'allow_poll_view', 'text' => 'poll_results', 'image' => 'poll_results.png', 'lang' => true, 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start'] . ';viewresults'), 'change_vote' => array('test' => 'allow_change_vote', 'text' => 'poll_change_vote', 'image' => 'poll_change_vote.png', 'lang' => true, 'url' => $scripturl . '?action=poll;sa=vote;topic=' . $context['current_topic'] . '.' . $context['start'] . ';poll=' . $context['poll']['id'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'lock' => array('test' => 'allow_lock_poll', 'text' => !$context['poll']['is_locked'] ? 'poll_lock' : 'poll_unlock', 'image' => 'poll_lock.png', 'lang' => true, 'url' => $scripturl . '?action=lockvoting;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'edit' => array('test' => 'allow_edit_poll', 'text' => 'poll_edit', 'image' => 'poll_edit.png', 'lang' => true, 'url' => $scripturl . '?action=editpoll;topic=' . $context['current_topic'] . '.' . $context['start']), 'remove_poll' => array('test' => 'can_remove_poll', 'text' => 'poll_remove', 'image' => 'admin_remove_poll.png', 'lang' => true, 'custom' => 'onclick="return confirm(\'' . $txt['poll_remove_warn'] . '\');"', 'url' => $scripturl . '?action=poll;sa=remove;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id'])); // Allow mods to add additional buttons here call_integration_hook('integrate_poll_buttons'); } // Calculate the fastest way to get the messages! $ascending = true; $start = $_REQUEST['start']; $limit = $context['messages_per_page']; $firstIndex = 0; if ($start >= $context['total_visible_posts'] / 2 && $context['messages_per_page'] != -1) { $ascending = !$ascending; $limit = $context['total_visible_posts'] <= $start + $limit ? $context['total_visible_posts'] - $start : $limit; $start = $context['total_visible_posts'] <= $start + $limit ? 0 : $context['total_visible_posts'] - $start - $limit; $firstIndex = $limit - 1; } // Taking care of member specific settings $limit_settings = array('messages_per_page' => $context['messages_per_page'], 'start' => $start, 'offset' => $limit); // Get each post and poster in this topic. $topic_details = getTopicsPostsAndPoster($topic, $limit_settings, $ascending); $messages = $topic_details['messages']; $posters = array_unique($topic_details['all_posters']); $all_posters = $topic_details['all_posters']; unset($topic_details); call_integration_hook('integrate_display_message_list', array(&$messages, &$posters)); // Guests can't mark topics read or for notifications, just can't sorry. if (!$user_info['is_guest'] && !empty($messages)) { $mark_at_msg = max($messages); if ($mark_at_msg >= $topicinfo['id_last_msg']) { $mark_at_msg = $modSettings['maxMsgID']; } if ($mark_at_msg >= $topicinfo['new_from']) { markTopicsRead(array($user_info['id'], $topic, $mark_at_msg, $topicinfo['unwatched']), $topicinfo['new_from'] !== 0); } updateReadNotificationsFor($topic, $board); // Have we recently cached the number of new topics in this board, and it's still a lot? if (isset($_REQUEST['topicseen']) && isset($_SESSION['topicseen_cache'][$board]) && $_SESSION['topicseen_cache'][$board] > 5) { $_SESSION['topicseen_cache'][$board]--; } elseif (isset($_REQUEST['topicseen'])) { // Use the mark read tables... and the last visit to figure out if this should be read or not. $numNewTopics = getUnreadCountSince($board, empty($_SESSION['id_msg_last_visit']) ? 0 : $_SESSION['id_msg_last_visit']); // If there're no real new topics in this board, mark the board as seen. if (empty($numNewTopics)) { $_REQUEST['boardseen'] = true; } else { $_SESSION['topicseen_cache'][$board] = $numNewTopics; } } elseif (isset($_SESSION['topicseen_cache'][$board])) { $_SESSION['topicseen_cache'][$board]--; } // Mark board as seen if we came using last post link from BoardIndex. (or other places...) if (isset($_REQUEST['boardseen'])) { require_once SUBSDIR . '/Boards.subs.php'; markBoardsRead($board, false, false); } } $attachments = array(); // If there _are_ messages here... (probably an error otherwise :!) if (!empty($messages)) { require_once SUBSDIR . '/Attachments.subs.php'; // Fetch attachments. $includeUnapproved = !$modSettings['postmod_active'] || allowedTo('approve_posts'); if (!empty($modSettings['attachmentEnable']) && allowedTo('view_attachments')) { $attachments = getAttachments($messages, $includeUnapproved, 'filter_accessible_attachment', $all_posters); } $msg_parameters = array('message_list' => $messages, 'new_from' => $topicinfo['new_from']); $msg_selects = array(); $msg_tables = array(); call_integration_hook('integrate_message_query', array(&$msg_selects, &$msg_tables, &$msg_parameters)); // What? It's not like it *couldn't* be only guests in this topic... if (!empty($posters)) { loadMemberData($posters); } // Load in the likes for this group of messages if (!empty($modSettings['likes_enabled'])) { require_once SUBSDIR . '/Likes.subs.php'; $context['likes'] = loadLikes($messages, true); // ajax controller for likes loadJavascriptFile('like_posts.js', array('defer' => true)); loadLanguage('Errors'); // Initiate likes and the tooltips for likes addInlineJavascript(' $(document).ready(function () { var likePostInstance = likePosts.prototype.init({ oTxt: ({ btnText : ' . JavaScriptEscape($txt['ok_uppercase']) . ', likeHeadingError : ' . JavaScriptEscape($txt['like_heading_error']) . ', error_occurred : ' . JavaScriptEscape($txt['error_occurred']) . ' }), }); $(".like_button, .unlike_button").SiteTooltip({ hoverIntent: { sensitivity: 10, interval: 150, timeout: 50 } }); });', true); } $messages_request = loadMessageRequest($msg_selects, $msg_tables, $msg_parameters); if (!empty($modSettings['enableFollowup'])) { require_once SUBSDIR . '/FollowUps.subs.php'; $context['follow_ups'] = followupTopics($messages, $includeUnapproved); } // Go to the last message if the given time is beyond the time of the last message. if (isset($context['start_from']) && $context['start_from'] >= $topicinfo['num_replies']) { $context['start_from'] = $topicinfo['num_replies']; } // Since the anchor information is needed on the top of the page we load these variables beforehand. $context['first_message'] = isset($messages[$firstIndex]) ? $messages[$firstIndex] : $messages[0]; $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['start_from']; } else { $messages_request = false; $context['first_message'] = 0; $context['first_new_message'] = false; } $context['jump_to'] = array('label' => addslashes(un_htmlspecialchars($txt['jump_to'])), 'board_name' => htmlspecialchars(strtr(strip_tags($board_info['name']), array('&' => '&')), ENT_COMPAT, 'UTF-8'), 'child_level' => $board_info['child_level']); // Set the callback. (do you REALIZE how much memory all the messages would take?!?) // This will be called from the template. $context['get_message'] = array($this, 'prepareDisplayContext_callback'); // Now set all the wonderful, wonderful permissions... like moderation ones... $common_permissions = array('can_approve' => 'approve_posts', 'can_ban' => 'manage_bans', 'can_sticky' => 'make_sticky', 'can_merge' => 'merge_any', 'can_split' => 'split_any', 'calendar_post' => 'calendar_post', 'can_mark_notify' => 'mark_any_notify', 'can_send_topic' => 'send_topic', 'can_send_pm' => 'pm_send', 'can_send_email' => 'send_email_to_members', 'can_report_moderator' => 'report_any', 'can_moderate_forum' => 'moderate_forum', 'can_issue_warning' => 'issue_warning', 'can_restore_topic' => 'move_any', 'can_restore_msg' => 'move_any'); foreach ($common_permissions as $contextual => $perm) { $context[$contextual] = allowedTo($perm); } // Permissions with _any/_own versions. $context[YYY] => ZZZ_any/_own. $anyown_permissions = array('can_move' => 'move', 'can_lock' => 'lock', 'can_delete' => 'remove', 'can_add_poll' => 'poll_add', 'can_remove_poll' => 'poll_remove', 'can_reply' => 'post_reply', 'can_reply_unapproved' => 'post_unapproved_replies'); foreach ($anyown_permissions as $contextual => $perm) { $context[$contextual] = allowedTo($perm . '_any') || $context['user']['started'] && allowedTo($perm . '_own'); } // Cleanup all the permissions with extra stuff... $context['can_mark_notify'] &= !$context['user']['is_guest']; $context['can_sticky'] &= !empty($modSettings['enableStickyTopics']); $context['calendar_post'] &= !empty($modSettings['cal_enabled']) && (allowedTo('modify_any') || $context['user']['started'] && allowedTo('modify_own')); $context['can_add_poll'] &= !empty($modSettings['pollMode']) && $topicinfo['id_poll'] <= 0; $context['can_remove_poll'] &= !empty($modSettings['pollMode']) && $topicinfo['id_poll'] > 0; $context['can_reply'] &= empty($topicinfo['locked']) || allowedTo('moderate_board'); $context['can_reply_unapproved'] &= $modSettings['postmod_active'] && (empty($topicinfo['locked']) || allowedTo('moderate_board')); $context['can_issue_warning'] &= in_array('w', $context['admin_features']) && !empty($modSettings['warning_enable']); // Handle approval flags... $context['can_reply_approved'] = $context['can_reply']; $context['can_reply'] |= $context['can_reply_unapproved']; $context['can_quote'] = $context['can_reply'] && (empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']))); $context['can_mark_unread'] = !$user_info['is_guest'] && $settings['show_mark_read']; $context['can_unwatch'] = !$user_info['is_guest'] && $modSettings['enable_unwatch']; $context['can_send_topic'] = (!$modSettings['postmod_active'] || $topicinfo['approved']) && allowedTo('send_topic'); $context['can_print'] = empty($modSettings['disable_print_topic']); // Start this off for quick moderation - it will be or'd for each post. $context['can_remove_post'] = allowedTo('delete_any') || allowedTo('delete_replies') && $context['user']['started']; // Can restore topic? That's if the topic is in the recycle board and has a previous restore state. $context['can_restore_topic'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_board']); $context['can_restore_msg'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_topic']); $context['can_follow_up'] = !empty($modSettings['enableFollowup']) && boardsallowedto('post_new') !== array(); // Check if the draft functions are enabled and that they have permission to use them (for quick reply.) $context['drafts_save'] = !empty($modSettings['drafts_enabled']) && !empty($modSettings['drafts_post_enabled']) && allowedTo('post_draft') && $context['can_reply']; $context['drafts_autosave'] = !empty($context['drafts_save']) && !empty($modSettings['drafts_autosave_enabled']) && allowedTo('post_autosave_draft'); if (!empty($context['drafts_save'])) { loadLanguage('Drafts'); } if (!empty($context['drafts_autosave']) && empty($options['use_editor_quick_reply'])) { loadJavascriptFile('drafts.js'); } if (!empty($modSettings['mentions_enabled'])) { $context['mentions_enabled'] = true; // Just using the plain text quick reply and not the editor if (empty($options['use_editor_quick_reply'])) { loadJavascriptFile(array('jquery.atwho.js', 'jquery.caret.min.js', 'mentioning.js')); } loadCSSFile('jquery.atwho.css'); addInlineJavascript(' $(document).ready(function () { for (var i = 0, count = all_elk_mentions.length; i < count; i++) all_elk_mentions[i].oMention = new elk_mentions(all_elk_mentions[i].oOptions); });'); } // Load up the Quick ModifyTopic and Quick Reply scripts loadJavascriptFile('topic.js'); // Auto video embeding enabled? if (!empty($modSettings['enableVideoEmbeding'])) { addInlineJavascript(' $(document).ready(function() { $().linkifyvideo(oEmbedtext); });'); } // Load up the "double post" sequencing magic. if (!empty($options['display_quick_reply'])) { checkSubmitOnce('register'); $context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : ''; $context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : ''; if (!empty($options['use_editor_quick_reply']) && $context['can_reply']) { // Needed for the editor and message icons. require_once SUBSDIR . '/Editor.subs.php'; // Now create the editor. $editorOptions = array('id' => 'message', 'value' => '', 'labels' => array('post_button' => $txt['post']), 'height' => '250px', 'width' => '100%', 'preview_type' => 0); create_control_richedit($editorOptions); $context['attached'] = ''; $context['make_poll'] = isset($_REQUEST['poll']); // Message icons - customized icons are off? $context['icons'] = getMessageIcons($board); if (!empty($context['icons'])) { $context['icons'][count($context['icons']) - 1]['is_last'] = true; } } } addJavascriptVar(array('notification_topic_notice' => $context['is_marked_notify'] ? $txt['notification_disable_topic'] : $txt['notification_enable_topic']), true); if ($context['can_send_topic']) { addJavascriptVar(array('sendtopic_cancel' => $txt['modify_cancel'], 'sendtopic_back' => $txt['back'], 'sendtopic_close' => $txt['find_close'], 'sendtopic_error' => $txt['send_error_occurred'], 'required_field' => $txt['require_field']), true); } // Build the normal button array. $context['normal_buttons'] = array('reply' => array('test' => 'can_reply', 'text' => 'reply', 'image' => 'reply.png', 'lang' => true, 'url' => $scripturl . '?action=post;topic=' . $context['current_topic'] . '.' . $context['start'] . ';last_msg=' . $context['topic_last_message'], 'active' => true), 'notify' => array('test' => 'can_mark_notify', 'text' => $context['is_marked_notify'] ? 'unnotify' : 'notify', 'image' => ($context['is_marked_notify'] ? 'un' : '') . 'notify.png', 'lang' => true, 'custom' => 'onclick="return notifyButton(this);"', 'url' => $scripturl . '?action=notify;sa=' . ($context['is_marked_notify'] ? 'off' : 'on') . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'mark_unread' => array('test' => 'can_mark_unread', 'text' => 'mark_unread', 'image' => 'markunread.png', 'lang' => true, 'url' => $scripturl . '?action=markasread;sa=topic;t=' . $context['mark_unread_time'] . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'unwatch' => array('test' => 'can_unwatch', 'text' => ($context['topic_unwatched'] ? '' : 'un') . 'watch', 'image' => ($context['topic_unwatched'] ? '' : 'un') . 'watched.png', 'lang' => true, 'custom' => 'onclick="return unwatchButton(this);"', 'url' => $scripturl . '?action=unwatchtopic;topic=' . $context['current_topic'] . '.' . $context['start'] . ';sa=' . ($context['topic_unwatched'] ? 'off' : 'on') . ';' . $context['session_var'] . '=' . $context['session_id']), 'send' => array('test' => 'can_send_topic', 'text' => 'send_topic', 'image' => 'sendtopic.png', 'lang' => true, 'url' => $scripturl . '?action=emailuser;sa=sendtopic;topic=' . $context['current_topic'] . '.0', 'custom' => 'onclick="return sendtopicOverlayDiv(this.href, \'' . $txt['send_topic'] . '\');"'), 'print' => array('test' => 'can_print', 'text' => 'print', 'image' => 'print.png', 'lang' => true, 'custom' => 'rel="nofollow"', 'class' => 'new_win', 'url' => $scripturl . '?action=topic;sa=printpage;topic=' . $context['current_topic'] . '.0')); // Build the mod button array $context['mod_buttons'] = array('move' => array('test' => 'can_move', 'text' => 'move_topic', 'image' => 'admin_move.png', 'lang' => true, 'url' => $scripturl . '?action=movetopic;current_board=' . $context['current_board'] . ';topic=' . $context['current_topic'] . '.0'), 'delete' => array('test' => 'can_delete', 'text' => 'remove_topic', 'image' => 'admin_rem.png', 'lang' => true, 'custom' => 'onclick="return confirm(\'' . $txt['are_sure_remove_topic'] . '\');"', 'url' => $scripturl . '?action=removetopic2;topic=' . $context['current_topic'] . '.0;' . $context['session_var'] . '=' . $context['session_id']), 'lock' => array('test' => 'can_lock', 'text' => empty($context['is_locked']) ? 'set_lock' : 'set_unlock', 'image' => 'admin_lock.png', 'lang' => true, 'url' => $scripturl . '?action=topic;sa=lock;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'sticky' => array('test' => 'can_sticky', 'text' => empty($context['is_sticky']) ? 'set_sticky' : 'set_nonsticky', 'image' => 'admin_sticky.png', 'lang' => true, 'url' => $scripturl . '?action=topic;sa=sticky;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'merge' => array('test' => 'can_merge', 'text' => 'merge', 'image' => 'merge.png', 'lang' => true, 'url' => $scripturl . '?action=mergetopics;board=' . $context['current_board'] . '.0;from=' . $context['current_topic']), 'calendar' => array('test' => 'calendar_post', 'text' => 'calendar_link', 'image' => 'linktocal.png', 'lang' => true, 'url' => $scripturl . '?action=post;calendar;msg=' . $context['topic_first_message'] . ';topic=' . $context['current_topic'] . '.0')); // Restore topic. eh? No monkey business. if ($context['can_restore_topic']) { $context['mod_buttons'][] = array('text' => 'restore_topic', 'image' => '', 'lang' => true, 'url' => $scripturl . '?action=restoretopic;topics=' . $context['current_topic'] . ';' . $context['session_var'] . '=' . $context['session_id']); } if ($context['can_reply'] && !empty($options['display_quick_reply'])) { $template_layers->add('quickreply'); } $template_layers->add('pages_and_buttons'); // Allow adding new buttons easily. call_integration_hook('integrate_display_buttons'); call_integration_hook('integrate_mod_buttons'); }
/** * Like action_sendtopic, but done via ajax from an API request * @uses Xml Template generic_xml_buttons sub template */ public function action_sendtopic_api() { global $topic, $modSettings, $txt, $context, $scripturl; loadTemplate('Xml'); Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'generic_xml_buttons'; if (empty($_POST['send'])) { die; } // We need at least a topic... go away if you don't have one. // Guests can't mark things. if (empty($topic)) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['not_a_topic']); return; } // Is the session valid? if (checkSession('post', '', false)) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'url' => $scripturl . '?action=emailuser;sa=sendtopic;topic=' . $topic . '.0'); return; } require_once SUBSDIR . '/Topic.subs.php'; $row = getTopicInfo($topic, 'message'); if (empty($row)) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['not_a_topic']); return; } // Can't send topic if its unapproved and using post moderation. if ($modSettings['postmod_active'] && !$row['approved']) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => $txt['not_approved_topic']); return; } $is_spam = spamProtection('sendtopic', false); if ($is_spam !== false) { loadLanguage('Errors'); $context['xml_data'] = array('error' => 1, 'text' => sprintf($txt['sendtopic_WaitTime_broken'], $is_spam)); return; } // Censor the subject.... censorText($row['subject']); $result = $this->_sendTopic($row); if ($result !== true) { loadLanguage('Errors'); $context['xml_data'] = $result; return; } $context['xml_data'] = array('text' => $txt['topic_sent']); }
/** * This action handler method displays and allows to change avatar settings. * * - Called by index.php?action=admin;area=manageattachments;sa=avatars. * * @uses 'avatars' sub-template. */ public function action_avatarSettings_display() { global $txt, $context, $scripturl; // Initialize the form $this->_initAvatarSettingsForm(); $config_vars = $this->_avatarSettings->settings(); // Saving avatar settings? if (isset($_GET['save'])) { checkSession(); call_integration_hook('integrate_save_avatar_settings'); // Disable if invalid values would result if (isset($_POST['custom_avatar_enabled']) && $_POST['custom_avatar_enabled'] == 1 && (empty($_POST['custom_avatar_dir']) || empty($_POST['custom_avatar_url']))) { $_POST['custom_avatar_enabled'] = 0; } Settings_Form::save_db($config_vars); redirectexit('action=admin;area=manageattachments;sa=avatars'); } // Attempt to figure out if the admin is trying to break things. $context['settings_save_onclick'] = 'return document.getElementById(\'custom_avatar_enabled\').value == 1 && (document.getElementById(\'custom_avatar_dir\').value == \'\' || document.getElementById(\'custom_avatar_url\').value == \'\') ? confirm(\'' . $txt['custom_avatar_check_empty'] . '\') : true;'; // We need this for the in-line permissions createToken('admin-mp'); // Prepare the context. $context['post_url'] = $scripturl . '?action=admin;area=manageattachments;save;sa=avatars'; Settings_Form::prepare_db($config_vars); // Add a layer for the javascript. Template_Layers::getInstance()->add('avatar_settings'); $context['sub_template'] = 'show_settings'; }
/** * Show a warning notice sent to a user. */ public function action_showNotice() { global $txt, $context; // What notice have they asked to view $id_notice = isset($_GET['nid']) ? (int) $_GET['nid'] : 0; $notice = moderatorNotice($id_notice); // legit? if (empty($notice) || !$context['can_moderate_boards']) { fatal_lang_error('no_access', false); } list($context['notice_body'], $context['notice_subject']) = $notice; $context['notice_body'] = parse_bbc($context['notice_body'], false); $context['page_title'] = $txt['show_notice']; $context['sub_template'] = 'show_notice'; Template_Layers::getInstance()->removeAll(); loadTemplate('ModerationCenter'); }
/** * Allow the admin to reset permissions on files. */ public function action_perms() { global $context, $txt, $modSettings, $package_ftp; // Let's try and be good, yes? checkSession('get'); // If we're restoring permissions this is just a pass through really. if (isset($_GET['restore'])) { create_chmod_control(array(), array(), true); fatal_lang_error('no_access', false); } // This is a time and memory eating ... setMemoryLimit('128M'); @set_time_limit(600); // Load up some FTP stuff. create_chmod_control(); if (empty($package_ftp) && !isset($_POST['skip_ftp'])) { require_once SUBSDIR . '/FtpConnection.class.php'; $ftp = new Ftp_Connection(null); list($username, $detect_path, $found_path) = $ftp->detect_path(BOARDDIR); $context['package_ftp'] = array('server' => isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost', 'port' => isset($modSettings['package_port']) ? $modSettings['package_port'] : '21', 'username' => empty($username) ? isset($modSettings['package_username']) ? $modSettings['package_username'] : '' : $username, 'path' => $detect_path, 'form_elements_only' => true); } else { $context['ftp_connected'] = true; } // Define the template. $context['page_title'] = $txt['package_file_perms']; $context['sub_template'] = 'file_permissions'; // Define what files we're interested in, as a tree. $context['file_tree'] = array(strtr(BOARDDIR, array('\\' => '/')) => array('type' => 'dir', 'contents' => array('agreement.txt' => array('type' => 'file', 'writable_on' => 'standard'), 'Settings.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'Settings_bak.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'attachments' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'avatars' => array('type' => 'dir', 'writable_on' => 'standard'), 'cache' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'custom_avatar_dir' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'smileys' => array('type' => 'dir_recursive', 'writable_on' => 'standard'), 'sources' => array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'), 'themes' => array('type' => 'dir_recursive', 'writable_on' => 'standard', 'contents' => array('default' => array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))))), 'packages' => array('type' => 'dir', 'writable_on' => 'standard', 'contents' => array('temp' => array('type' => 'dir'), 'backup' => array('type' => 'dir'), 'installed.list' => array('type' => 'file', 'writable_on' => 'standard')))))); // Directories that can move. if (substr(SOURCEDIR, 0, strlen(BOARDDIR)) != BOARDDIR) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['sources']); $context['file_tree'][strtr(SOURCEDIR, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'); } // Moved the cache? if (substr(CACHEDIR, 0, strlen(BOARDDIR)) != BOARDDIR) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['cache']); $context['file_tree'][strtr(CACHEDIR, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => false, 'writable_on' => 'restrictive'); } // Are we using multiple attachment directories? if (!empty($modSettings['currentAttachmentUploadDir'])) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['attachments']); if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // @todo Should we suggest non-current directories be read only? foreach ($modSettings['attachmentUploadDir'] as $dir) { $context['file_tree'][strtr($dir, array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } } elseif (substr($modSettings['attachmentUploadDir'], 0, strlen(BOARDDIR)) != BOARDDIR) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['attachments']); $context['file_tree'][strtr($modSettings['attachmentUploadDir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } if (substr($modSettings['smileys_dir'], 0, strlen(BOARDDIR)) != BOARDDIR) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['smileys']); $context['file_tree'][strtr($modSettings['smileys_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'writable_on' => 'standard'); } if (substr($modSettings['avatar_directory'], 0, strlen(BOARDDIR)) != BOARDDIR) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['avatars']); $context['file_tree'][strtr($modSettings['avatar_directory'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'standard'); } if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen(BOARDDIR)) != BOARDDIR) { unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['custom_avatar_dir']); $context['file_tree'][strtr($modSettings['custom_avatar_dir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } // Load up any custom themes. require_once SUBSDIR . '/Themes.subs.php'; $themes = getCustomThemes(); foreach ($themes as $id => $theme) { // Skip the default if ($id == 1) { continue; } if (substr(strtolower(strtr($theme['theme_dir'], array('\\' => '/'))), 0, strlen(BOARDDIR) + 7) === strtolower(strtr(BOARDDIR, array('\\' => '/')) . '/themes')) { $context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['themes']['contents'][substr($theme['theme_dir'], strlen(BOARDDIR) + 8)] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } else { $context['file_tree'][strtr($theme['theme_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } } // If we're submitting then let's move on to another function to keep things cleaner.. if (isset($_POST['action_changes'])) { return $this->action_perms_save(); } $context['look_for'] = array(); // Are we looking for a particular tree - normally an expansion? if (!empty($_REQUEST['find'])) { $context['look_for'][] = base64_decode($_REQUEST['find']); } // Only that tree? $context['only_find'] = isset($_GET['xml']) && !empty($_REQUEST['onlyfind']) ? $_REQUEST['onlyfind'] : ''; if ($context['only_find']) { $context['look_for'][] = $context['only_find']; } // Have we got a load of back-catalogue trees to expand from a submit etc? if (!empty($_GET['back_look'])) { $potententialTrees = unserialize(base64_decode($_GET['back_look'])); foreach ($potententialTrees as $tree) { $context['look_for'][] = $tree; } } // ... maybe posted? if (!empty($_POST['back_look'])) { $context['only_find'] = array_merge($context['only_find'], $_POST['back_look']); } $context['back_look_data'] = base64_encode(serialize(array_slice($context['look_for'], 0, 15))); // Are we finding more files than first thought? $context['file_offset'] = !empty($_REQUEST['fileoffset']) ? (int) $_REQUEST['fileoffset'] : 0; // Don't list more than this many files in a directory. $context['file_limit'] = 150; // How many levels shall we show? $context['default_level'] = empty($context['only_find']) ? 2 : 25; // This will be used if we end up catching XML data. $context['xml_data'] = array('roots' => array('identifier' => 'root', 'children' => array(array('value' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])))), 'folders' => array('identifier' => 'folder', 'children' => array())); foreach ($context['file_tree'] as $path => $data) { // Run this directory. if (file_exists($path) && (empty($context['only_find']) || substr($context['only_find'], 0, strlen($path)) == $path)) { // Get the first level down only. fetchPerms__recursive($path, $context['file_tree'][$path], 1); $context['file_tree'][$path]['perms'] = array('chmod' => @is_writable($path), 'perms' => @fileperms($path)); } else { unset($context['file_tree'][$path]); } } // Is this actually xml? if (isset($_GET['xml'])) { loadTemplate('Xml'); $context['sub_template'] = 'generic_xml'; Template_Layers::getInstance()->removeAll(); } }
/** * Initializes the portal, outputs all the blocks as needed * * @param boolean $standalone */ function sportal_init($standalone = false) { global $context, $scripturl, $modSettings, $settings, $maintenance, $sportal_version; $sportal_version = '1.0.0 Beta 1'; if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach') { return; } if ((isset($_REQUEST['xml']) || isset($_REQUEST['api'])) && (isset($_REQUEST['action']) && $_REQUEST['action'] !== 'shoutbox')) { return; } // Not running standalone then we need to load in some template information if (!$standalone) { // Load the portal css and the default css if its not yet loaded. loadCSSFile('portal.css'); // rtl css as well? if (!empty($context['right_to_left'])) { loadCSSFile('portal_rtl.css'); } if (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], array('admin'))) { loadLanguage('SPortalAdmin', sp_languageSelect('SPortalAdmin')); } if (!isset($settings['sp_images_url'])) { if (file_exists($settings['theme_dir'] . '/images/sp')) { $settings['sp_images_url'] = $settings['theme_url'] . '/images/sp'; } else { $settings['sp_images_url'] = $settings['default_theme_url'] . '/images/sp'; } } } // Portal not enabled, or mobile, or debug, or maintenance, or .... then bow out now if (!empty($modSettings['sp_disableMobile']) && empty($_GET['page']) && empty($_GET['article']) || !empty($settings['disable_sp']) || empty($modSettings['sp_portal_mode']) || (!empty($modSettings['sp_maintenance']) || !empty($maintenance)) && !allowedTo('admin_forum') || isset($_GET['debug']) || empty($modSettings['allow_guestAccess']) && $context['user']['is_guest']) { $context['disable_sp'] = true; if ($standalone) { $get_string = ''; foreach ($_GET as $get_var => $get_value) { $get_string .= $get_var . (!empty($get_value) ? '=' . $get_value : '') . ';'; } redirectexit(substr($get_string, 0, -1)); } return; } // Not standalone means we need to load some portal specific information in to context if (!$standalone) { require_once SUBSDIR . '/PortalBlocks.subs.php'; // Not running via ssi then we need to get SSI for its functions if (ELK !== 'SSI') { require_once BOARDDIR . '/SSI.php'; } // Portal specific templates and language loadTemplate('Portal'); loadLanguage('SPortal', sp_languageSelect('SPortal')); if (!empty($modSettings['sp_maintenance']) && !allowedTo('sp_admin')) { $modSettings['sp_portal_mode'] = 0; } if (empty($modSettings['sp_standalone_url'])) { $modSettings['sp_standalone_url'] = ''; } if ($modSettings['sp_portal_mode'] == 3) { $context += array('portal_url' => $modSettings['sp_standalone_url'], 'page_title' => $context['forum_name']); } else { $context += array('portal_url' => $scripturl); } if ($modSettings['sp_portal_mode'] == 1) { $context['linktree'][0] = array('url' => $scripturl . '?action=forum', 'name' => $context['forum_name']); } if (!empty($context['linktree']) && $modSettings['sp_portal_mode'] == 1) { foreach ($context['linktree'] as $key => $tree) { if (strpos($tree['url'], '#c') !== false && strpos($tree['url'], 'action=forum#c') === false) { $context['linktree'][$key]['url'] = str_replace('#c', '?action=forum#c', $tree['url']); } } } } else { $_GET['action'] = 'portal'; } // Load the headers if necessary. sportal_init_headers(); // Load permissions sportal_load_permissions(); // Play with our blocks $context['standalone'] = $standalone; sportal_load_blocks(); $context['SPortal']['on_portal'] = getShowInfo(0, 'portal', ''); if (!Template_Layers::getInstance()->hasLayers(true) && !in_array('portal', Template_Layers::getInstance()->getLayers())) { Template_Layers::getInstance()->add('portal'); } }
/** * When checking via ajax * * - Clears the templates * - Returns a json response to the page */ private function EntropyResponse() { global $context; // Clear the templates $template_layers = Template_Layers::getInstance(); $template_layers->removeAll(); // Make room for ajax loadTemplate('Json'); $context['sub_template'] = 'send_json'; // Provide the response $context['json_data'] = $this->_pwentropy_response; }
/** * Integration hook integrate_buffer, called from ob_exit via call_integration_buffer * Used to modify the output buffer before its sent, here we add in our copyright * * @param string $tourniquet */ function sp_integrate_buffer($tourniquet) { global $sportal_version, $context, $modSettings, $forum_version; $fix = str_replace('{version}', $sportal_version, '<a href="http://www.simpleportal.net/" target="_blank" class="new_win">SimplePortal {version} © 2008-2014</a>'); if (ELK == 'SSI' && empty($context['standalone']) || !Template_Layers::getInstance()->hasLayers() || empty($modSettings['sp_portal_mode']) || strpos($tourniquet, $fix) !== false) { return $tourniquet; } // Don't display copyright for things like SSI. if (!isset($forum_version)) { return ''; } // Append our cp notice at the end of the line $finds = array(sprintf('powered by %1$s</a> | ', $forum_version)); $replaces = array(sprintf('powered by %1$s</a> | ', $forum_version) . $fix . ' | '); $tourniquet = str_replace($finds, $replaces, $tourniquet); // Can't find it for some reason so we add it at the end if (strpos($tourniquet, $fix) === false) { $fix = '<div style="text-align: center; width: 100%; font-size: x-small; margin-bottom: 5px;">' . $fix . '</div></body></html>'; $tourniquet = preg_replace('~</body>\\s*</html>~', $fix, $tourniquet); } return $tourniquet; }