/** * Find the ID of the "current" member * * @param boolean $fatal if the function ends in a fatal error in case of problems (default true) * @param boolean $reload_id if true the already set value is ignored (default false) * * @return mixed and integer if no error, false in case of problems if $fatal is false */ function currentMemberID($fatal = true, $reload_id = false) { global $user_info; static $memID; // If we already know who we're dealing with if (isset($memID) && !$reload_id) { return $memID; } // Did we get the user by name... if (isset($_REQUEST['user'])) { $memberResult = loadMemberData($_REQUEST['user'], true, 'profile'); } elseif (!empty($_REQUEST['u'])) { $memberResult = loadMemberData((int) $_REQUEST['u'], false, 'profile'); } else { $memberResult = loadMemberData($user_info['id'], false, 'profile'); } // Check if loadMemberData() has returned a valid result. if (!is_array($memberResult)) { // Members only... is_not_guest('', $fatal); if ($fatal) { fatal_lang_error('not_a_user', false); } else { return false; } } // If all went well, we have a valid member ID! list($memID) = $memberResult; return $memID; }
function teknoromisidebarsag() { global $boarddir, $modSettings, $txt, $context; require_once $boarddir . '/SSI.php'; echo '</td></tr></tbody></table>'; if (!empty($modSettings['sideright']) && empty($context['current_action'])) { echo '<td valign="top" id="upshrinkRightBarTD"> <div id="upshrinkRightBar" style="width:', $modSettings['siderightwidth'] ? $modSettings['siderightwidth'] : '200px', '; margin-right:4px; overflow:auto;">'; if (!empty($modSettings['sideright1'])) { echo '<div class="cat_bar"><h3 class="catbg">' . $modSettings['righthtmlbaslik'] . '</h3></div>'; echo '' . $modSettings['sideright1'] . ''; } if (!empty($modSettings['siderightphp'])) { echo '<div class="cat_bar"><h3 class="catbg">' . $modSettings['rightphpbaslik'] . '</h3></div>'; eval($modSettings['siderightphp']); } if (!empty($modSettings['siderighthaberetkin'])) { $array = ssi_boardNews($modSettings['siderighthaber'], $modSettings['siderightsay'], null, 1000, 'array'); echo '<div class="cat_bar"> <h3 class="catbg">', $modSettings['rbaslik'], '</h3> </div>'; global $memberContext; foreach ($array as $news) { loadMemberData($news['poster']['id']); loadMemberContext($news['poster']['id']); echo '<div class="sidehaber"> <div class="sideBaslik"> ', $news['icon'], ' <h3><a href="', $news['href'], '">', $news['subject'], '</a></h3> </div> <div class="snrj"> ', $memberContext[$news['poster']['id']]['avatar']['image'], ' <p>', $txt['by'], '', $news['poster']['link'], '</p> </div> </div><hr/>'; } } echo '</div> </td> <td valign="top"> <button type="button" onclick="rightPanel.toggle();" id="teknoright"></button> </td>'; } echo ' </tr></tbody></table>'; }
/** * @param $memID int id_member * * fetch all likes received by the given user and display them * part of the profile -> show content area. */ function LikesByUser($memID) { global $context, $user_info, $scripturl, $memberContext, $txt, $modSettings, $options; if ($memID != $user_info['id']) { isAllowedTo('can_view_ratings'); } // let us use the same value as for topics per page here. $perpage = empty($modSettings['disableCustomPerPage']) && !empty($options['topics_per_page']) ? $options['topics_per_page'] : $modSettings['defaultMaxTopics']; $out = $_GET['sa'] === 'likesout'; // display likes *given* instead of received ones $is_owner = $user_info['id'] == $memID; // we are the owner of this profile, this is important for proper formatting (you/yours etc.) $boards_like_see = boardsAllowedTo('like_see'); // respect permissions $start = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; if (!($user_info['is_admin'] || allowedTo('moderate_forum'))) { // admins and global mods can see everything $bq = ' AND b.id_board IN({array_int:boards})'; } else { $bq = ''; } $q = $out ? 'l.id_user = {int:id_user}' : 'l.id_receiver = {int:id_user}'; $request = smf_db_query('SELECT count(l.id_msg) FROM {db_prefix}likes AS l INNER JOIN {db_prefix}messages AS m ON (m.id_msg = l.id_msg) INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) WHERE ' . $q . ' AND {query_see_board}' . $bq, array('id_user' => $memID, 'boards' => $boards_like_see)); list($context['total_likes']) = mysql_fetch_row($request); mysql_free_result($request); $request = smf_db_query('SELECT m.subject, m.id_topic, l.id_user, l.id_receiver, l.updated, l.id_msg, l.rtype, mfirst.subject AS first_subject, SUBSTRING(m.body, 1, 150) AS body FROM {db_prefix}likes AS l INNER JOIN {db_prefix}messages AS m ON (m.id_msg = l.id_msg) INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) INNER JOIN {db_prefix}messages AS mfirst ON (mfirst.id_msg = t.id_first_msg) INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) WHERE ' . $q . ' AND {query_see_board} ' . $bq . ' ORDER BY l.id_like DESC LIMIT {int:startwith}, {int:perpage}', array('id_user' => $memID, 'startwith' => $start, 'perpage' => $perpage, 'boards' => $boards_like_see)); $context['results_count'] = 0; $context['likes'] = array(); $context['displaymode'] = $out ? true : false; $context['pages'] = ''; if ($context['total_likes'] > $perpage) { $context['pages'] = constructPageIndex($scripturl . '?action=profile;area=showposts;sa=' . $_GET['sa'] . ';u=' . trim($memID), $start, $context['total_likes'], $perpage); } $users = array(); while ($row = mysql_fetch_assoc($request)) { $context['results_count']++; $thref = URL::topic($row['id_topic'], $row['first_subject'], 0); $phref = URL::topic($row['id_topic'], $row['subject'], 0, false, '.msg' . $row['id_msg'], '#msg' . $row['id_msg']); $users[] = $out ? $row['id_receiver'] : $row['id_user']; $context['likes'][] = array('id_user' => $out ? $row['id_receiver'] : $row['id_user'], 'time' => timeformat($row['updated']), 'topic' => array('href' => $thref, 'link' => '<a href="' . $thref . '">' . $row['first_subject'] . '</a>', 'subject' => $row['first_subject']), 'post' => array('href' => $phref, 'link' => '<a href="' . $phref . '">' . $row['subject'] . '</a>', 'subject' => $row['subject'], 'id' => $row['id_msg']), 'rtype' => $row['rtype'], 'teaser' => strip_tags(preg_replace('~[[\\/\\!]*?[^\\[\\]]*?]~si', '', $row['body'])) . '...', 'morelink' => URL::parse('?msg=' . $row['id_msg'] . ';perma')); } loadMemberData(array_unique($users)); foreach ($context['likes'] as &$like) { loadMemberContext($like['id_user']); $like['member'] =& $memberContext[$like['id_user']]; $like['text'] = $out ? $is_owner ? sprintf($txt['liked_a_post'], $is_owner ? $txt['you_liker'] : $memberContext[$memID]['name'], $memberContext[$like['id_user']]['link'], $like['post']['href'], $like['topic']['link'], $modSettings['ratings'][$like['rtype']]['text']) : sprintf($txt['liked_a_post'], $is_owner ? $txt['you_liker'] : $memberContext[$memID]['name'], $memberContext[$like['id_user']]['link'], $like['post']['href'], $like['topic']['link'], $modSettings['ratings'][$like['rtype']]['text']) : ($is_owner ? sprintf($txt['liked_your_post'], $like['id_user'] == $user_info['id'] ? $txt['you_liker'] : $like['member']['link'], $like['post']['href'], $like['topic']['link'], $modSettings['ratings'][$like['rtype']]['text']) : sprintf($txt['liked_a_post'], $like['id_user'] == $user_info['id'] ? $txt['you_liker'] : $like['member']['link'], $memberContext[$memID]['name'], $like['post']['href'], $like['topic']['link'], $modSettings['ratings'][$like['rtype']]['text'])); } mysql_free_result($request); EoS_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'ratings/profile_display'); }
/** * Allows to edit Personal Message Settings. * * @uses Profile.php * @uses Profile-Modify.php * @uses Profile template. * @uses Profile language file. */ function MessageSettings() { global $txt, $user_settings, $user_info, $context, $sourcedir, $smcFunc; global $scripturl, $profile_vars, $cur_profile, $user_profile; // Need this for the display. require_once $sourcedir . '/Profile.php'; require_once $sourcedir . '/Profile-Modify.php'; // We want them to submit back to here. $context['profile_custom_submit_url'] = $scripturl . '?action=pm;sa=settings;save'; loadMemberData($user_info['id'], false, 'profile'); $cur_profile = $user_profile[$user_info['id']]; loadLanguage('Profile'); loadTemplate('Profile'); $context['page_title'] = $txt['pm_settings']; $context['user']['is_owner'] = true; $context['id_member'] = $user_info['id']; $context['require_password'] = false; $context['menu_item_selected'] = 'settings'; $context['submit_button_text'] = $txt['pm_settings']; $context['profile_header_text'] = $txt['personal_messages']; // Add our position to the linktree. $context['linktree'][] = array('url' => $scripturl . '?action=pm;sa=settings', 'name' => $txt['pm_settings']); // Are they saving? if (isset($_REQUEST['save'])) { checkSession('post'); // Mimic what profile would do. $_POST = htmltrim__recursive($_POST); $_POST = htmlspecialchars__recursive($_POST); // Save the fields. saveProfileFields(); if (!empty($profile_vars)) { updateMemberData($user_info['id'], $profile_vars); } } // Load up the fields. pmprefs($user_info['id']); }
function template_main() { global $scripturl, $context, $txt, $settings, $modSettings, $user_profile, $memberContext; // Check if the user is an Admin $manage_staff = allowedTo('admin_forum'); $bbc_check = function_exists('parse_bbc'); echo '<div class="tborder">'; echo '<br />'; $totalcols = 1; if ($modSettings['smfstaff_showavatar']) { $totalcols++; } if ($modSettings['smfstaff_showlastactive']) { $totalcols++; } if ($modSettings['smfstaff_showdateregistered']) { $totalcols++; } if ($modSettings['smfstaff_showcontactinfo']) { $totalcols++; } foreach ($context['smfstaff_groups'] as $id => $data) { $count_users = count(@$context['smfstaff_users'][$data['id']]); if ($count_users == 0) { continue; } echo '<table border="0" cellspacing="0" cellpadding="2" width="100%">'; echo '<tr>'; echo '<td class="catbg2" width="30%">', $data['name'], '</td>'; if ($modSettings['smfstaff_showavatar']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_avatar'], '</td>'; } if ($modSettings['smfstaff_showlastactive']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_lastactive'], '</td>'; } if ($modSettings['smfstaff_showdateregistered']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_dateregistered'], '</td>'; } if ($modSettings['smfstaff_showcontactinfo']) { echo '<td class="catbg2" width="30%">', $txt['smfstaff_contact'], '</td>'; } echo '</tr>'; foreach (@$context['smfstaff_users'][$data['id']] as $id => $row2) { echo '<tr>'; echo '<td class="windowbg"><a href="' . $scripturl . '?action=profile;u=' . $row2['ID_MEMBER'] . '"><font color="' . $data['color'] . '">' . $row2['realName'] . '</font></a></td>'; if ($modSettings['smfstaff_showavatar']) { echo '<td class="windowbg">'; // Display the users avatar $memCommID = $row2['ID_MEMBER']; loadMemberData($memCommID); loadMemberContext($memCommID); echo $memberContext[$memCommID]['avatar']['image']; echo '</td>'; } if ($modSettings['smfstaff_showlastactive']) { echo '<td class="windowbg">' . timeformat($row2['lastLogin']) . '</td>'; } if ($modSettings['smfstaff_showdateregistered']) { echo '<td class="windowbg">' . timeformat($row2['dateRegistered']) . '</td>'; } if ($modSettings['smfstaff_showcontactinfo']) { echo '<td class="windowbg">'; //Send email row if ($row2['hideEmail'] == 0) { echo '<a href="mailto:', $row2['emailAddress'], '"><img src="' . $settings['images_url'] . '/email_sm.gif" alt="email" /></a> '; } if ($row2['ICQ'] != '') { echo '<a href="http://www.icq.com/whitepages/about_me.php?uin=' . $row2['ICQ'] . '" target="_blank"><img src="http://status.icq.com/online.gif?img=5&icq=' . $row2['ICQ'] . '" alt="' . $row2['ICQ'] . '" width="18" height="18" border="0" /></a> '; } if ($row2['AIM'] != '') { echo '<a href="aim:goim?screenname=' . urlencode(strtr($row2['AIM'], array(' ' => '%20'))) . '&message=' . $txt['aim_default_message'] . '"><img src="' . $settings['images_url'] . '/aim.gif" alt="' . $row2['AIM'] . '" border="0" /></a> '; } if ($row2['YIM'] != '') { echo '<a href="http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($row2['YIM']) . '"><img src="http://opi.yahoo.com/online?u=' . urlencode($row2['YIM']) . '&m=g&t=0" alt="' . $row2['YIM'] . '" border="0" /></a> '; } if ($row2['MSN'] != '') { echo '<a href="http://members.msn.com/' . $row2['MSN'] . '" target="_blank"><img src="' . $settings['images_url'] . '/msntalk.gif" alt="' . $row2['MSN'] . '" border="0" /></a> '; } // Send PM row echo '<a href="' . $scripturl . '?action=pm;sa=send;u=' . $row2['ID_MEMBER'] . '">' . $txt['smfstaff_sendpm'] . '</a>'; echo '</td>'; } // End Contact Information echo '</tr>'; } // If they are allowed to manage the staff page give them the option if ($manage_staff) { echo '<tr> <td align="center" colspan="', $totalcols, '" class="windowbg"> <a href="' . $scripturl . '?action=staff;sa=catdown&id=' . $data['id'] . '">' . $txt['smfstaff_down'] . '</a> | <a href="' . $scripturl . '?action=staff;sa=catup&id=' . $data['id'] . '">' . $txt['smfstaff_up'] . '</a> | <a href="' . $scripturl . '?action=staff;sa=delete&id=' . $data['id'] . ';ret">' . $txt['smfstaff_delgroup'] . '</a></td></tr>'; } echo '</table>'; // Seperate the groups from the local mods. echo '<br />'; } // End of Main staff listing if ($modSettings['smfstaff_showlocalmods']) { $localcount = count($context['smfstaff_localmods']); if ($localcount > 0) { echo '<table border="0" cellspacing="0" cellpadding="2" width="100%">'; echo '<tr>'; echo '<td class="catbg2" width="25%">', $txt['smfstaff_local'], '</td>'; if ($modSettings['smfstaff_showavatar']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_avatar'], '</td>'; } if ($modSettings['smfstaff_showlastactive']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_lastactive'], '</td>'; } if ($modSettings['smfstaff_showdateregistered']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_dateregistered'], '</td>'; } echo '<td class="catbg2" width="25%">', $txt['smfstaff_forums'], '</td>'; if ($modSettings['smfstaff_showcontactinfo']) { echo '<td class="catbg2" width="25%">', $txt['smfstaff_contact'], '</td>'; } echo '</tr>'; foreach ($context['smfstaff_localmods'] as $id => $data) { echo '<tr>'; echo '<td class="windowbg"><a href="', $scripturl, '?action=profile;u=', $data['id'], '">', $data['realName'], '</a></td>'; if ($modSettings['smfstaff_showavatar']) { echo '<td class="windowbg">'; //Display the users avatar $memCommID = $data['id']; loadMemberData($memCommID); loadMemberContext($memCommID); echo $memberContext[$memCommID]['avatar']['image']; echo '</td>'; } if ($modSettings['smfstaff_showlastactive']) { echo '<td class="windowbg">', timeformat($data['lastLogin']), '</td>'; } if ($modSettings['smfstaff_showdateregistered']) { echo '<td class="windowbg">', timeformat($data['dateRegistered']), '</td>'; } echo '<td class="windowbg">', $data['forums'], '</td>'; if ($modSettings['smfstaff_showcontactinfo']) { echo '<td class="windowbg" align="center">'; // Send email row if ($data['hideEmail'] == 0) { echo '<a href="mailto:', $data['emailAddress'], '"><img src="', $settings['images_url'], '/email_sm.gif" alt="email" /></a> '; } if ($data['ICQ'] != '') { echo '<a href="http://www.icq.com/whitepages/about_me.php?uin=', $data['ICQ'], '" target="_blank"><img src="http://status.icq.com/online.gif?img=5&icq=', $data['ICQ'], '" alt="', $data['ICQ'], '" width="18" height="18" border="0" /></a> '; } if ($data['AIM'] != '') { echo '<a href="aim:goim?screenname=', urlencode(strtr($data['AIM'], array(' ' => '%20'))), '&message=', $txt['aim_default_message'], '"><img src="', $settings['images_url'], '/aim.gif" alt="', $data['AIM'], '" border="0" /></a> '; } if ($data['YIM'] != '') { echo '<a href="http://edit.yahoo.com/config/send_webmesg?.target=', urlencode($data['YIM']), '"><img src="http://opi.yahoo.com/online?u=', urlencode($data['YIM']), '&m=g&t=0" alt="', $data['YIM'], '" border="0" /></a> '; } if ($data['MSN'] != '') { echo '<a href="http://members.msn.com/', $data['MSN'], '" target="_blank"><img src="', $settings['images_url'], '/msntalk.gif" alt="', $data['MSN'], '" border="0" /></a> '; } //Send PM row echo '<a href="', $scripturl, '?action=pm;sa=send;u=', $data['id'], '">', $txt['smfstaff_sendpm'], '</a>'; echo '</td>'; } // End smfstaff_showcontactinfo echo '</tr>'; } echo '</table>'; } // End of local mods count } // End of modSettings local mods check // If they can manage the staff page show them the link if ($manage_staff) { echo '<div align="center"><a href="', $scripturl, '?action=staff;sa=admin">', $txt['smfstaff_admin'], '</a></div><br />'; } echo '</div>'; // The Copyright is required to remain or contact me to purchase link removal. echo '<div align="center"><a href="http://www.smfhacks.com" target="blank">SMF Staff</a></div>'; }
/** * Creates a new ticket or reply in the database. * * This function handles all of the creation of posts and tickets within SimpleDesk, even with respect to managing tickets spawned * from forum topics being moved. New tickets' contents as well as replies to tickets generally hold the same format. * * All three parameters are by <b>reference</b> meaning they WILL be updated if things change. Note that this function * is not validating that they are sensible values; it is up to the calling function to ascertain that. * * @param array &$msgOptions A hash array by reference, containing details of the post you wish to add. * <ul> * <li>id: Not required on input (and is ignored) - and will be overwritten with the new message id when the function completes.</li> * <li>body: Required string, the principle body content of the message to post. Assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and preparsecode)</li> * <li>smileys_enabled: Optional, boolean denoting whether smileys should be active on this post; defaults to false</li> * <li>time: Optional, timestamp of the post. If omitted, time() will be used instead (for "now" based on server clock)</li> * <li>modified: Optional, hash array containing items relating to modification (if 'modified' key exists, all of these should be set) * <ul> * <li> time: Unsigned int timestamp of the change</li> * <li> name: String; user name of the user making the change; if omitted, modified will be ignored</li> * <li> id: Unsigned int user id of the user making the change; if not provided, id MUST be. If id isn't, or it doesn't exist, modified will be ignored entirely</li> * </ul> * </li> * <li> attachments: Optional, array of attachment ids that need attaching to this message; if omitted no changes will occur * </ul> * * @param array &$ticketOptions A hash array by reference, containing details of the ticket as a whole. * <ul> * <li>id: Required if replying to a ticket, 0 if a new ticket (will default to 0 if not specified)</li> * <li>mark_as_read: Optional boolean, whether to mark the ticket as read by the person posting it ($posterOptions['id'] is required to use this)</li> * <li>mark_as_read_proxy: Optional integer for proxy tickets, if $ticketOptions['mark_as_read'] is true. Mark the ticket as read for the user with this id.</li> * <li>subject: Semi-optional string with the new subject in; required for a new ticket, ignored if adding a reply. If set, assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and strtr)</li> * <li>private: Semi-optional boolean with ticket privacy (true = private); required for a new ticket, ignored if adding a reply.</li> * <li>status: Integer to denote new status of the ticket, defaults to TICKET_STATUS_NEW. Calling function to determine new status.</li> * <li>urgency: Semi-optional integer with the ticket urgency; required for a new ticket, ignored if adding a reply. If not stated on a new ticket, TICKET_URGENCY_LOW will be used.</li> * <li>assigned: Optional integer of user id, used to create a ticket with assignment, ignored if not a new ticket.</li> * <li>dept: Required if creating a new ticket, to indicate which department the ticket should belong to.</li> * </ul> * * @param array &$posterOptions A hash array by reference, containing details of the person the reply is written by. * <ul> * <li>id: User id to credit the post to. Uses 0 if not specified.</li> * <li>ip: IP address the post came from. Uses the current user's IP address if not specified.</li> * <li>name: Name to credit against the post. If not specified, and a user id was supplied, look that up in the member table, otherwise just use 'Guest'.</li> * <li>email: Email address to list against the post. If not specified, and a user id was supplied, look that up in the member table, otherwise just use ''.</li> * </ul> * @return bool True on success, false on failure. * @since 1.0 */ function shd_create_ticket_post(&$msgOptions, &$ticketOptions, &$posterOptions) { global $user_info, $txt, $modSettings, $smcFunc, $context, $user_profile; // Clean them incoming vars up good 'n' proper $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; $msgOptions['time'] = empty($msgOptions['time']) ? time() : (int) $msgOptions['time']; $ticketOptions['id'] = empty($ticketOptions['id']) ? 0 : (int) $ticketOptions['id']; $ticketOptions['private'] = !empty($ticketOptions['private']); $ticketOptions['urgency'] = empty($ticketOptions['urgency']) ? TICKET_URGENCY_LOW : (int) $ticketOptions['urgency']; $ticketOptions['assigned'] = empty($ticketOptions['assigned']) ? 0 : (int) $ticketOptions['assigned']; $ticketOptions['status'] = empty($ticketOptions['status']) ? TICKET_STATUS_NEW : (int) $ticketOptions['status']; $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; $posterOptions['ip'] = empty($posterOptions['ip']) ? $user_info['ip'] : $posterOptions['ip']; // If nothing was filled in as name/e-mail address, try the member table. if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || empty($posterOptions['email']) && !empty($posterOptions['id'])) { if (empty($posterOptions['id'])) { $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } elseif ($posterOptions['id'] != $user_info['id']) { if (empty($user_profile[$posterOptions['id']])) { loadMemberData($posterOptions['id'], false, 'minimal'); } // Couldn't find the current poster? if (empty($user_profile[$posterOptions['id']])) { trigger_error('shd_create_ticket_post(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } else { $posterOptions['name'] = $user_profile[$posterOptions['id']]['real_name']; $posterOptions['email'] = $user_profile[$posterOptions['id']]['email_address']; } } else { $posterOptions['name'] = $user_info['name']; $posterOptions['email'] = $user_info['email']; } } // Is there modified name data? (For topic->ticket) $modified = true; if (isset($msgOptions['modified'])) { $msgOptions['modified']['time'] = empty($msgOptions['modified']['time']) ? 0 : (int) $msgOptions['modified']['time']; $msgOptions['modified']['id'] = empty($msgOptions['modified']['id']) ? 0 : (int) $msgOptions['modified']['id']; $msgOptions['modified']['name'] = empty($msgOptions['modified']['name']) ? '' : $msgOptions['modified']['name']; $cancel = false; if (empty($msgOptions['modified']['time']) || empty($msgOptions['modified']['name']) && empty($msgOptions['modified']['id'])) { $modified = false; } if ($modified) { // So they have a time, and name or id (or even both). Let's see what we need. if (empty($msgOptions['modified']['name'])) { loadMemberData($msgOptions['modified']['id'], false, 'minimal'); if (empty($user_profile[$msgOptions['modified']['id']])) { $modified = false; } // oops, they gave us a user id that doesn't exist -- and we don't have a name } // Otherwise, we have a name and no id, which is fine. Can't be doing with trying to figure out usernames. } } else { $modified = false; } if (!$modified) { $msgOptions['modified'] = array('id' => 0, 'name' => '', 'time' => 0); } // It's do or die time: forget any user aborts! $previous_ignore_user_abort = ignore_user_abort(true); $new_ticket = empty($ticketOptions['id']); // OK, so let's add the reply. Even if it's a new ticket and stuff, let's still add the msg first so we have our friendly msg id $smcFunc['db_insert']('', '{db_prefix}helpdesk_ticket_replies', array('id_ticket' => 'int', 'id_member' => 'int', 'body' => 'string-65534', 'poster_name' => 'string-255', 'poster_email' => 'string-255', 'poster_time' => 'int', 'poster_ip' => 'string-255', 'smileys_enabled' => 'int', 'modified_member' => 'int', 'modified_name' => 'string', 'modified_time' => 'int'), array($ticketOptions['id'], $posterOptions['id'], $msgOptions['body'], $posterOptions['name'], $posterOptions['email'], $msgOptions['time'], $posterOptions['ip'], $msgOptions['smileys_enabled'] ? 1 : 0, $msgOptions['modified']['id'], $msgOptions['modified']['name'], $msgOptions['modified']['time']), array('id_msg')); $msgOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}messages', 'id_msg'); // Something went wrong creating the message... if (empty($msgOptions['id'])) { return false; } // Insert a new ticket (if the ID was left empty) if ($new_ticket) { $smcFunc['db_insert']('', '{db_prefix}helpdesk_tickets', array('id_dept' => 'int', 'id_first_msg' => 'int', 'id_member_started' => 'int', 'id_last_msg' => 'int', 'id_member_updated' => 'int', 'id_member_assigned' => 'int', 'subject' => 'string-100', 'urgency' => 'int', 'status' => 'int', 'private' => 'int'), array($ticketOptions['dept'], $msgOptions['id'], $posterOptions['id'], $msgOptions['id'], $posterOptions['id'], $ticketOptions['assigned'], $ticketOptions['subject'], $ticketOptions['urgency'], $ticketOptions['status'], $ticketOptions['private'] ? 1 : 0), array('id_ticket')); $ticketOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}helpdesk_tickets', 'id_ticket'); // The ticket couldn't be created for some reason. if (empty($ticketOptions['id'])) { // We should delete the post that did work, though... shd_db_query('', ' DELETE FROM {db_prefix}helpdesk_ticket_replies WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'])); return false; } // Fix the message with the ticket. shd_db_query('', ' UPDATE {db_prefix}helpdesk_ticket_replies SET id_ticket = {int:id_ticket} WHERE id_msg = {int:id_msg}', array('id_ticket' => $ticketOptions['id'], 'id_msg' => $msgOptions['id'])); } else { shd_db_query('', ' UPDATE {db_prefix}helpdesk_tickets SET id_member_updated = {int:poster_id}, id_last_msg = {int:id_msg}, num_replies = num_replies + 1, status = {int:status} WHERE id_ticket = {int:id_ticket}', array('poster_id' => $posterOptions['id'], 'id_msg' => $msgOptions['id'], 'status' => $ticketOptions['status'], 'id_ticket' => $ticketOptions['id'])); } // Fix the attachments. if (!empty($msgOptions['attachments'])) { $array = array(); foreach ($msgOptions['attachments'] as $attach) { $array[] = array($attach, $msgOptions['id'], $ticketOptions['id']); } $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_attachments', array('id_attach' => 'int', 'id_msg' => 'int', 'id_ticket' => 'int'), $array, array('id_attach')); } // Mark inserted ticket as read (only for the user listed as the author -- oftentimes will be the current user though) if (!empty($ticketOptions['mark_as_read']) && !empty($posterOptions['id'])) { // Since it's likely they *read* it before replying, let's try an UPDATE first. if (!$new_ticket) { shd_db_query('', ' UPDATE {db_prefix}helpdesk_log_read SET id_msg = {int:id_msg} WHERE id_member = {int:current_member} AND id_ticket = {int:id_ticket}', array('current_member' => $posterOptions['id'], 'id_msg' => $msgOptions['id'], 'id_ticket' => $ticketOptions['id'])); $flag = $smcFunc['db_affected_rows']() != 0; } if (empty($flag)) { // Hold on a second... If this is a proxy ticket... We'll want to mark it read for the staff member, not the member for whom it was posted. $mark_read_user = !empty($ticketOptions['mark_as_read_proxy']) ? $ticketOptions['mark_as_read_proxy'] : $posterOptions['id']; $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_log_read', array('id_ticket' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), array($ticketOptions['id'], $mark_read_user, $msgOptions['id']), array('id_ticket', 'id_member')); } } // Are we saving custom fields? $rows = array(); if (!empty($ticketOptions['custom_fields'])) { // We shouldn't need to be bothering with pre-existing ones. This is a new message in whatever form, after all. foreach ($ticketOptions['custom_fields'] as $field_id => $field) { if (isset($field['new_value'])) { $rows[] = array('id_post' => $ticketOptions['id'], 'id_field' => $field_id, 'value' => $field['new_value'], 'post_type' => CFIELD_TICKET); } } } // Same deal, just this time for message fields. if (!empty($msgOptions['custom_fields'])) { foreach ($msgOptions['custom_fields'] as $field_id => $field) { if (isset($field['new_value'])) { $rows[] = array('id_post' => $msgOptions['id'], 'id_field' => $field_id, 'value' => $field['new_value'], 'post_type' => CFIELD_REPLY); } } } if (!empty($rows)) { $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_custom_fields_values', array('id_post' => 'int', 'id_field' => 'int', 'value' => 'string-65534', 'post_type' => 'int'), $rows, array('id_post', 'id_field')); } // Int hooks $hook = $new_ticket ? 'shd_hook_newticket' : 'shd_hook_newreply'; call_integration_hook($hook, array(&$msgOptions, &$ticketOptions, &$posterOptions)); ignore_user_abort($previous_ignore_user_abort); if (empty($ticketOptions['dept']) && !empty($ticketOptions['id'])) { // So we're making a reply, we need the department id. The ticket will already exist - we just added to it! $query = $smcFunc['db_query']('', ' SELECT id_dept FROM {db_prefix}helpdesk_tickets WHERE id_ticket = {int:id_ticket}', array('id_ticket' => $ticketOptions['id'])); list($ticketOptions['dept']) = $smcFunc['db_fetch_row']($query); $smcFunc['db_free_result']($query); } if (!empty($ticketOptions['dept'])) { shd_clear_active_tickets($ticketOptions['dept']); } // Success. return true; }
function Who() { global $context, $scripturl, $user_info, $txt, $modSettings, $memberContext, $smcFunc; // 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'; } // Get the total amount of members online. $request = $smcFunc['db_query']('', ' SELECT COUNT(*) FROM {db_prefix}log_online AS lo LEFT JOIN {db_prefix}members AS mem ON (lo.id_member = mem.id_member)' . (!empty($conditions) ? ' WHERE ' . implode(' AND ', $conditions) : ''), array()); list($totalMembers) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // 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']; // Look for people online, provided they don't mind if you see they are. $request = $smcFunc['db_query']('', ' SELECT lo.log_time, lo.id_member, lo.url, INET_NTOA(lo.ip) AS ip, mem.real_name, lo.session, mg.online_color, IFNULL(mem.show_online, 1) AS show_online, lo.id_spider FROM {db_prefix}log_online AS lo LEFT JOIN {db_prefix}members AS mem ON (lo.id_member = mem.id_member) LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:regular_member} THEN mem.id_post_group ELSE mem.id_group END)' . (!empty($conditions) ? ' WHERE ' . implode(' AND ', $conditions) : '') . ' ORDER BY {raw:sort_method} {raw:sort_direction} LIMIT {int:offset}, {int:limit}', array('regular_member' => 0, 'sort_method' => $sort_method, 'sort_direction' => $context['sort_direction'] == 'up' ? 'ASC' : 'DESC', 'offset' => $context['start'], 'limit' => $modSettings['defaultMaxMembers'])); $context['members'] = array(); $member_ids = array(); $url_data = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $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' => strtr(timeformat($row['log_time']), array($txt['today'] => '', $txt['yesterday'] => '')), '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']; } $smcFunc['db_free_result']($request); // 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); } } $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'); // any profile fields disabled? $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array(); }
/** * @param $memID int member ID * * show the settings to customize opt-outs for activity entries and notifications * to receive. * * todo: we need to find a way to filter out notifications that are for * admins/mods only. probably needs a db scheme change... */ function showActivitiesProfileSettings($memID) { global $modSettings, $context, $user_info, $txt, $user_profile, $scripturl; loadLanguage('Activities-Profile'); if (empty($modSettings['astream_active']) || $user_info['id'] != $memID && !$user_info['is_admin']) { fatal_lang_error('no_access'); } Eos_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'profile/astream_settings'); $context['submiturl'] = $scripturl . '?action=profile;area=activities;sa=settings;save;u=' . $memID; $context['page_title'] = $txt['showActivities'] . ' - ' . $user_profile[$memID]['real_name']; $context[$context['profile_menu_name']]['tab_data'] = array('title' => $txt['showActivitiesSettings'], 'description' => $txt['showActivitiesSettings_desc'], 'tabs' => array()); $result = smf_db_query('SELECT * FROM {db_prefix}activity_types ORDER BY id_type ASC'); if ($user_info['id'] == $memID) { $my_act_optout = empty($user_info['act_optout']) ? array(0) : explode(',', $user_info['act_optout']); $my_notify_optout = empty($user_info['notify_optout']) ? array(0) : explode(',', $user_info['notify_optout']); } else { loadMemberData($memID, false, 'minimal'); $my_act_optout = empty($user_profile[$memID]['act_optout']) ? array(0) : explode(',', $user_profile[$memID]['act_optout']); $my_notify_optout = empty($user_profile[$memID]['notify_optout']) ? array(0) : explode(',', $user_profile[$memID]['notify_optout']); } $context['activity_types'] = array(); while ($row = mysql_fetch_assoc($result)) { $context['activity_types'][] = array('id' => $row['id_type'], 'shortdesc' => $row['id_desc'], 'longdesc_act' => $txt['actdesc_' . trim($row['id_desc'])], 'longdesc_not' => isset($txt['ndesc_' . trim($row['id_desc'])]) ? $txt['ndesc_' . trim($row['id_desc'])] : '', 'act_optout' => in_array($row['id_type'], $my_act_optout), 'notify_optout' => in_array($row['id_type'], $my_notify_optout)); } mysql_free_result($result); if (isset($_GET['save'])) { $new_not_optout = array(); $new_act_optout = array(); $update_array = array(); foreach ($context['activity_types'] as $t) { $_id = trim($t['id']); if (!empty($t['longdesc_act']) && (!isset($_REQUEST['act_check_' . $_id]) || empty($_REQUEST['act_check_' . $_id]))) { $new_act_optout[] = $_id; } if (!empty($t['longdesc_not']) && (!isset($_REQUEST['not_check_' . $_id]) || empty($_REQUEST['not_check_' . $_id]))) { $new_not_optout[] = $_id; } } //if(count(array_unique($new_act_optout)) > 0) $update_array['act_optout'] = implode(',', array_unique($new_act_optout)); //if(count(array_unique($new_not_optout)) > 0) $update_array['notify_optout'] = implode(',', array_unique($new_not_optout)); if (count($update_array)) { updateMemberData($memID, $update_array); } redirectexit($scripturl . '?action=profile;area=activities;sa=settings;u=' . $memID); } }
$return = ssi_topPoster($topNumber, 'array'); cache_put_data('bk_top_poster', $return, 1800); } else { $return = cache_get_data('bk_top_poster', 1800); } } else { $return = ssi_topPoster($topNumber, 'array'); } // Make a quick array to list the links in. echo ' <table style="border-spacing:5px;width:100%;" border="0" cellspacing="1" cellpadding="3"> '; $count = 0; foreach ($return as $member) { //load member data loadMemberData($member['id']); loadMemberContext($member['id']); //end load member data... $count++; echo ' <tr> <td align="left">'; if (!empty($memberContext[$member['id']]['avatar']['href'])) { echo '<img src="' . $memberContext[$member['id']]['avatar']['href'] . '" style="-moz-box-shadow: 0px 0px 5px #444; -webkit-box-shadow: 0px 0px 5px #444; box-shadow: 0px 0px 5px #444;" width="50px;" alt="" />'; } echo '</td> <td width="100%" valign="middle"> ', $count == 1 ? '<img src="' . $settings['default_images_url'] . '/ultimate-portal/icons/1.gif" width="22px" alt="" />' : '', '
function PlushSearch2() { global $scripturl, $modSettings, $sourcedir, $txt, $db_prefix, $db_connection; global $user_info, $ID_MEMBER, $context, $options, $messages_request, $boards_can; global $excludedWords, $participants, $func; // !!! Add spam protection. if (!empty($context['load_average']) && !empty($modSettings['loadavg_search']) && $context['load_average'] >= $modSettings['loadavg_search']) { fatal_lang_error('loadavg_search_disabled', false); } // No, no, no... this is a bit hard on the server, so don't you go prefetching it! if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') { ob_end_clean(); header('HTTP/1.1 403 Forbidden'); die; } $weight_factors = array('frequency', 'age', 'length', 'subject', 'first_message', 'sticky'); $weight = array(); $weight_total = 0; foreach ($weight_factors as $weight_factor) { $weight[$weight_factor] = empty($modSettings['search_weight_' . $weight_factor]) ? 0 : (int) $modSettings['search_weight_' . $weight_factor]; $weight_total += $weight[$weight_factor]; } // Zero weight. Weightless :P. if (empty($weight_total)) { fatal_lang_error('search_invalid_weights'); } // These vars don't require an interface, the're just here for tweaking. $recentPercentage = 0.3; $humungousTopicPosts = 200; $maxMembersToSearch = 500; $maxMessageResults = empty($modSettings['search_max_results']) ? 0 : $modSettings['search_max_results'] * 5; // Start with no errors. $context['search_errors'] = array(); // Number of pages hard maximum - normally not set at all. $modSettings['search_max_results'] = empty($modSettings['search_max_results']) ? 200 * $modSettings['search_results_per_page'] : (int) $modSettings['search_max_results']; loadLanguage('Search'); loadTemplate('Search'); // Are you allowed? isAllowedTo('search_posts'); require_once $sourcedir . '/Display.php'; if (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'fulltext') { // Try to determine the minimum number of letters for a fulltext search. $request = db_query("\n\t\t\tSHOW VARIABLES\n\t\t\tLIKE 'ft_min_word_len'", false, false); if ($request !== false && mysql_num_rows($request) == 1) { list(, $min_word_length) = mysql_fetch_row($request); mysql_free_result($request); } else { $min_word_length = '4'; } // Some MySQL versions are superior to others :P. $canDoBooleanSearch = version_compare(mysql_get_server_info($db_connection), '4.0.1', '>=') == 1; // Get a list of banned fulltext words. $banned_words = empty($modSettings['search_banned_words']) ? array() : explode(',', addslashes($modSettings['search_banned_words'])); } elseif (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'custom' && !empty($modSettings['search_custom_index_config'])) { $customIndexSettings = unserialize($modSettings['search_custom_index_config']); $min_word_length = $customIndexSettings['bytes_per_word']; $banned_words = empty($modSettings['search_stopwords']) ? array() : explode(',', addslashes($modSettings['search_stopwords'])); } else { $modSettings['search_index'] = ''; } // $search_params will carry all settings that differ from the default search parameters. // That way, the URLs involved in a search page will be kept as short as possible. $search_params = array(); if (isset($_REQUEST['params'])) { $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+')))); foreach ($temp_params as $i => $data) { @(list($k, $v) = explode('|\'|', $data)); $search_params[$k] = stripslashes($v); } if (isset($search_params['brd'])) { $search_params['brd'] = empty($search_params['brd']) ? array() : explode(',', $search_params['brd']); } } // Store whether simple search was used (needed if the user wants to do another query). if (!isset($search_params['advanced'])) { $search_params['advanced'] = empty($_REQUEST['advanced']) ? 0 : 1; } // 1 => 'allwords' (default, don't set as param) / 2 => 'anywords'. if (!empty($search_params['searchtype']) || !empty($_REQUEST['searchtype']) && $_REQUEST['searchtype'] == 2) { $search_params['searchtype'] = 2; } // Minimum age of messages. Default to zero (don't set param in that case). if (!empty($search_params['minage']) || !empty($_REQUEST['minage']) && $_REQUEST['minage'] > 0) { $search_params['minage'] = !empty($search_params['minage']) ? (int) $search_params['minage'] : (int) $_REQUEST['minage']; } // Maximum age of messages. Default to infinite (9999 days: param not set). if (!empty($search_params['maxage']) || !empty($_REQUEST['maxage']) && $_REQUEST['maxage'] != 9999) { $search_params['maxage'] = !empty($search_params['maxage']) ? (int) $search_params['maxage'] : (int) $_REQUEST['maxage']; } // Searching a specific topic? if (!empty($_REQUEST['topic'])) { $search_params['topic'] = (int) $_REQUEST['topic']; $search_params['show_complete'] = true; } elseif (!empty($search_params['topic'])) { $search_params['topic'] = (int) $search_params['topic']; } if (!empty($search_params['minage']) || !empty($search_params['maxage'])) { $request = db_query("\n\t\t\tSELECT " . (empty($search_params['maxage']) ? '0, ' : 'IFNULL(MIN(ID_MSG), -1), ') . (empty($search_params['minage']) ? '0' : 'IFNULL(MAX(ID_MSG), -1)') . "\n\t\t\tFROM {$db_prefix}messages\n\t\t\tWHERE " . (empty($search_params['minage']) ? '1' : 'posterTime <= ' . (time() - 86400 * $search_params['minage'])) . (empty($search_params['maxage']) ? '' : "\n\t\t\t\tAND posterTime >= " . (time() - 86400 * $search_params['maxage'])), __FILE__, __LINE__); list($minMsgID, $maxMsgID) = mysql_fetch_row($request); if ($minMsgID < 0 || $maxMsgID < 0) { $context['search_errors']['no_messages_in_time_frame'] = true; } mysql_free_result($request); } // Default the user name to a wildcard matching every user (*). if (!empty($search_params['userspec']) || !empty($_REQUEST['userspec']) && $_REQUEST['userspec'] != '*') { $search_params['userspec'] = isset($search_params['userspec']) ? $search_params['userspec'] : $_REQUEST['userspec']; } // If there's no specific user, then don't mention it in the main query. if (empty($search_params['userspec'])) { $userQuery = ''; } else { $userString = strtr(addslashes($func['htmlspecialchars'](stripslashes($search_params['userspec']), ENT_QUOTES)), array('"' => '"')); $userString = strtr($userString, array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_')); preg_match_all('~"([^"]+)"~', $userString, $matches); $possible_users = array_merge($matches[1], explode(',', preg_replace('~"([^"]+)"~', '', $userString))); for ($k = 0, $n = count($possible_users); $k < $n; $k++) { $possible_users[$k] = trim($possible_users[$k]); if (strlen($possible_users[$k]) == 0) { unset($possible_users[$k]); } } // Retrieve a list of possible members. $request = db_query("\n\t\t\tSELECT ID_MEMBER\n\t\t\tFROM {$db_prefix}members\n\t\t\tWHERE realName LIKE '" . implode("' OR realName LIKE '", $possible_users) . "'", __FILE__, __LINE__); // Simply do nothing if there're too many members matching the criteria. if (mysql_num_rows($request) > $maxMembersToSearch) { $userQuery = ''; } elseif (mysql_num_rows($request) == 0) { $userQuery = "m.ID_MEMBER = 0 AND (m.posterName LIKE '" . implode("' OR m.posterName LIKE '", $possible_users) . "')"; } else { $memberlist = array(); while ($row = mysql_fetch_assoc($request)) { $memberlist[] = $row['ID_MEMBER']; } $userQuery = "(m.ID_MEMBER IN (" . implode(', ', $memberlist) . ") OR (m.ID_MEMBER = 0 AND (m.posterName LIKE '" . implode("' OR m.posterName LIKE '", $possible_users) . "')))"; } mysql_free_result($request); } // If the boards were passed by URL (params=), temporarily put them back in $_REQUEST. if (!empty($search_params['brd']) && is_array($search_params['brd'])) { $_REQUEST['brd'] = $search_params['brd']; } // Ensure that brd is an array. if (!empty($_REQUEST['brd']) && !is_array($_REQUEST['brd'])) { $_REQUEST['brd'] = strpos($_REQUEST['brd'], ',') !== false ? explode(',', $_REQUEST['brd']) : array($_REQUEST['brd']); } // Make sure all boards are integers. if (!empty($_REQUEST['brd'])) { foreach ($_REQUEST['brd'] as $id => $brd) { $_REQUEST['brd'][$id] = (int) $brd; } } // Special case for boards: searching just one topic? if (!empty($search_params['topic'])) { $request = db_query("\n\t\t\tSELECT b.ID_BOARD\n\t\t\tFROM ({$db_prefix}topics AS t, {$db_prefix}boards AS b)\n\t\t\tWHERE b.ID_BOARD = t.ID_BOARD\n\t\t\t\tAND t.ID_TOPIC = " . $search_params['topic'] . "\n\t\t\t\tAND {$user_info['query_see_board']}\n\t\t\tLIMIT 1", __FILE__, __LINE__); if (mysql_num_rows($request) == 0) { fatal_lang_error('topic_gone', false); } $search_params['brd'] = array(); list($search_params['brd'][0]) = mysql_fetch_row($request); mysql_free_result($request); } elseif ($user_info['is_admin'] && (!empty($search_params['advanced']) || !empty($_REQUEST['brd']))) { $search_params['brd'] = empty($_REQUEST['brd']) ? array() : $_REQUEST['brd']; } else { $request = db_query("\n\t\t\tSELECT b.ID_BOARD\n\t\t\tFROM {$db_prefix}boards AS b\n\t\t\tWHERE {$user_info['query_see_board']}" . (empty($_REQUEST['brd']) ? !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? "\n\t\t\t\tAND b.ID_BOARD != {$modSettings['recycle_board']}" : '' : "\n\t\t\t\tAND b.ID_BOARD IN (" . implode(', ', $_REQUEST['brd']) . ")"), __FILE__, __LINE__); $search_params['brd'] = array(); while ($row = mysql_fetch_assoc($request)) { $search_params['brd'][] = $row['ID_BOARD']; } mysql_free_result($request); // This error should pro'bly only happen for hackers. if (empty($search_params['brd'])) { $context['search_errors']['no_boards_selected'] = true; } } if (count($search_params['brd']) != 0) { // If we've selected all boards, this parameter can be left empty. $request = db_query("\n\t\t\tSELECT COUNT(*)\n\t\t\tFROM {$db_prefix}boards", __FILE__, __LINE__); list($num_boards) = mysql_fetch_row($request); mysql_free_result($request); if (count($search_params['brd']) == $num_boards) { $boardQuery = ''; } elseif (count($search_params['brd']) == $num_boards - 1 && !empty($modSettings['recycle_board']) && !in_array($modSettings['recycle_board'], $search_params['brd'])) { $boardQuery = '!= ' . $modSettings['recycle_board']; } else { $boardQuery = 'IN (' . implode(', ', $search_params['brd']) . ')'; } } else { $boardQuery = ''; } $search_params['show_complete'] = !empty($search_params['show_complete']) || !empty($_REQUEST['show_complete']); $search_params['subject_only'] = !empty($search_params['subject_only']) || !empty($_REQUEST['subject_only']); $context['compact'] = !$search_params['show_complete']; // Get the sorting parameters right. Default to sort by relevance descending. $sort_columns = array('relevance', 'numReplies', 'ID_MSG'); if (empty($search_params['sort']) && !empty($_REQUEST['sort'])) { list($search_params['sort'], $search_params['sort_dir']) = array_pad(explode('|', $_REQUEST['sort']), 2, ''); } $search_params['sort'] = !empty($search_params['sort']) && in_array($search_params['sort'], $sort_columns) ? $search_params['sort'] : 'relevance'; if (!empty($search_params['topic']) && $search_params['sort'] === 'numReplies') { $search_params['sort'] = 'ID_MSG'; } // Sorting direction: descending unless stated otherwise. $search_params['sort_dir'] = !empty($search_params['sort_dir']) && $search_params['sort_dir'] == 'asc' ? 'asc' : 'desc'; // Determine some values needed to calculate the relevance. $minMsg = (int) ((1 - $recentPercentage) * $modSettings['maxMsgID']); $recentMsg = $modSettings['maxMsgID'] - $minMsg; // *** Parse the search query // Unfortunately, searching for words like this is going to be slow, so we're blacklisting them. // !!! Setting to add more here? // !!! Maybe only blacklist if they are the only word, or "any" is used? $blacklisted_words = array('img', 'url', 'quote', 'www', 'http', 'the', 'is', 'it', 'are', 'if'); // What are we searching for? if (empty($search_params['search'])) { if (isset($_GET['search'])) { $search_params['search'] = un_htmlspecialchars($_GET['search']); } elseif (isset($_POST['search'])) { $search_params['search'] = stripslashes($_POST['search']); } else { $search_params['search'] = ''; } } // Nothing?? if (!isset($search_params['search']) || $search_params['search'] == '') { $context['search_errors']['invalid_search_string'] = true; } // Change non-word characters into spaces. $stripped_query = preg_replace('~([\\x0B\\0' . ($context['utf8'] ? $context['server']['complex_preg_chars'] ? '\\x{A0}' : pack('C*', 0xc2, 0xa0) : '\\xA0') . '\\t\\r\\s\\n(){}\\[\\]<>!@$%^*.,:+=`\\~\\?/\\\\]|&(amp|lt|gt|quot);)+~' . ($context['utf8'] ? 'u' : ''), ' ', $search_params['search']); // Make the query lower case. It's gonna be case insensitive anyway. $stripped_query = un_htmlspecialchars($func['strtolower']($stripped_query)); // This (hidden) setting will do fulltext searching in the most basic way. if (!empty($modSettings['search_simple_fulltext'])) { $stripped_query = strtr($stripped_query, array('"' => '')); } $no_regexp = preg_match('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', $stripped_query) === 1; // Extract phrase parts first (e.g. some words "this is a phrase" some more words.) preg_match_all('/(?:^|\\s)([-]?)"([^"]+)"(?:$|\\s)/', $stripped_query, $matches, PREG_PATTERN_ORDER); $phraseArray = $matches[2]; // Remove the phrase parts and extract the words. $wordArray = explode(' ', preg_replace('~(?:^|\\s)([-]?)"([^"]+)"(?:$|\\s)~' . ($context['utf8'] ? 'u' : ''), ' ', $stripped_query)); // A minus sign in front of a word excludes the word.... so... $excludedWords = array(); $excludedIndexWords = array(); $excludedSubjectWords = array(); $excludedPhrases = array(); // .. first, we check for things like -"some words", but not "-some words". foreach ($matches[1] as $index => $word) { if ($word === '-') { if (($word = trim($phraseArray[$index], '-_\' ')) !== '' && !in_array($word, $blacklisted_words)) { $excludedWords[] = addslashes($word); } unset($phraseArray[$index]); } } // Now we look for -test, etc.... normaller. foreach ($wordArray as $index => $word) { if (strpos(trim($word), '-') === 0) { if (($word = trim($word, '-_\' ')) !== '' && !in_array($word, $blacklisted_words)) { $excludedWords[] = addslashes($word); } unset($wordArray[$index]); } } // The remaining words and phrases are all included. $searchArray = array_merge($phraseArray, $wordArray); // Trim everything and make sure there are no words that are the same. foreach ($searchArray as $index => $value) { if (($searchArray[$index] = trim($value, '-_\' ')) === '' || in_array($searchArray[$index], $blacklisted_words)) { unset($searchArray[$index]); } else { $searchArray[$index] = addslashes($searchArray[$index]); } } $searchArray = array_slice(array_unique($searchArray), 0, 10); // Create an array of replacements for highlighting. $context['mark'] = array(); foreach ($searchArray as $word) { $context['mark'][$word] = '<b class="highlight">' . $word . '</b>'; } // Initialize two arrays storing the words that have to be searched for. $orParts = array(); $searchWords = array(); // Make sure at least one word is being searched for. if (empty($searchArray)) { $context['search_errors']['invalid_search_string'] = true; } elseif (empty($search_params['searchtype'])) { $orParts[0] = $searchArray; } else { foreach ($searchArray as $index => $value) { $orParts[$index] = array($value); } } // Make sure the excluded words are in all or-branches. foreach ($orParts as $orIndex => $andParts) { foreach ($excludedWords as $word) { $orParts[$orIndex][] = $word; } } // Determine the or-branches and the fulltext search words. foreach ($orParts as $orIndex => $andParts) { $searchWords[$orIndex] = array('indexed_words' => array(), 'words' => array(), 'subject_words' => array(), 'all_words' => array()); // Sort the indexed words (large words -> small words -> excluded words). if (!empty($modSettings['search_index'])) { usort($orParts[$orIndex], 'searchSort'); } foreach ($orParts[$orIndex] as $word) { $is_excluded = in_array($word, $excludedWords); $searchWords[$orIndex]['all_words'][] = $word; $subjectWords = text2words(stripslashes($word)); if (!$is_excluded || count($subjectWords) === 1) { $searchWords[$orIndex]['subject_words'] = array_merge($searchWords[$orIndex]['subject_words'], $subjectWords); if ($is_excluded) { $excludedSubjectWords = array_merge($excludedSubjectWords, $subjectWords); } } else { $excludedPhrases[] = $word; } if (!empty($modSettings['search_index'])) { $subwords = text2words(stripslashes($word), $modSettings['search_index'] === 'fulltext' ? null : $min_word_length, $modSettings['search_index'] === 'custom'); if (($modSettings['search_index'] === 'custom' || $modSettings['search_index'] === 'fulltext' && !$canDoBooleanSearch && count($subwords) > 1) && empty($modSettings['search_force_index'])) { $searchWords[$orIndex]['words'][] = $word; } if ($modSettings['search_index'] === 'fulltext' && $canDoBooleanSearch) { $fulltextWord = count($subwords) === 1 ? $word : '"' . $word . '"'; $searchWords[$orIndex]['indexed_words'][] = $fulltextWord; if ($is_excluded) { $excludedIndexWords[] = $fulltextWord; } } elseif (count($subwords) > 1 && $is_excluded) { continue; } else { $relyOnIndex = true; foreach ($subwords as $subword) { if (($modSettings['search_index'] === 'custom' || strlen(stripslashes($subword)) >= $min_word_length) && !in_array($subword, $banned_words)) { $searchWords[$orIndex]['indexed_words'][] = $subword; if ($is_excluded) { $excludedIndexWords[] = $subword; } } elseif (!in_array($subword, $banned_words)) { $relyOnIndex = false; } } if ($modSettings['search_index'] === 'fulltext' && $canDoBooleanSearch && !$relyOnIndex && empty($modSettings['search_force_index'])) { $searchWords[$orIndex]['words'][] = $word; } } } } // Search_force_index requires all AND parts to have at least one fulltext word. if (!empty($modSettings['search_force_index']) && empty($searchWords[$orIndex]['indexed_words'])) { $context['search_errors']['query_not_specific_enough'] = true; break; } else { $searchWords[$orIndex]['indexed_words'] = array_slice($searchWords[$orIndex]['indexed_words'], 0, 7); $searchWords[$orIndex]['subject_words'] = array_slice($searchWords[$orIndex]['subject_words'], 0, 7); } } // *** Spell checking $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new'); if ($context['show_spellchecking']) { // Windows fix. ob_start(); $old = error_reporting(0); pspell_new('en'); $pspell_link = pspell_new($txt['lang_dictionary'], $txt['lang_spelling'], '', strtr($txt['lang_character_set'], array('iso-' => 'iso', 'ISO-' => 'iso')), PSPELL_FAST | PSPELL_RUN_TOGETHER); error_reporting($old); if (!$pspell_link) { $pspell_link = pspell_new('en', '', '', '', PSPELL_FAST | PSPELL_RUN_TOGETHER); } ob_end_clean(); $did_you_mean = array('search' => array(), 'display' => array()); $found_misspelling = false; foreach ($searchArray as $word) { if (empty($pspell_link)) { continue; } $word = stripslashes($word); // Don't check phrases. if (preg_match('~^\\w+$~', $word) === 0) { $did_you_mean['search'][] = '"' . $word . '"'; $did_you_mean['display'][] = '"' . $func['htmlspecialchars']($word) . '"'; continue; } elseif (preg_match('~\\d~', $word) === 1) { $did_you_mean['search'][] = $word; $did_you_mean['display'][] = $func['htmlspecialchars']($word); continue; } elseif (pspell_check($pspell_link, $word)) { $did_you_mean['search'][] = $word; $did_you_mean['display'][] = $func['htmlspecialchars']($word); continue; } $suggestions = pspell_suggest($pspell_link, $word); foreach ($suggestions as $i => $s) { // Search is case insensitive. if ($func['strtolower']($s) == $func['strtolower']($word)) { unset($suggestions[$i]); } } // Anything found? If so, correct it! if (!empty($suggestions)) { $suggestions = array_values($suggestions); $did_you_mean['search'][] = $suggestions[0]; $did_you_mean['display'][] = '<em><b>' . $func['htmlspecialchars']($suggestions[0]) . '</b></em>'; $found_misspelling = true; } else { $did_you_mean['search'][] = $word; $did_you_mean['display'][] = $func['htmlspecialchars']($word); } } if ($found_misspelling) { // Don't spell check excluded words, but add them still... $temp_excluded = array('search' => array(), 'display' => array()); foreach ($excludedWords as $word) { $word = stripslashes($word); if (preg_match('~^\\w+$~', $word) == 0) { $temp_excluded['search'][] = '-"' . $word . '"'; $temp_excluded['display'][] = '-"' . $func['htmlspecialchars']($word) . '"'; } else { $temp_excluded['search'][] = '-' . $word; $temp_excluded['display'][] = '-' . $func['htmlspecialchars']($word); } } $did_you_mean['search'] = array_merge($did_you_mean['search'], $temp_excluded['search']); $did_you_mean['display'] = array_merge($did_you_mean['display'], $temp_excluded['display']); $temp_params = $search_params; $temp_params['search'] = implode(' ', $did_you_mean['search']); if (isset($temp_params['brd'])) { $temp_params['brd'] = implode(',', $temp_params['brd']); } $context['params'] = array(); foreach ($temp_params as $k => $v) { $context['did_you_mean_params'][] = $k . '|\'|' . addslashes($v); } $context['did_you_mean_params'] = base64_encode(implode('|"|', $context['did_you_mean_params'])); $context['did_you_mean'] = implode(' ', $did_you_mean['display']); } } // Let the user adjust the search query, should they wish? $context['search_params'] = $search_params; if (isset($context['search_params']['search'])) { $context['search_params']['search'] = $func['htmlspecialchars']($context['search_params']['search']); } if (isset($context['search_params']['userspec'])) { $context['search_params']['userspec'] = $func['htmlspecialchars']($context['search_params']['userspec']); } // *** Encode all search params // All search params have been checked, let's compile them to a single string... made less simple by PHP 4.3.9 and below. $temp_params = $search_params; if (isset($temp_params['brd'])) { $temp_params['brd'] = implode(',', $temp_params['brd']); } $context['params'] = array(); foreach ($temp_params as $k => $v) { $context['params'][] = $k . '|\'|' . addslashes($v); } $context['params'] = base64_encode(implode('|"|', $context['params'])); // ... and add the links to the link tree. $context['linktree'][] = array('url' => $scripturl . '?action=search;params=' . $context['params'], 'name' => $txt[182]); $context['linktree'][] = array('url' => $scripturl . '?action=search2;params=' . $context['params'], 'name' => $txt['search_results']); // *** A last error check // One or more search errors? Go back to the first search screen. if (!empty($context['search_errors'])) { $_REQUEST['params'] = $context['params']; return PlushSearch1(); } /* // !!! This doesn't seem too urgent anymore. Can we remove it? if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) { // !!! Change error message... if (cache_get_data('search_start:' . ($user_info['is_guest'] ? $user_info['ip'] : $ID_MEMBER), 90) == 1) fatal_lang_error('loadavg_search_disabled', false); cache_put_data('search_start:' . ($user_info['is_guest'] ? $user_info['ip'] : $ID_MEMBER), 1, 90); }*/ // *** Reserve an ID for caching the search results. // Update the cache if the current search term is not yet cached. if (empty($_SESSION['search_cache']) || $_SESSION['search_cache']['params'] != $context['params']) { // Increase the pointer... $modSettings['search_pointer'] = empty($modSettings['search_pointer']) ? 0 : (int) $modSettings['search_pointer']; // ...and store it right off. updateSettings(array('search_pointer' => $modSettings['search_pointer'] >= 255 ? 0 : $modSettings['search_pointer'] + 1)); // As long as you don't change the parameters, the cache result is yours. $_SESSION['search_cache'] = array('ID_SEARCH' => $modSettings['search_pointer'], 'num_results' => -1, 'params' => $context['params']); // Clear the previous cache of the final results cache. db_query("\n\t\t\tDELETE FROM {$db_prefix}log_search_results\n\t\t\tWHERE ID_SEARCH = " . $_SESSION['search_cache']['ID_SEARCH'], __FILE__, __LINE__); if ($search_params['subject_only']) { foreach ($searchWords as $orIndex => $words) { $subject_query = array('from' => array("{$db_prefix}topics AS t"), 'left_join' => array(), 'where' => array()); $numTables = 0; $prev_join = 0; $numSubjectResults = 0; foreach ($words['subject_words'] as $subjectWord) { $numTables++; if (in_array($subjectWord, $excludedSubjectWords)) { $subject_query['left_join'][] = "{$db_prefix}log_search_subjects AS subj{$numTables} ON (subj{$numTables}.word " . (empty($modSettings['search_match_words']) ? "LIKE '%{$subjectWord}%'" : "= '{$subjectWord}'") . " AND subj{$numTables}.ID_TOPIC = t.ID_TOPIC)"; $subject_query['where'][] = "(subj{$numTables}.word IS NULL)"; } else { $subject_query['from'][] = "{$db_prefix}log_search_subjects AS subj{$numTables}"; $subject_query['where'][] = "subj{$numTables}.word " . (empty($modSettings['search_match_words']) ? "LIKE '%{$subjectWord}%'" : "= '{$subjectWord}'"); $subject_query['where'][] = "subj{$numTables}.ID_TOPIC = " . ($prev_join === 0 ? 't' : 'subj' . $prev_join) . '.ID_TOPIC'; $prev_join = $numTables; } } if (!empty($userQuery)) { if (!in_array("{$db_prefix}messages AS m", $subject_query['from'])) { $subject_query['from'][] = "{$db_prefix}messages AS m"; $subject_query['where'][] = 'm.ID_TOPIC = t.ID_TOPIC'; } $subject_query['where'][] = $userQuery; } if (!empty($search_params['topic'])) { $subject_query['where'][] = 't.ID_TOPIC = ' . $search_params['topic']; } if (!empty($minMsgID)) { $subject_query['where'][] = 't.ID_FIRST_MSG >= ' . $minMsgID; } if (!empty($maxMsgID)) { $subject_query['where'][] = 't.ID_LAST_MSG <= ' . $maxMsgID; } if (!empty($boardQuery)) { $subject_query['where'][] = 't.ID_BOARD ' . $boardQuery; } if (!empty($excludedPhrases)) { if (!in_array("{$db_prefix}messages AS m", $subject_query['from'])) { $subject_query['from'][] = "{$db_prefix}messages AS m"; $subject_query['where'][] = 'm.ID_MSG = t.ID_FIRST_MSG'; } foreach ($excludedPhrases as $phrase) { $subject_query['where'][] = 'm.subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . "[[:>:]]'"); } } db_query("\n\t\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_search_results\n\t\t\t\t\t\t(ID_SEARCH, ID_TOPIC, relevance, ID_MSG, num_matches)\n\t\t\t\t\tSELECT \n\t\t\t\t\t\t" . $_SESSION['search_cache']['ID_SEARCH'] . ",\n\t\t\t\t\t\tt.ID_TOPIC,\n\t\t\t\t\t\t1000 * (\n\t\t\t\t\t\t\t{$weight['frequency']} / (t.numReplies + 1) +\n\t\t\t\t\t\t\t{$weight['age']} * IF(t.ID_FIRST_MSG < {$minMsg}, 0, (t.ID_FIRST_MSG - {$minMsg}) / {$recentMsg}) +\n\t\t\t\t\t\t\t{$weight['length']} * IF(t.numReplies < {$humungousTopicPosts}, t.numReplies / {$humungousTopicPosts}, 1) +\n\t\t\t\t\t\t\t{$weight['subject']} +\n\t\t\t\t\t\t\t{$weight['sticky']} * t.isSticky\n\t\t\t\t\t\t) / {$weight_total} AS relevance,\n\t\t\t\t\t\t" . (empty($userQuery) ? 't.ID_FIRST_MSG' : 'm.ID_MSG') . ",\n\t\t\t\t\t\t1\n\t\t\t\t\tFROM (" . implode(', ', $subject_query['from']) . ')' . (empty($subject_query['left_join']) ? '' : "\n\t\t\t\t\t\tLEFT JOIN " . implode("\n\t\t\t\t\t\tLEFT JOIN ", $subject_query['left_join'])) . "\n\t\t\t\t\tWHERE " . implode("\n\t\t\t\t\t\tAND ", $subject_query['where']) . (empty($modSettings['search_max_results']) ? '' : "\n\t\t\t\t\tLIMIT " . ($modSettings['search_max_results'] - $numSubjectResults)), __FILE__, __LINE__); $numSubjectResults += db_affected_rows(); if (!empty($modSettings['search_max_results']) && $numSubjectResults >= $modSettings['search_max_results']) { break; } } $_SESSION['search_cache']['num_results'] = $numSubjectResults; } else { $main_query = array('select' => array('ID_SEARCH' => $_SESSION['search_cache']['ID_SEARCH'], 'relevance' => '0'), 'weights' => array(), 'from' => array("{$db_prefix}topics AS t", "{$db_prefix}messages AS m"), 'left_join' => array(), 'where' => array('t.ID_TOPIC = m.ID_TOPIC'), 'group_by' => array()); if (empty($search_params['topic'])) { $main_query['select']['ID_TOPIC'] = 't.ID_TOPIC'; $main_query['select']['ID_MSG'] = 'MAX(m.ID_MSG) AS ID_MSG'; $main_query['select']['num_matches'] = 'COUNT(*) AS num_matches'; $main_query['weights'] = array('frequency' => 'COUNT(*) / (t.numReplies + 1)', 'age' => "IF(MAX(m.ID_MSG) < {$minMsg}, 0, (MAX(m.ID_MSG) - {$minMsg}) / {$recentMsg})", 'length' => "IF(t.numReplies < {$humungousTopicPosts}, t.numReplies / {$humungousTopicPosts}, 1)", 'subject' => '0', 'first_message' => "IF(MIN(m.ID_MSG) = t.ID_FIRST_MSG, 1, 0)", 'sticky' => 't.isSticky'); $main_query['group_by'][] = 't.ID_TOPIC'; } else { // This is outrageous! $main_query['select']['ID_TOPIC'] = 'm.ID_MSG AS ID_TOPIC'; $main_query['select']['ID_MSG'] = 'm.ID_MSG'; $main_query['select']['num_matches'] = '1 AS num_matches'; $main_query['weights'] = array('age' => "((m.ID_MSG - t.ID_FIRST_MSG) / IF(t.ID_LAST_MSG = t.ID_FIRST_MSG, 1, t.ID_LAST_MSG - t.ID_FIRST_MSG))", 'first_message' => "IF(m.ID_MSG = t.ID_FIRST_MSG, 1, 0)"); $main_query['where'][] = 't.ID_TOPIC = ' . $search_params['topic']; } // *** Get the subject results. $numSubjectResults = 0; if (empty($search_params['topic'])) { // Create a temporary table to store some preliminary results in. db_query("\n\t\t\t\t\tDROP TABLE IF EXISTS {$db_prefix}tmp_log_search_topics", __FILE__, __LINE__); $createTemporary = db_query("\n\t\t\t\t\tCREATE TEMPORARY TABLE {$db_prefix}tmp_log_search_topics (\n\t\t\t\t\t\tID_TOPIC mediumint(8) unsigned NOT NULL default '0',\n\t\t\t\t\t\tPRIMARY KEY (ID_TOPIC)\n\t\t\t\t\t) TYPE=HEAP", false, false) !== false; // Clean up some previous cache. if (!$createTemporary) { db_query("\n\t\t\t\t\t\tDELETE FROM {$db_prefix}log_search_topics\n\t\t\t\t\t\tWHERE ID_SEARCH = " . $_SESSION['search_cache']['ID_SEARCH'], __FILE__, __LINE__); } foreach ($searchWords as $orIndex => $words) { $subject_query = array('from' => array("{$db_prefix}topics AS t"), 'left_join' => array(), 'where' => array()); $numTables = 0; $prev_join = 0; foreach ($words['subject_words'] as $subjectWord) { $numTables++; if (in_array($subjectWord, $excludedSubjectWords)) { if (!in_array("{$db_prefix}messages AS m", $subject_query['from'])) { $subject_query['from'][] = "{$db_prefix}messages AS m"; $subject_query['where'][] = 'm.ID_MSG = t.ID_FIRST_MSG'; } $subject_query['left_join'][] = "{$db_prefix}log_search_subjects AS subj{$numTables} ON (subj{$numTables}.word " . (empty($modSettings['search_match_words']) ? "LIKE '%{$subjectWord}%'" : "= '{$subjectWord}'") . " AND subj{$numTables}.ID_TOPIC = t.ID_TOPIC)"; $subject_query['where'][] = "(subj{$numTables}.word IS NULL)"; $subject_query['where'][] = 'm.body NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($subjectWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $subjectWord), '\\\'') . "[[:>:]]'"); } else { $subject_query['from'][] = "{$db_prefix}log_search_subjects AS subj{$numTables}"; $subject_query['where'][] = "subj{$numTables}.word " . (empty($modSettings['search_match_words']) ? "LIKE '%{$subjectWord}%'" : "= '{$subjectWord}'"); $subject_query['where'][] = "subj{$numTables}.ID_TOPIC = " . ($prev_join === 0 ? 't' : 'subj' . $prev_join) . '.ID_TOPIC'; $prev_join = $numTables; } } if (!empty($userQuery)) { if (!in_array("{$db_prefix}messages AS m", $subject_query['from'])) { $subject_query['from'][] = "{$db_prefix}messages AS m"; $subject_query['where'][] = 'm.ID_MSG = t.ID_FIRST_MSG'; } $subject_query['where'][] = $userQuery; } if (!empty($search_params['topic'])) { $subject_query['where'][] = 't.ID_TOPIC = ' . $search_params['topic']; } if (!empty($minMsgID)) { $subject_query['where'][] = 't.ID_FIRST_MSG >= ' . $minMsgID; } if (!empty($maxMsgID)) { $subject_query['where'][] = 't.ID_LAST_MSG <= ' . $maxMsgID; } if (!empty($boardQuery)) { $subject_query['where'][] = 't.ID_BOARD ' . $boardQuery; } if (!empty($excludedPhrases)) { if (!in_array("{$db_prefix}messages AS m", $subject_query['from'])) { $subject_query['from'][] = "{$db_prefix}messages AS m"; $subject_query['where'][] = 'm.ID_MSG = t.ID_FIRST_MSG'; } foreach ($excludedPhrases as $phrase) { $subject_query['where'][] = 'm.subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . "[[:>:]]'"); $subject_query['where'][] = 'm.body NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . "[[:>:]]'"); } } db_query("\n\t\t\t\t\t\tINSERT IGNORE INTO {$db_prefix}" . ($createTemporary ? 'tmp_' : '') . "log_search_topics\n\t\t\t\t\t\t\t(" . ($createTemporary ? '' : 'ID_SEARCH, ') . "ID_TOPIC)\n\t\t\t\t\t\tSELECT " . ($createTemporary ? '' : $_SESSION['search_cache']['ID_SEARCH'] . ', ') . "t.ID_TOPIC\n\t\t\t\t\t\tFROM (" . implode(', ', $subject_query['from']) . ')' . (empty($subject_query['left_join']) ? '' : "\n\t\t\t\t\t\t\tLEFT JOIN " . implode("\n\t\t\t\t\t\t\tLEFT JOIN ", $subject_query['left_join'])) . "\n\t\t\t\t\t\tWHERE " . implode("\n\t\t\t\t\t\t\tAND ", $subject_query['where']) . (empty($modSettings['search_max_results']) ? '' : "\n\t\t\t\t\t\tLIMIT " . ($modSettings['search_max_results'] - $numSubjectResults)), __FILE__, __LINE__); $numSubjectResults += db_affected_rows(); if (!empty($modSettings['search_max_results']) && $numSubjectResults >= $modSettings['search_max_results']) { break; } } if ($numSubjectResults !== 0) { $main_query['weights']['subject'] = 'IF(lst.ID_TOPIC IS NULL, 0, 1)'; $main_query['left_join'][] = "{$db_prefix}" . ($createTemporary ? 'tmp_' : '') . "log_search_topics AS lst ON (" . ($createTemporary ? '' : 'lst.ID_SEARCH = ' . $_SESSION['search_cache']['ID_SEARCH'] . ' AND ') . "lst.ID_TOPIC = t.ID_TOPIC)"; } } $indexedResults = 0; if (!empty($modSettings['search_index'])) { db_query("\n\t\t\t\t\tDROP TABLE IF EXISTS {$db_prefix}tmp_log_search_messages", __FILE__, __LINE__); $createTemporary = db_query("\n\t\t\t\t\tCREATE TEMPORARY TABLE {$db_prefix}tmp_log_search_messages (\n\t\t\t\t\t\tID_MSG int(10) unsigned NOT NULL default '0',\n\t\t\t\t\t\tPRIMARY KEY (ID_MSG)\n\t\t\t\t\t) TYPE=HEAP", false, false) !== false; if (!$createTemporary) { db_query("\n\t\t\t\t\t\tDELETE FROM {$db_prefix}log_search_messages\n\t\t\t\t\t\tWHERE ID_SEARCH = " . $_SESSION['search_cache']['ID_SEARCH'], __FILE__, __LINE__); } foreach ($searchWords as $orIndex => $words) { // *** Do the fulltext search. if (!empty($words['indexed_words']) && $modSettings['search_index'] == 'fulltext') { $fulltext_query = array('insert_into' => $db_prefix . ($createTemporary ? 'tmp_' : '') . 'log_search_messages', 'select' => array('ID_MSG' => 'ID_MSG'), 'where' => array()); if (!$createTemporary) { $fulltext_query['select']['ID_SEARCH'] = $_SESSION['search_cache']['ID_SEARCH']; } if (empty($modSettings['search_simple_fulltext'])) { foreach ($words['words'] as $regularWord) { $fulltext_query['where'][] = 'body' . (in_array($regularWord, $excludedWords) ? ' NOT' : '') . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($regularWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $regularWord), '\\\'') . "[[:>:]]'"); } } if (!empty($userQuery)) { $fulltext_query['where'][] = strtr($userQuery, array('m.' => '')); } if (!empty($search_params['topic'])) { $fulltext_query['where'][] = 'ID_TOPIC = ' . $search_params['topic']; } if (!empty($minMsgID)) { $fulltext_query['where'][] = 'ID_MSG >= ' . $minMsgID; } if (!empty($maxMsgID)) { $fulltext_query['where'][] = 'ID_MSG <= ' . $maxMsgID; } if (!empty($boardQuery)) { $fulltext_query['where'][] = 'ID_BOARD ' . $boardQuery; } if (!empty($excludedPhrases) && empty($modSettings['search_force_index'])) { foreach ($excludedPhrases as $phrase) { $fulltext_query['where'][] = 'subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . "[[:>:]]'"); } } if (!empty($excludedSubjectWords) && empty($modSettings['search_force_index'])) { foreach ($excludedSubjectWords as $excludedWord) { $fulltext_query['where'][] = 'subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($excludedWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $excludedWord), '\\\'') . "[[:>:]]'"); } } if (!empty($modSettings['search_simple_fulltext'])) { $fulltext_query['where'][] = "MATCH (body) AGAINST ('" . implode(' ', array_diff($words['indexed_words'], $excludedIndexWords)) . "')"; } elseif ($canDoBooleanSearch) { $where = "MATCH (body) AGAINST ('"; foreach ($words['indexed_words'] as $fulltextWord) { $where .= (in_array($fulltextWord, $excludedIndexWords) ? '-' : '+') . $fulltextWord . ' '; } $fulltext_query['where'][] = substr($where, 0, -1) . "' IN BOOLEAN MODE)"; } else { foreach ($words['indexed_words'] as $fulltextWord) { $fulltext_query['where'][] = (in_array($fulltextWord, $excludedIndexWords) ? 'NOT ' : '') . "MATCH (body) AGAINST ('{$fulltextWord}')"; } } db_query("\n\t\t\t\t\t\t\tINSERT IGNORE INTO {$fulltext_query['insert_into']}\n\t\t\t\t\t\t\t\t(" . implode(', ', array_keys($fulltext_query['select'])) . ")\n\t\t\t\t\t\t\tSELECT " . implode(', ', $fulltext_query['select']) . "\n\t\t\t\t\t\t\tFROM {$db_prefix}messages\n\t\t\t\t\t\t\tWHERE " . implode("\n\t\t\t\t\t\t\t\tAND ", $fulltext_query['where']) . (empty($maxMessageResults) ? '' : "\n\t\t\t\t\t\t\tLIMIT " . ($maxMessageResults - $indexedResults)), __FILE__, __LINE__); $indexedResults += db_affected_rows(); if (!empty($maxMessageResults) && $indexedResults >= $maxMessageResults) { break; } } elseif (!empty($words['indexed_words']) && $modSettings['search_index'] == 'custom') { $custom_query = array('insert_into' => $db_prefix . ($createTemporary ? 'tmp_' : '') . 'log_search_messages', 'select' => array('ID_MSG' => 'm.ID_MSG'), 'from' => array("{$db_prefix}messages AS m"), 'left_join' => array(), 'where' => array()); if (!$createTemporary) { $custom_query['select']['ID_SEARCH'] = $_SESSION['search_cache']['ID_SEARCH']; } foreach ($words['words'] as $regularWord) { $custom_query['where'][] = 'm.body' . (in_array($regularWord, $excludedWords) ? ' NOT' : '') . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($regularWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $regularWord), '\\\'') . "[[:>:]]'"); } if (!empty($userQuery)) { $custom_query['where'][] = $userQuery; } if (!empty($search_params['topic'])) { $custom_query['where'][] = 'm.ID_TOPIC = ' . $search_params['topic']; } if (!empty($minMsgID)) { $custom_query['where'][] = 'm.ID_MSG >= ' . $minMsgID; } if (!empty($maxMsgID)) { $custom_query['where'][] = 'm.ID_MSG <= ' . $maxMsgID; } if (!empty($boardQuery)) { $custom_query['where'][] = 'm.ID_BOARD ' . $boardQuery; } if (!empty($excludedPhrases) && empty($modSettings['search_force_index'])) { foreach ($excludedPhrases as $phrase) { $fulltext_query['where'][] = 'subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . "[[:>:]]'"); } } if (!empty($excludedSubjectWords) && empty($modSettings['search_force_index'])) { foreach ($excludedSubjectWords as $excludedWord) { $fulltext_query['where'][] = 'subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($excludedWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $excludedWord), '\\\'') . "[[:>:]]'"); } } $numTables = 0; $prev_join = 0; foreach ($words['indexed_words'] as $indexedWord) { $numTables++; if (in_array($indexedWord, $excludedIndexWords)) { $custom_query['left_join'][] = "{$db_prefix}log_search_words AS lsw{$numTables} ON (lsw{$numTables}.ID_WORD = {$indexedWord} AND lsw{$numTables}.ID_MSG = m.ID_MSG)"; $custom_query['where'][] = "(lsw{$numTables}.ID_WORD IS NULL)"; } else { $custom_query['from'][] = "{$db_prefix}log_search_words AS lsw{$numTables}"; $custom_query['where'][] = "lsw{$numTables}.ID_WORD = {$indexedWord}"; $custom_query['where'][] = "lsw{$numTables}.ID_MSG = " . ($prev_join === 0 ? 'm' : 'lsw' . $prev_join) . '.ID_MSG'; $prev_join = $numTables; } } db_query("\n\t\t\t\t\t\t\tINSERT IGNORE INTO {$custom_query['insert_into']}\n\t\t\t\t\t\t\t\t(" . implode(', ', array_keys($custom_query['select'])) . ")\n\t\t\t\t\t\t\tSELECT " . implode(', ', $custom_query['select']) . "\n\t\t\t\t\t\t\tFROM (" . implode(', ', $custom_query['from']) . ')' . (empty($custom_query['left_join']) ? '' : "\n\t\t\t\t\t\t\t\tLEFT JOIN " . implode("\n\t\t\t\t\t\t\t\tLEFT JOIN ", $custom_query['left_join'])) . "\n\t\t\t\t\t\t\tWHERE " . implode("\n\t\t\t\t\t\t\t\tAND ", $custom_query['where']) . (empty($maxMessageResults) ? '' : "\n\t\t\t\t\t\t\tLIMIT " . ($maxMessageResults - $indexedResults)), __FILE__, __LINE__); $indexedResults += db_affected_rows(); if (!empty($maxMessageResults) && $indexedResults >= $maxMessageResults) { break; } } } if (empty($indexedResults) && empty($numSubjectResults) && !empty($modSettings['search_force_index'])) { $context['search_errors']['query_not_specific_enough'] = true; $_REQUEST['params'] = $context['params']; return PlushSearch1(); } elseif (!empty($indexedResults)) { $main_query['from'][] = $db_prefix . ($createTemporary ? 'tmp_' : '') . 'log_search_messages AS lsm'; $main_query['where'][] = 'lsm.ID_MSG = m.ID_MSG'; if (!$createTemporary) { $main_query['where'][] = 'lsm.ID_SEARCH = ' . $_SESSION['search_cache']['ID_SEARCH']; } } } else { $orWhere = array(); foreach ($searchWords as $orIndex => $words) { $where = array(); foreach ($words['all_words'] as $regularWord) { $where[] = 'm.body' . (in_array($regularWord, $excludedWords) ? ' NOT' : '') . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($regularWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $regularWord), '\\\'') . "[[:>:]]'"); if (in_array($regularWord, $excludedWords)) { $where[] = 'm.subject NOT' . (empty($modSettings['search_match_words']) || $no_regexp ? " LIKE '%" . strtr($regularWord, array('_' => '\\_', '%' => '\\%')) . "%'" : " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $regularWord), '\\\'') . "[[:>:]]'"); } } if (!empty($where)) { $orWhere[] = count($where) > 1 ? '(' . implode(' AND ', $where) . ')' : $where[0]; } } if (!empty($orWhere)) { $main_query['where'][] = count($orWhere) > 1 ? '(' . implode(' OR ', $orWhere) . ')' : $orWhere[0]; } if (!empty($userQuery)) { $main_query['where'][] = $userQuery; } if (!empty($search_params['topic'])) { $main_query['where'][] = 'm.ID_TOPIC = ' . $search_params['topic']; } if (!empty($minMsgID)) { $main_query['where'][] = 'm.ID_MSG >= ' . $minMsgID; } if (!empty($maxMsgID)) { $main_query['where'][] = 'm.ID_MSG <= ' . $maxMsgID; } if (!empty($boardQuery)) { $main_query['where'][] = 'm.ID_BOARD ' . $boardQuery; } } if (!empty($indexedResults) || empty($modSettings['search_index'])) { $relevance = '1000 * ('; $new_weight_total = 0; foreach ($main_query['weights'] as $type => $value) { $relevance .= $weight[$type] . ' * ' . $value . ' + '; $new_weight_total += $weight[$type]; } $main_query['select']['relevance'] = substr($relevance, 0, -3) . ") / {$new_weight_total} AS relevance"; db_query("\n\t\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_search_results\n\t\t\t\t\t\t(" . implode(', ', array_keys($main_query['select'])) . ")\n\t\t\t\t\tSELECT\n\t\t\t\t\t\t" . implode(', ', $main_query['select']) . "\n\t\t\t\t\tFROM (" . implode(', ', $main_query['from']) . ')' . (empty($main_query['left_join']) ? '' : "\n\t\t\t\t\t\tLEFT JOIN " . implode("\n\t\t\t\t\t\tLEFT JOIN ", $main_query['left_join'])) . "\n\t\t\t\t\tWHERE " . implode("\n\t\t\t\t\t\tAND ", $main_query['where']) . (empty($main_query['group_by']) ? '' : "\n\t\t\t\t\tGROUP BY " . implode(', ', $main_query['group_by'])) . (empty($modSettings['search_max_results']) ? '' : "\n\t\t\t\t\tLIMIT {$modSettings['search_max_results']}"), __FILE__, __LINE__); $_SESSION['search_cache']['num_results'] = db_affected_rows(); } // Insert subject-only matches. if ($_SESSION['search_cache']['num_results'] < $modSettings['search_max_results'] && $numSubjectResults !== 0) { db_query("\n\t\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_search_results\n\t\t\t\t\t\t(ID_SEARCH, ID_TOPIC, relevance, ID_MSG, num_matches)\n\t\t\t\t\tSELECT\n\t\t\t\t\t\t" . $_SESSION['search_cache']['ID_SEARCH'] . ",\n\t\t\t\t\t\tt.ID_TOPIC,\n\t\t\t\t\t\t1000 * (\n\t\t\t\t\t\t\t{$weight['frequency']} / (t.numReplies + 1) +\n\t\t\t\t\t\t\t{$weight['age']} * IF(t.ID_FIRST_MSG < {$minMsg}, 0, (t.ID_FIRST_MSG - {$minMsg}) / {$recentMsg}) +\n\t\t\t\t\t\t\t{$weight['length']} * IF(t.numReplies < {$humungousTopicPosts}, t.numReplies / {$humungousTopicPosts}, 1) +\n\t\t\t\t\t\t\t{$weight['subject']} +\n\t\t\t\t\t\t\t{$weight['sticky']} * t.isSticky\n\t\t\t\t\t\t) / {$weight_total} AS relevance,\n\t\t\t\t\t\tt.ID_FIRST_MSG,\n\t\t\t\t\t\t1\n\t\t\t\t\tFROM ({$db_prefix}topics AS t, {$db_prefix}" . ($createTemporary ? 'tmp_' : '') . "log_search_topics AS lst)\n\t\t\t\t\tWHERE lst.ID_TOPIC = t.ID_TOPIC" . (empty($modSettings['search_max_results']) ? '' : "\n\t\t\t\t\tLIMIT " . ($modSettings['search_max_results'] - $_SESSION['search_cache']['num_results'])), __FILE__, __LINE__); $_SESSION['search_cache']['num_results'] += db_affected_rows(); } elseif ($_SESSION['search_cache']['num_results'] == -1) { $_SESSION['search_cache']['num_results'] = 0; } } } // *** Retrieve the results to be shown on the page $participants = array(); $request = db_query("\n\t\tSELECT " . (empty($search_params['topic']) ? 'lsr.ID_TOPIC' : $search_params['topic'] . ' AS ID_TOPIC') . ", lsr.ID_MSG, lsr.relevance, lsr.num_matches\n\t\tFROM ({$db_prefix}log_search_results AS lsr" . ($search_params['sort'] == 'numReplies' ? ", {$db_prefix}topics AS t" : '') . ")\n\t\tWHERE ID_SEARCH = " . $_SESSION['search_cache']['ID_SEARCH'] . ($search_params['sort'] == 'numReplies' ? "\n\t\t\tAND t.ID_TOPIC = lsr.ID_TOPIC" : '') . "\n\t\tORDER BY {$search_params['sort']} {$search_params['sort_dir']}\n\t\tLIMIT " . (int) $_REQUEST['start'] . ", {$modSettings['search_results_per_page']}", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) { $context['topics'][$row['ID_MSG']] = array('id' => $row['ID_TOPIC'], 'relevance' => round($row['relevance'] / 10, 1) . '%', 'num_matches' => $row['num_matches'], 'matches' => array()); // By default they didn't participate in the topic! $participants[$row['ID_TOPIC']] = false; } mysql_free_result($request); // Now that we know how many results to expect we can start calculating the page numbers. $context['page_index'] = constructPageIndex($scripturl . '?action=search2;params=' . $context['params'], $_REQUEST['start'], $_SESSION['search_cache']['num_results'], $modSettings['search_results_per_page'], false); if (!empty($context['topics'])) { // Create an array for the permissions. $boards_can = array('post_reply_own' => boardsAllowedTo('post_reply_own'), 'post_reply_any' => boardsAllowedTo('post_reply_any'), 'mark_any_notify' => boardsAllowedTo('mark_any_notify')); // How's about some quick moderation? if (!empty($options['display_quick_mod']) && !empty($context['topics'])) { $boards_can['lock_any'] = boardsAllowedTo('lock_any'); $boards_can['lock_own'] = boardsAllowedTo('lock_own'); $boards_can['make_sticky'] = boardsAllowedTo('make_sticky'); $boards_can['move_any'] = boardsAllowedTo('move_any'); $boards_can['move_own'] = boardsAllowedTo('move_own'); $boards_can['remove_any'] = boardsAllowedTo('remove_any'); $boards_can['remove_own'] = boardsAllowedTo('remove_own'); $boards_can['merge_any'] = boardsAllowedTo('merge_any'); $context['can_lock'] = in_array(0, $boards_can['lock_any']); $context['can_sticky'] = in_array(0, $boards_can['make_sticky']) && !empty($modSettings['enableStickyTopics']); $context['can_move'] = in_array(0, $boards_can['move_any']); $context['can_remove'] = in_array(0, $boards_can['remove_any']); $context['can_merge'] = in_array(0, $boards_can['merge_any']); } // Load the posters... $request = db_query("\n\t\t\tSELECT ID_MEMBER\n\t\t\tFROM {$db_prefix}messages\n\t\t\tWHERE ID_MEMBER != 0\n\t\t\t\tAND ID_MSG IN (" . implode(', ', array_keys($context['topics'])) . ")\n\t\t\tLIMIT " . count($context['topics']), __FILE__, __LINE__); $posters = array(); while ($row = mysql_fetch_assoc($request)) { $posters[] = $row['ID_MEMBER']; } mysql_free_result($request); if (!empty($posters)) { loadMemberData(array_unique($posters)); } // Get the messages out for the callback - select enough that it can be made to look just like Display. $messages_request = db_query("\n\t\t\tSELECT\n\t\t\t\tm.ID_MSG, m.subject, m.posterName, m.posterEmail, m.posterTime, m.ID_MEMBER,\n\t\t\t\tm.icon, m.posterIP, m.body, m.smileysEnabled, m.modifiedTime, m.modifiedName,\n\t\t\t\tfirst_m.ID_MSG AS first_msg, first_m.subject AS first_subject, first_m.icon AS firstIcon, first_m.posterTime AS first_posterTime,\n\t\t\t\tfirst_mem.ID_MEMBER AS first_member_id, IFNULL(first_mem.realName, first_m.posterName) AS first_member_name,\n\t\t\t\tlast_m.ID_MSG AS last_msg, last_m.posterTime AS last_posterTime, last_mem.ID_MEMBER AS last_member_id,\n\t\t\t\tIFNULL(last_mem.realName, last_m.posterName) AS last_member_name, last_m.icon AS lastIcon, last_m.subject AS last_subject,\n\t\t\t\tt.ID_TOPIC, t.isSticky, t.locked, t.ID_POLL, t.numReplies, t.numViews,\n\t\t\t\tb.ID_BOARD, b.name AS bName, c.ID_CAT, c.name AS cName\n\t\t\tFROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t, {$db_prefix}boards AS b, {$db_prefix}categories AS c, {$db_prefix}messages AS first_m, {$db_prefix}messages AS last_m)\n\t\t\t\tLEFT JOIN {$db_prefix}members AS first_mem ON (first_mem.ID_MEMBER = first_m.ID_MEMBER)\n\t\t\t\tLEFT JOIN {$db_prefix}members AS last_mem ON (last_mem.ID_MEMBER = first_m.ID_MEMBER)\n\t\t\tWHERE m.ID_MSG IN (" . implode(', ', array_keys($context['topics'])) . ")\n\t\t\t\tAND t.ID_TOPIC = m.ID_TOPIC\n\t\t\t\tAND b.ID_BOARD = t.ID_BOARD\n\t\t\t\tAND c.ID_CAT = b.ID_CAT\n\t\t\t\tAND first_m.ID_MSG = t.ID_FIRST_MSG\n\t\t\t\tAND last_m.ID_MSG = t.ID_LAST_MSG\n\t\t\tORDER BY FIND_IN_SET(m.ID_MSG, '" . implode(',', array_keys($context['topics'])) . "')\n\t\t\tLIMIT " . count($context['topics']), __FILE__, __LINE__); // Note that the reg-exp slows things alot, but makes things make a lot more sense. // If we want to know who participated in what then load this now. if (!empty($modSettings['enableParticipation']) && !$user_info['is_guest']) { $result = db_query("\n\t\t\t\tSELECT ID_TOPIC\n\t\t\t\tFROM {$db_prefix}messages\n\t\t\t\tWHERE ID_TOPIC IN (" . implode(', ', array_keys($participants)) . ")\n\t\t\t\t\tAND ID_MEMBER = {$ID_MEMBER}\n\t\t\t\tGROUP BY ID_TOPIC\n\t\t\t\tLIMIT " . count($participants), __FILE__, __LINE__); while ($row = mysql_fetch_assoc($result)) { $participants[$row['ID_TOPIC']] = true; } mysql_free_result($result); } } // Consider the search complete! if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) { cache_put_data('search_start:' . ($user_info['is_guest'] ? $user_info['ip'] : $ID_MEMBER), null, 90); } $context['key_words'] =& $searchArray; // Set the basic stuff for the template. $context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']); // Setup the default topic icons... for checking they exist and the like! $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless'); $context['icon_sources'] = array(); foreach ($stable_icons as $icon) { $context['icon_sources'][$icon] = 'images_url'; } $context['sub_template'] = 'results'; $context['page_title'] = $txt[166]; $context['get_topics'] = 'prepareSearchContext'; $context['can_send_pm'] = allowedTo('pm_send'); loadJumpTo(); if (!empty($options['display_quick_mod']) && !empty($_SESSION['move_to_topic'])) { foreach ($context['jump_to'] as $id => $cat) { if (isset($context['jump_to'][$id]['boards'][$_SESSION['move_to_topic']])) { $context['jump_to'][$id]['boards'][$_SESSION['move_to_topic']]['selected'] = true; } } } }
function ModifyProfile($post_errors = array()) { global $txt, $scripturl, $user_info, $context, $sourcedir, $user_profile, $cur_profile; global $modSettings, $memberContext, $profile_vars, $smcFunc, $post_errors, $options, $user_settings; // Don't reload this as we may have processed error strings. if (empty($post_errors)) { loadLanguage('Profile'); } loadTemplate('Profile'); require_once $sourcedir . '/Subs-Menu.php'; // Did we get the user by name... if (isset($_REQUEST['user'])) { $memberResult = loadMemberData($_REQUEST['user'], true, 'profile'); } elseif (!empty($_REQUEST['u'])) { $memberResult = loadMemberData((int) $_REQUEST['u'], false, 'profile'); } else { $memberResult = loadMemberData($user_info['id'], false, 'profile'); } // Check if loadMemberData() has returned a valid result. if (!is_array($memberResult)) { fatal_lang_error('not_a_user', false); } // If all went well, we have a valid member ID! list($memID) = $memberResult; $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 SMF takes this and turns 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' => 'Profile-View.php', 'function' => 'summary', 'permission' => array('own' => 'profile_view_own', 'any' => 'profile_view_any')), 'statistics' => array('label' => $txt['statPanel'], 'file' => 'Profile-View.php', 'function' => 'statPanel', 'permission' => array('own' => 'profile_view_own', 'any' => 'profile_view_any')), 'showposts' => array('label' => $txt['showPosts'], 'file' => 'Profile-View.php', 'function' => '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')), 'attach' => array($txt['showAttachments'], array('profile_view_own', 'profile_view_any'))), 'permission' => array('own' => 'profile_view_own', 'any' => 'profile_view_any')), 'permissions' => array('label' => $txt['showPermissions'], 'file' => 'Profile-View.php', 'function' => 'showPermissions', 'permission' => array('own' => 'manage_permissions', 'any' => 'manage_permissions')), 'tracking' => array('label' => $txt['trackUser'], 'file' => 'Profile-View.php', 'function' => 'tracking', 'subsections' => array('activity' => array($txt['trackActivity'], 'moderate_forum'), 'ip' => array($txt['trackIP'], 'moderate_forum'), 'edits' => array($txt['trackEdits'], 'moderate_forum')), 'permission' => array('own' => 'moderate_forum', 'any' => 'moderate_forum')), 'viewwarning' => array('label' => $txt['profile_view_warnings'], 'enabled' => in_array('w', $context['admin_features']) && $modSettings['warning_settings'][0] == 1 && $cur_profile['warning'] && $context['user']['is_owner'] && !empty($modSettings['warning_show']), 'file' => 'Profile-View.php', 'function' => 'viewWarning', 'permission' => array('own' => 'profile_view_own', 'any' => 'issue_warning')))), 'edit_profile' => array('title' => $txt['profileEdit'], 'areas' => array('account' => array('label' => $txt['account'], 'file' => 'Profile-Modify.php', 'function' => 'account', 'enabled' => $context['user']['is_admin'] || $cur_profile['id_group'] != 1 && !in_array(1, explode(',', $cur_profile['additional_groups'])), 'sc' => 'post', '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' => 'Profile-Modify.php', 'function' => 'forumProfile', 'sc' => 'post', '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' => 'Profile-Modify.php', 'function' => 'theme', 'sc' => 'post', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array('profile_extra_any'))), 'authentication' => array('label' => $txt['authentication'], 'file' => 'Profile-Modify.php', 'function' => 'authentication', 'enabled' => !empty($modSettings['enableOpenID']) || !empty($cur_profile['openid_uri']), 'sc' => 'post', '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['notification'], 'file' => 'Profile-Modify.php', 'function' => 'notification', 'sc' => 'post', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array('profile_extra_any'))), 'pmprefs' => array('label' => $txt['pmprefs'], 'file' => 'Profile-Modify.php', 'function' => 'pmprefs', 'enabled' => allowedTo(array('profile_extra_own', 'profile_extra_any')), 'sc' => 'post', 'permission' => array('own' => array('pm_read'), 'any' => array('profile_extra_any'))), 'ignoreboards' => array('label' => $txt['ignoreboards'], 'file' => 'Profile-Modify.php', 'function' => 'ignoreboards', 'enabled' => !empty($modSettings['allow_ignore_boards']), 'sc' => 'post', 'permission' => array('own' => array('profile_extra_any', 'profile_extra_own'), 'any' => array('profile_extra_any'))), 'lists' => array('label' => $txt['editBuddyIgnoreLists'], 'file' => 'Profile-Modify.php', 'function' => 'editBuddyIgnoreLists', 'enabled' => !empty($modSettings['enable_buddylist']) && $context['user']['is_owner'], 'sc' => 'post', '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' => 'Profile-Modify.php', 'function' => 'groupMembership', 'enabled' => !empty($modSettings['show_group_membership']) && $context['user']['is_owner'], 'sc' => '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']) && $modSettings['warning_settings'][0] == 1 && (!$context['user']['is_owner'] || $context['user']['is_admin']), 'file' => 'Profile-Actions.php', 'function' => 'issueWarning', 'permission' => array('own' => array('issue_warning'), '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' => 'Profile-Actions.php', 'function' => 'subscriptions', 'enabled' => !empty($modSettings['paid_enabled']), 'permission' => array('own' => array('profile_view_own'), 'any' => array('moderate_forum'))), 'deleteaccount' => array('label' => $txt['deleteAccount'], 'file' => 'Profile-Actions.php', 'function' => 'deleteAccount', 'sc' => 'post', 'password' => true, 'permission' => array('own' => array('profile_remove_any', 'profile_remove_own'), 'any' => array('profile_remove_any'))), 'activateaccount' => array('file' => 'Profile-Actions.php', 'function' => 'activateAccount', 'sc' => 'get', 'permission' => array('own' => array(), 'any' => array('moderate_forum')))))); // Let them modify profile areas easily. call_integration_hook('integrate_profile_areas', array(&$profile_areas)); // Do some cleaning ready for the menu function. $context['password_areas'] = array(); $current_area = isset($_REQUEST['area']) ? $_REQUEST['area'] : ''; foreach ($profile_areas as $section_id => $section) { // Do a bit of spring cleaning so to speak. foreach ($section['areas'] as $area_id => $area) { // If it said no permissions that meant it wasn't valid! if (empty($area['permission'][$context['user']['is_owner'] ? 'own' : 'any'])) { $profile_areas[$section_id]['areas'][$area_id]['enabled'] = false; } else { $profile_areas[$section_id]['areas'][$area_id]['permission'] = $area['permission'][$context['user']['is_owner'] ? 'own' : 'any']; } // Password required - only if not on OpenID. if (!empty($area['password'])) { $context['password_areas'][] = $area_id; } } } // 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, 'current_area' => $current_area, 'extra_url_parameters' => array('u' => $context['id_member'])); // Actually create the menu! $profile_include_data = createMenu($profile_areas, $menuOptions); // No menu means no access. if (!$profile_include_data && (!$user_info['is_guest'] || validateSession())) { 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 every compromise the menu function in error! $context['completed_save'] = false; $security_checks = array(); $found_area = false; foreach ($profile_areas as $section_id => $section) { // Do a bit of spring cleaning so to speak. foreach ($section['areas'] as $area_id => $area) { // Is this our area? if ($current_area == $area_id) { // This can't happen - but is a security check. if (isset($section['enabled']) && $section['enabled'] == false || isset($area['enabled']) && $area['enabled'] == false) { fatal_lang_error('no_access', false); } // Are we saving data in a valid area? if (isset($area['sc']) && isset($_REQUEST['save'])) { $security_checks['session'] = $area['sc']; $context['completed_save'] = true; } // Does this require session validating? if (!empty($area['validate'])) { $security_checks['validate'] = true; } // Permissions for good measure. if (!empty($profile_include_data['permission'])) { $security_checks['permission'] = $profile_include_data['permission']; } // Either way got something. $found_area = true; } } } // Oh dear, some serious security lapse is going on here... we'll put a stop to that! if (!$found_area) { fatal_lang_error('no_access', false); } // Release this now. unset($profile_areas); // Now the context is setup have we got any security checks to carry out additional to that above? if (isset($security_checks['session'])) { checkSession($security_checks['session']); } if (isset($security_checks['validate'])) { validateSession(); } if (isset($security_checks['permission'])) { isAllowedTo($security_checks['permission']); } // File to include? if (isset($profile_include_data['file'])) { require_once $sourcedir . '/' . $profile_include_data['file']; } // Make sure that the area function does exist! if (!isset($profile_include_data['function']) || !function_exists($profile_include_data['function'])) { destroyMenu(); fatal_lang_error('no_access', false); } // 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 and add the profile layer. $context['sub_template'] = $profile_include_data['function']; $context['template_layers'][] = 'profile'; // All the subactions that require a user password in order to validate. $check_password = $context['user']['is_owner'] && in_array($profile_include_data['current_area'], $context['password_areas']); $context['require_password'] = $check_password && empty($user_settings['openid_uri']); // If we're in wireless then we have a cut down template... if (WIRELESS && $context['sub_template'] == 'summary' && WIRELESS_PROTOCOL != 'wap') { $context['sub_template'] = WIRELESS_PROTOCOL . '_profile'; } // 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 ($context['completed_save']) { // If it's someone elses profile then validate the session. if (!$context['user']['is_owner']) { validateSession(); } // 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 $sourcedir . '/Subs-OpenID.php'; smf_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); // Bad password!!! if (!$good_password && $user_info['passwd'] != sha1(strtolower($cur_profile['member_name']) . $_POST['oldpasswrd'])) { $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)) { activateAccount($memID); } } elseif ($current_area == 'deleteaccount') { if (empty($post_errors)) { deleteAccount2($profile_vars, $post_errors, $memID); redirectexit(); } } elseif ($current_area == 'groupmembership' && empty($post_errors)) { $msg = groupMembership2($profile_vars, $post_errors, $memID); // 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') { authentication($memID, true); } elseif (in_array($current_area, array('account', 'forumprofile', 'theme', 'pmprefs'))) { saveProfileFields(); } else { $force_redirect = true; // Ensure we include this. require_once $sourcedir . '/Profile-Modify.php'; saveProfileChanges($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, 'id_log' => 2, 'log_time' => time(), 'id_member' => $memID, 'ip' => $user_info['ip'], 'extra' => serialize(array_merge($v, array('applicator' => $user_info['id'])))); } $smcFunc['db_insert']('', '{db_prefix}log_actions', array('action' => 'string', 'id_log' => 'int', 'log_time' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'extra' => 'string-65534'), $log_changes, array('id_action')); } // 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']) { redirectexit('action=profile;area=' . $current_area . ';updated'); } elseif (!empty($force_redirect)) { redirectexit('action=profile' . ($context['user']['is_owner'] ? '' : ';u=' . $memID) . ';area=' . $current_area); } // Call the appropriate subaction function. $profile_include_data['function']($memID); // 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] : ''); } }
/** * Gather the data and prepare to display the ticket blocks. * * Actually performs the queries to get data for each block, subject to the parameters specified by the calling functions. * * It also sets up per-block pagination links, collects a variety of data (enough to populate all the columns as listed in shd_main_helpdesk, * even if not entirely applicable, and populates it all into $context['ticket_blocks']['tickets'], extending the array that was * already there. * * @see shd_main_helpdesk() * @see shd_closed_tickets() * @see shd_recycle_bin() * @since 1.0 */ function shd_helpdesk_listing() { global $context, $txt, $smcFunc, $user_profile, $scripturl, $settings, $user_info, $modSettings, $language; if (!empty($context['shd_permission'])) { shd_is_allowed_to($context['shd_permission']); } $block_list = array_keys($context['ticket_blocks']); $primary_url = '?action=helpdesk;sa=' . $_REQUEST['sa']; // First figure out the start positions of each item and sanitise them foreach ($context['ticket_blocks'] as $block_key => $block) { if (empty($block['viewing_as_block'])) { $num_per_page = !empty($context['shd_preferences']['blocks_' . $block_key . '_count']) ? $context['shd_preferences']['blocks_' . $block_key . '_count'] : $context['items_per_page']; $start = empty($_REQUEST['st_' . $block_key]) ? 0 : (int) $_REQUEST['st_' . $block_key]; $max_value = $block['count']; // easier to read } else { $num_per_page = $context['items_per_page']; $max_value = $context['items_per_page']; $start = 0; } if ($start < 0) { $start = 0; } elseif ($start >= $max_value) { $start = max(0, (int) $max_value - ((int) $max_value % (int) $num_per_page == 0 ? $num_per_page : (int) $max_value % (int) $num_per_page)); } else { $start = max(0, (int) $start - (int) $start % (int) $num_per_page); } $context['ticket_blocks'][$block_key]['start'] = $start; $context['ticket_blocks'][$block_key]['num_per_page'] = $num_per_page; if ($start != 0) { $_REQUEST['st_' . $block_key] = $start; } elseif (isset($_REQUEST['st_' . $block_key])) { unset($_REQUEST['st_' . $block_key]); } } // Now ordering the columns, separate loop for breaking the two processes apart $sort_methods = array('ticketid' => array('sql' => 'hdt.id_ticket'), 'ticketname' => array('sql' => 'hdt.subject'), 'replies' => array('sql' => 'hdt.num_replies'), 'allreplies' => array('sql' => '(hdt.num_replies + hdt.deleted_replies)'), 'urgency' => array('sql' => 'hdt.urgency'), 'updated' => array('sql' => 'hdt.last_updated'), 'assigned' => array('sql' => 'assigned_name', 'sql_select' => 'IFNULL(mem.real_name, 0) AS assigned_name', 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_assigned = mem.id_member)'), 'status' => array('sql' => 'hdt.status'), 'starter' => array('sql' => 'starter_name', 'sql_select' => 'IFNULL(mem.real_name, 0) AS starter_name', 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_started = mem.id_member)'), 'lastreply' => array('sql' => 'last_reply', 'sql_select' => 'IFNULL(mem.real_name, 0) AS last_reply', 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdtr_last.id_member = mem.id_member)')); foreach ($context['ticket_blocks'] as $block_key => $block) { $sort = isset($_REQUEST['so_' . $block_key]) ? $_REQUEST['so_' . $block_key] : (!empty($context['shd_preferences']['block_order_' . $block_key . '_block']) ? $context['shd_preferences']['block_order_' . $block_key . '_block'] : ''); if (strpos($sort, '_') > 0 && substr_count($sort, '_') == 1) { list($sort_item, $sort_dir) = explode('_', $sort); if (empty($sort_methods[$sort_item])) { $sort_item = 'updated'; $sort = ''; } if (!in_array($sort_dir, array('asc', 'desc'))) { $sort = ''; $sort_dir = 'asc'; } } else { $sort = ''; $sort_item = 'updated'; $sort_dir = $_REQUEST['sa'] == 'closedtickets' || $_REQUEST['sa'] == 'recyclebin' ? 'desc' : 'asc'; // default to newest first if on recyclebin or closed tickets, otherwise oldest first } if ($sort != '') { $_REQUEST['so_' . $block_key] = $sort; } elseif (isset($_REQUEST['so_' . $block_key])) { unset($_REQUEST['so_' . $block_key]); } $context['ticket_blocks'][$block_key]['sort'] = array('item' => $sort_item, 'direction' => $sort_dir, 'add_link' => $sort != '', 'sql' => array('select' => !empty($sort_methods[$sort_item]['sql_select']) ? $sort_methods[$sort_item]['sql_select'] : '', 'join' => !empty($sort_methods[$sort_item]['sql_join']) ? $sort_methods[$sort_item]['sql_join'] : '', 'sort' => $sort_methods[$sort_item]['sql'] . ' ' . strtoupper($sort_dir)), 'link_bits' => array()); } // Having got all that, step through the blocks again to determine the full URL fragments foreach ($context['ticket_blocks'] as $block_key => $block) { foreach ($sort_methods as $method => $sort_details) { $context['ticket_blocks'][$block_key]['sort']['link_bits'][$method] = ';so_' . $block_key . '=' . $method . '_' . $block['sort']['direction']; } } // Figure out if the user is filtering on anything, and if so, set up containers for the extra joins, selects, pagination link fragments, etc $_REQUEST['field'] = isset($_REQUEST['field']) ? (int) $_REQUEST['field'] : 0; $_REQUEST['filter'] = isset($_REQUEST['filter']) ? (int) $_REQUEST['filter'] : 0; if ($_REQUEST['field'] > 0 && $_REQUEST['filter'] > 0) { $context['filter_fragment'] = ';field=' . $_REQUEST['field'] . ';filter=' . $_REQUEST['filter']; $context['filter_join'] = ' INNER JOIN {db_prefix}helpdesk_custom_fields_values AS hdcfv ON (hdcfv.id_post = hdt.id_ticket AND hdcfv.id_field = {int:field} AND hdcfv.post_type = {int:type_ticket}) INNER JOIN {db_prefix}helpdesk_custom_fields AS hdcf ON (hdcf.id_field = hdcfv.id_field AND hdcf.active = {int:active})'; $context['filter_where'] = ' AND hdcfv.value = {string:filter}'; } else { $context['filter_fragment'] = ''; $context['filter_join'] = ''; $context['filter_where'] = ''; } // Now go actually do the whole block thang, setting up space for a list of users and tickets as we go along $users = array(); $tickets = array(); foreach ($context['ticket_blocks'] as $block_key => $block) { if (empty($block['display']) || !empty($block['collapsed'])) { continue; } $context['ticket_blocks'][$block_key]['tickets'] = array(); // If we're filtering, we have to query it first to figure out how many rows there are in this block. It's not pretty. if (!empty($context['filter_join'])) { $query = shd_db_query('', ' SELECT COUNT(hdt.id_ticket) FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept) ' . (!empty($block['sort']['sql']['join']) ? $block['sort']['sql']['join'] : '') . $context['filter_join'] . ' WHERE {query_see_ticket}' . (!empty($block['where']) ? ' AND ' . $block['where'] : '') . (!empty($context['shd_department']) ? ' AND hdt.id_dept = {int:dept}' : '') . $context['filter_where'], array('dept' => $context['shd_department'], 'user' => $context['user']['id'], 'field' => $_REQUEST['field'], 'filter' => $_REQUEST['filter'], 'type_ticket' => CFIELD_TICKET, 'active' => 1)); list($context['ticket_blocks'][$block_key]['count']) = $smcFunc['db_fetch_row']($query); $block['count'] = $context['ticket_blocks'][$block_key]['count']; $smcFunc['db_free_result']($query); if ($block['start'] >= $block['count']) { $context['ticket_blocks'][$block_key]['start'] = max(0, (int) $block['count'] - ((int) $block['count'] % (int) $block['num_per_page'] == 0 ? $block['num_per_page'] : (int) $block['count'] % (int) $block['num_per_page'])); $block['start'] = $context['ticket_blocks'][$block_key]['start']; } } $query = shd_db_query('', ' SELECT hdt.id_ticket, hdt.id_dept, hdd.dept_name, hdt.id_last_msg, hdt.id_member_started, hdt.id_member_updated, hdt.id_member_assigned, hdt.subject, hdt.status, hdt.num_replies, hdt.deleted_replies, hdt.private, hdt.urgency, hdt.last_updated, hdtr_first.poster_name AS ticket_opener, hdtr_last.poster_name AS respondent, hdtr_last.poster_time, IFNULL(hdlr.id_msg, 0) AS log_read' . (!empty($block['sort']['sql']['select']) ? ', ' . $block['sort']['sql']['select'] : '') . ' FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept) LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdt.id_ticket = hdlr.id_ticket AND hdlr.id_member = {int:user}) ' . (!empty($block['sort']['sql']['join']) ? $block['sort']['sql']['join'] : '') . $context['filter_join'] . ' WHERE {query_see_ticket}' . (!empty($block['where']) ? ' AND ' . $block['where'] : '') . (!empty($context['shd_department']) ? ' AND hdt.id_dept = {int:dept}' : '') . $context['filter_where'] . ' ORDER BY ' . (!empty($block['sort']['sql']['sort']) ? $block['sort']['sql']['sort'] : 'hdt.id_last_msg ASC') . ' LIMIT {int:start}, {int:items_per_page}', array('dept' => $context['shd_department'], 'user' => $context['user']['id'], 'start' => $block['start'], 'items_per_page' => $block['num_per_page'], 'field' => $_REQUEST['field'], 'filter' => $_REQUEST['filter'], 'type_ticket' => CFIELD_TICKET, 'active' => 1)); while ($row = $smcFunc['db_fetch_assoc']($query)) { $is_own = $user_info['id'] == $row['id_member_started']; censorText($row['subject']); $new_block = array('id' => $row['id_ticket'], 'display_id' => str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT), 'dept_link' => empty($context['shd_department']) && $context['shd_multi_dept'] ? '[<a href="' . $scripturl . '?' . $context['shd_home'] . ';dept=' . $row['id_dept'] . '">' . $row['dept_name'] . '</a>] ' : '', 'link' => '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '">' . $row['subject'] . '</a>', 'subject' => $row['subject'], 'status' => array('level' => $row['status'], 'label' => $txt['shd_status_' . $row['status']]), 'starter' => array('id' => $row['id_member_started'], 'name' => $row['ticket_opener']), 'last_update' => timeformat($row['last_updated']), 'assigned' => array('id' => $row['id_member_assigned']), 'respondent' => array('id' => $row['id_member_updated'], 'name' => $row['respondent']), 'urgency' => array('level' => $row['urgency'], 'label' => $row['urgency'] > TICKET_URGENCY_HIGH ? '<span class="error">' . $txt['shd_urgency_' . $row['urgency']] . '</span>' : $txt['shd_urgency_' . $row['urgency']]), 'is_unread' => $row['id_last_msg'] > $row['log_read'], 'new_href' => $row['id_last_msg'] <= $row['log_read'] ? '' : $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . '.new' . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '#new', 'private' => $row['private'], 'actions' => array('movedept' => !empty($context['shd_multi_dept']) && (shd_allowed_to('shd_move_dept_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_move_dept_own', $context['shd_department'])) ? '<a href="' . $scripturl . '?action=helpdesk;sa=movedept;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_move_dept'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/movedept.png" alt="' . $txt['shd_move_dept'] . '" /></a>' : ''), 'num_replies' => $row['num_replies'], 'replies_href' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . '.msg' . $row['id_last_msg'] . '#msg' . $row['id_last_msg'] . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : ''), 'all_replies' => (int) $row['num_replies'] + (int) $row['deleted_replies']); if ($row['status'] == TICKET_STATUS_CLOSED) { $new_block['actions'] += array('resolve' => shd_allowed_to('shd_unresolve_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_unresolve_ticket_own', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $row['id_ticket'] . ';home;' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_unresolved'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/unresolved.png" alt="' . $txt['shd_ticket_unresolved'] . '" /></a>' : ''); } elseif ($row['status'] == TICKET_STATUS_DELETED) { $new_block['actions'] += array('restore' => shd_allowed_to('shd_restore_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_restore_ticket_own', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=restoreticket;ticket=' . $row['id_ticket'] . ';home;' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_restore'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/restore.png" alt="' . $txt['shd_ticket_restore'] . '" /></a>' : '', 'permadelete' => shd_allowed_to('shd_delete_recycling', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=permadelete;ticket=' . $row['id_ticket'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_delete_permanently'] . '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_permanently_confirm']) . ');"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_delete_permanently'] . '" /></a>' : ''); } else { $langstring = ''; if (shd_allowed_to('shd_assign_ticket_any', $context['shd_department'])) { $langstring = empty($row['id_member_assigned']) ? $txt['shd_ticket_assign'] : $txt['shd_ticket_reassign']; } elseif (shd_allowed_to('shd_assign_ticket_own', $context['shd_department']) && (empty($row['id_member_assigned']) || $row['id_member_assigned'] == $context['user']['id'])) { $langstring = $row['id_member_assigned'] == $context['user']['id'] ? $txt['shd_ticket_unassign'] : $txt['shd_ticket_assign_self']; } if (!empty($langstring)) { $new_block['actions']['assign'] = '<a href="' . $scripturl . '?action=helpdesk;sa=assign;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $langstring . '"><img src="' . $settings['default_images_url'] . '/simpledesk/assign.png" alt="' . $langstring . '" /></a>'; } $new_block['actions'] += array('resolve' => shd_allowed_to('shd_resolve_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_resolve_ticket_own', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $row['id_ticket'] . ';home;' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_resolved'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/resolved.png" alt="' . $txt['shd_ticket_resolved'] . '" /></a>' : '', 'tickettotopic' => empty($modSettings['shd_helpdesk_only']) && shd_allowed_to('shd_ticket_to_topic', $context['shd_department']) && ($row['deleted_replies'] == 0 || shd_allowed_to('shd_access_recyclebin')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=tickettotopic;ticket=' . $row['id_ticket'] . ';' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_move_to_topic'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/tickettotopic.png" alt="' . $txt['shd_ticket_move_to_topic'] . '" /></a>' : '', 'delete' => shd_allowed_to('shd_delete_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_delete_ticket_own') ? '<a href="' . $scripturl . '?action=helpdesk;sa=deleteticket;ticket=' . $row['id_ticket'] . ';' . $context['shd_dept_link'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_delete'] . '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_confirm']) . ');"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_ticket_delete'] . '" /></a>' : ''); } $context['ticket_blocks'][$block_key]['tickets'][$row['id_ticket']] = $new_block; $users[] = $row['id_member_started']; $users[] = $row['id_member_updated']; $users[] = $row['id_member_assigned']; $tickets[$row['id_ticket']] = array(); } $smcFunc['db_free_result']($query); } $users = array_unique($users); if (!empty($users)) { loadMemberData($users, false, 'minimal'); } foreach ($context['ticket_blocks'] as $block_id => $block) { if (empty($block['tickets'])) { continue; } foreach ($block['tickets'] as $tid => $ticket) { // Set up names and profile links for topic starter if (!empty($user_profile[$ticket['starter']['id']])) { // We found the name, so let's use their current name and profile link $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['name'] = $user_profile[$ticket['starter']['id']]['real_name']; $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['link'] = shd_profile_link($user_profile[$ticket['starter']['id']]['real_name'], $ticket['starter']['id']); } else { // We didn't, so keep using the name we found previously and don't make an actual link $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['link'] = $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['name']; } // Set up names and profile links for assigned user if ($ticket['assigned']['id'] == 0 || empty($user_profile[$ticket['assigned']['id']])) { $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['name'] = $txt['shd_unassigned']; $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['link'] = '<span class="error">' . $txt['shd_unassigned'] . '</span>'; } else { $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['name'] = $user_profile[$ticket['assigned']['id']]['real_name']; $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['link'] = shd_profile_link($user_profile[$ticket['assigned']['id']]['real_name'], $ticket['assigned']['id']); } // And last respondent if ($ticket['respondent']['id'] == 0 || empty($user_profile[$ticket['respondent']['id']])) { // Didn't find the name, so reuse what we have $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['link'] = $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['name']; } else { $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['name'] = $user_profile[$ticket['respondent']['id']]['real_name']; $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['link'] = shd_profile_link($user_profile[$ticket['respondent']['id']]['real_name'], $ticket['respondent']['id']); } } } foreach ($context['ticket_blocks'] as $block_id => $block) { if (empty($block['display']) || empty($block['count']) && !$block['required'] && empty($block['collapsed'])) { unset($context['ticket_blocks'][$block_id]); } } $base_url = ''; foreach ($context['ticket_blocks'] as $block_id => $block) { if ($block['sort']['add_link']) { $base_url .= $block['sort']['link_bits'][$block['sort']['item']]; } } if ($_REQUEST['sa'] != 'viewblock') { foreach ($context['ticket_blocks'] as $block_id => $block) { $num_per_page = !empty($context['shd_preferences']['blocks_' . $block_key . '_count']) ? $context['shd_preferences']['blocks_' . $block_key . '_count'] : $context['items_per_page']; $url_fragment = $base_url; foreach ($block_list as $block_item) { if ($block_item == $block_id) { $url_fragment .= ';st_' . $block_item . '=%1$d'; } elseif (!empty($context['ticket_blocks'][$block_item]['start'])) { $url_fragment .= ';st_' . $block_item . '=' . $context['ticket_blocks'][$block_item]['start']; } } $context['start'] = $context['ticket_blocks'][$block_id]['start']; $context['ticket_blocks'][$block_id]['page_index'] = shd_no_expand_pageindex($scripturl . $primary_url . $url_fragment . $context['shd_dept_link'] . $context['filter_fragment'] . '#shd_block_' . $block_id, $context['start'], $block['count'], $block['num_per_page'], true); } } // Just need to deal with those pesky prefix fields, if there are any. if (empty($tickets)) { return; } // We're all done here. // 1. Figure out if there are any custom fields that apply to us or not. if ($context['shd_multi_dept'] && empty($context['shd_department'])) { $dept_list = shd_allowed_to('access_helpdesk', false); } else { $dept_list = array($context['shd_department']); } $fields = array(); $query = $smcFunc['db_query']('', ' SELECT hdcf.id_field, can_see, field_type, field_options, placement, field_name FROM {db_prefix}helpdesk_custom_fields AS hdcf INNER JOIN {db_prefix}helpdesk_custom_fields_depts AS hdcfd ON (hdcfd.id_field = hdcf.id_field) WHERE placement IN ({array_int:placement_prefix}) AND field_loc IN ({array_int:locations}) AND hdcfd.id_dept IN ({array_int:dept_list}) AND active = {int:active} GROUP BY hdcf.id_field ORDER BY field_order', array('locations' => array(CFIELD_TICKET, CFIELD_TICKET | CFIELD_REPLY), 'placement_prefix' => array(CFIELD_PLACE_PREFIX, CFIELD_PLACE_PREFIXFILTER), 'active' => 1, 'dept_list' => $dept_list)); $is_staff = shd_allowed_to('shd_staff', $context['shd_department']); $is_admin = $context['user']['is_admin'] || shd_allowed_to('admin_helpdesk', $context['shd_department']); $context['shd_filter_fields'] = array(); while ($row = $smcFunc['db_fetch_assoc']($query)) { list($user_see, $staff_see) = explode(',', $row['can_see']); if ($is_admin || $is_staff && $staff_see == '1' || !$is_staff && $user_see == '1') { if (!empty($row['field_options'])) { $row['field_options'] = unserialize($row['field_options']); if (isset($row['field_options']['inactive'])) { unset($row['field_options']['inactive']); } foreach ($row['field_options'] as $k => $v) { if (strpos($v, '[') !== false) { $row['field_options'][$k] = parse_bbc($v); } } } $fields[$row['id_field']] = $row; if ($row['placement'] == CFIELD_PLACE_PREFIXFILTER) { $context['shd_filter_fields'][$row['id_field']] = array('name' => $row['field_name'], 'options' => $row['field_options'], 'in_use' => array()); } } } $smcFunc['db_free_result']($query); if (empty($fields)) { return; } // No fields to process, time to go. // 2. Get the relevant values. $query = $smcFunc['db_query']('', ' SELECT id_post, id_field, value FROM {db_prefix}helpdesk_custom_fields_values WHERE id_post IN ({array_int:tickets}) AND id_field IN ({array_int:fields}) AND post_type = {int:ticket}', array('tickets' => array_keys($tickets), 'fields' => array_keys($fields), 'ticket' => CFIELD_TICKET)); while ($row = $smcFunc['db_fetch_assoc']($query)) { $tickets[$row['id_post']][$row['id_field']] = $row['value']; } // 3. Apply the values into the tickets. if ($_REQUEST['sa'] == 'closedtickets') { $context['filterbase'] = $scripturl . '?action=helpdesk;sa=closedtickets'; } elseif ($_REQUEST['sa'] == 'recyclebin') { $context['filterbase'] = $scripturl . '?action=helpdesk;sa=recyclebin'; } else { $context['filterbase'] = $scripturl . '?' . $context['shd_home']; } foreach ($context['ticket_blocks'] as $block_id => $block) { if (empty($block['tickets'])) { continue; } foreach ($block['tickets'] as $ticket_id => $ticket) { if (isset($tickets[$ticket_id])) { $prefix_filter = ''; $prefix = ''; foreach ($fields as $field_id => $field) { if (empty($tickets[$ticket_id][$field_id])) { continue; } if ($field['placement'] == CFIELD_PLACE_PREFIXFILTER) { if (!isset($field['field_options'][$tickets[$ticket_id][$field_id]])) { continue; } $prefix_filter .= '[<a href="' . $context['filterbase'] . $context['shd_dept_link'] . ';field=' . $field_id . ';filter=' . $tickets[$ticket_id][$field_id] . '">' . $field['field_options'][$tickets[$ticket_id][$field_id]] . '</a>] '; } else { if ($field['field_type'] == CFIELD_TYPE_CHECKBOX) { $prefix .= !empty($tickets[$ticket_id][$field_id]) ? $txt['yes'] . ' ' : $txt['no'] . ' '; } elseif ($field['field_type'] == CFIELD_TYPE_SELECT || $field['field_type'] == CFIELD_TYPE_RADIO) { $prefix .= $field['field_options'][$tickets[$ticket_id][$field_id]] . ' '; } elseif ($field['field_type'] == CFIELD_TYPE_MULTI) { $values = explode(',', $tickets[$ticket_id][$field_id]); foreach ($values as $value) { $prefix .= $field['field_options'][$value] . ' '; } } else { $prefix .= $tickets[$ticket_id][$field_id] . ' '; } } } // First, set aside the subject, and if there is a non category prefix, strip links from it. $subject = $ticket['subject']; if (!empty($prefix)) { $prefix = '[' . trim(preg_replace('~<a (.*?)</a>~is', '', $prefix)) . '] '; } // Then, if we have a category prefix, prepend that to any other prefix we have. if (!empty($prefix_filter)) { $prefix = $prefix_filter . $prefix; } // Lastly, if we have some kind of prefix to put in front of this ticket, do so. if (!empty($prefix)) { $context['ticket_blocks'][$block_id]['tickets'][$ticket_id]['subject'] = $prefix . $subject; $context['ticket_blocks'][$block_id]['tickets'][$ticket_id]['link'] = $prefix . '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticket_id . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '">' . $subject . '</a>'; } } } } // 4. We've collected the list of prefix-filter fields in use, now establish which values are actually in use. if (!empty($context['shd_filter_fields'])) { $query = $smcFunc['db_query']('', ' SELECT id_field, value FROM {db_prefix}helpdesk_custom_fields_values WHERE id_field IN ({array_int:fields})', array('fields' => array_keys($context['shd_filter_fields']))); while ($row = $smcFunc['db_fetch_assoc']($query)) { $context['shd_filter_fields'][$row['id_field']]['in_use'][$row['value']] = true; } $smcFunc['db_free_result']($query); foreach ($context['shd_filter_fields'] as $id_field => $field) { if (empty($field['in_use'])) { unset($context['shd_filter_fields'][$id_field]); } else { foreach ($field['options'] as $k => $v) { if (!isset($field['in_use'][$k])) { unset($context['shd_filter_fields'][$id_field]['options'][$k]); } } if (empty($context['shd_filter_fields'][$id_field]['options'])) { unset($context['shd_filter_fields'][$id_field]); } } } } }
if (!isset($website)) { header('HTTP/1.1 404 Not Found'); die; } if (!is_logged()) { if (file_exists($smf_forum . 'SSI.php')) { include $smf_forum . 'SSI.php'; global $context, $txt, $scripturl; if ($context["user"]["id"] >= 1) { $SMF_id = $context["user"]["id"]; $SMF_session_var = $context['session_var']; $SMF_sid =& $context['session_id']; $SMF_username = $context["user"]["name"]; $SMF_email = $context["user"]["email"]; $SMF_website = $smf_forum_url . "index.php?action=profile;u=" . $SMF_id; $userID = loadMemberData($SMF_username, true, 'profile'); loadMemberContext($userID[0]); $SMF_avatar = $memberContext[$userID[0]]['avatar']['href']; require_once 'inc/common.php'; require_once 'inc/class.db.PDO.php'; //require_once('inc/db_connect.php'); $OSDB = new db("mysql:host=" . OSDB_SERVER . ";dbname=" . OSDB_DATABASE . "", OSDB_USERNAME, OSDB_PASSWORD); $sth = $db->prepare("SELECT * FROM " . OSDB_USERS . " \n\t\t WHERE user_email = :SMF_email AND smf_id = :SMF_id "); $sth->bindValue(':SMF_email', $SMF_email, PDO::PARAM_STR); $sth->bindValue(':SMF_id', $SMF_id, PDO::PARAM_STR); $result = $sth->execute(); if ($sth->rowCount() <= 0) { //CREATE NEW USER (from phpbb database) $sth = $db->prepare("SELECT * FROM " . OSDB_USERS . " WHERE LOWER(user_name) = :SMF_username "); $sth->bindValue(':SMF_username', strtolower($SMF_username), PDO::PARAM_STR); $result = $sth->execute();
function MessageSearch2() { global $scripturl, $modSettings, $user_info, $context, $txt, $db_prefix; global $ID_MEMBER, $memberContext, $func; if (!empty($context['load_average']) && !empty($modSettings['loadavg_search']) && $context['load_average'] >= $modSettings['loadavg_search']) { fatal_lang_error('loadavg_search_disabled', false); } // !!! For the moment force the folder to the inbox. $context['folder'] = 'inbox'; // Some useful general permissions. $context['can_send_pm'] = allowedTo('pm_send'); // Some hardcoded veriables that can be tweaked if required. $maxMembersToSearch = 500; // Extract all the search parameters. $search_params = array(); if (isset($_REQUEST['params'])) { $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+')))); foreach ($temp_params as $i => $data) { @(list($k, $v) = explode('|\'|', $data)); $search_params[$k] = stripslashes($v); } } $context['start'] = isset($_GET['start']) ? (int) $_GET['start'] : 0; // Store whether simple search was used (needed if the user wants to do another query). if (!isset($search_params['advanced'])) { $search_params['advanced'] = empty($_REQUEST['advanced']) ? 0 : 1; } // 1 => 'allwords' (default, don't set as param) / 2 => 'anywords'. if (!empty($search_params['searchtype']) || !empty($_REQUEST['searchtype']) && $_REQUEST['searchtype'] == 2) { $search_params['searchtype'] = 2; } // Minimum age of messages. Default to zero (don't set param in that case). if (!empty($search_params['minage']) || !empty($_REQUEST['minage']) && $_REQUEST['minage'] > 0) { $search_params['minage'] = !empty($search_params['minage']) ? (int) $search_params['minage'] : (int) $_REQUEST['minage']; } // Maximum age of messages. Default to infinite (9999 days: param not set). if (!empty($search_params['maxage']) || !empty($_REQUEST['maxage']) && $_REQUEST['maxage'] != 9999) { $search_params['maxage'] = !empty($search_params['maxage']) ? (int) $search_params['maxage'] : (int) $_REQUEST['maxage']; } $search_params['subject_only'] = !empty($search_params['subject_only']) || !empty($_REQUEST['subject_only']); $search_params['show_complete'] = !empty($search_params['show_complete']) || !empty($_REQUEST['show_complete']); // Default the user name to a wildcard matching every user (*). if (!empty($search_params['user_spec']) || !empty($_REQUEST['userspec']) && $_REQUEST['userspec'] != '*') { $search_params['userspec'] = isset($search_params['userspec']) ? $search_params['userspec'] : $_REQUEST['userspec']; } // If there's no specific user, then don't mention it in the main query. if (empty($search_params['userspec'])) { $userQuery = ''; } else { $userString = strtr(addslashes($func['htmlspecialchars'](stripslashes($search_params['userspec']), ENT_QUOTES)), array('"' => '"')); $userString = strtr($userString, array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_')); preg_match_all('~"([^"]+)"~', $userString, $matches); $possible_users = array_merge($matches[1], explode(',', preg_replace('~"([^"]+)"~', '', $userString))); for ($k = 0, $n = count($possible_users); $k < $n; $k++) { $possible_users[$k] = trim($possible_users[$k]); if (strlen($possible_users[$k]) == 0) { unset($possible_users[$k]); } } // Who matches those criteria? // !!! This doesn't support outbox searching. $request = db_query("\n\t\t\tSELECT ID_MEMBER\n\t\t\tFROM {$db_prefix}members\n\t\t\tWHERE realName LIKE '" . implode("' OR realName LIKE '", $possible_users) . "'", __FILE__, __LINE__); // Simply do nothing if there're too many members matching the criteria. if (mysql_num_rows($request) > $maxMembersToSearch) { $userQuery = ''; } elseif (mysql_num_rows($request) == 0) { $userQuery = "AND pm.ID_MEMBER_FROM = 0 AND (pm.fromName LIKE '" . implode("' OR pm.fromName LIKE '", $possible_users) . "')"; } else { $memberlist = array(); while ($row = mysql_fetch_assoc($request)) { $memberlist[] = $row['ID_MEMBER']; } $userQuery = "AND (pm.ID_MEMBER_FROM IN (" . implode(', ', $memberlist) . ") OR (pm.ID_MEMBER_FROM = 0 AND (pm.fromName LIKE '" . implode("' OR pm.fromName LIKE '", $possible_users) . "')))"; } mysql_free_result($request); } // Setup the sorting variables... // !!! Add more in here! $sort_columns = array('ID_PM'); if (empty($search_params['sort']) && !empty($_REQUEST['sort'])) { list($search_params['sort'], $search_params['sort_dir']) = array_pad(explode('|', $_REQUEST['sort']), 2, ''); } $search_params['sort'] = !empty($search_params['sort']) && in_array($search_params['sort'], $sort_columns) ? $search_params['sort'] : 'ID_PM'; $search_params['sort_dir'] = !empty($search_params['sort_dir']) && $search_params['sort_dir'] == 'asc' ? 'asc' : 'desc'; // Sort out any labels we may be searching by. $labelQuery = ''; if ($context['folder'] == 'inbox' && !empty($search_params['advanced']) && $context['currently_using_labels']) { // Came here from pagination? Put them back into $_REQUEST for sanitization. if (isset($search_params['labels'])) { $_REQUEST['searchlabel'] = explode(',', $search_params['labels']); } // Assuming we have some labels - make them all integers. if (!empty($_REQUEST['searchlabel']) && is_array($_REQUEST['searchlabel'])) { foreach ($_REQUEST['searchlabel'] as $key => $id) { $_REQUEST['searchlabel'][$key] = (int) $id; } } else { $_REQUEST['searchlabel'] = array(); } // Now that everything is cleaned up a bit, make the labels a param. $search_params['labels'] = implode(',', $_REQUEST['searchlabel']); // No labels selected? That must be an error! if (empty($_REQUEST['searchlabel'])) { $context['search_errors']['no_labels_selected'] = true; } elseif (count($_REQUEST['searchlabel']) != count($context['labels'])) { $labelQuery = "\n\t\t\tAND (FIND_IN_SET('" . implode("', pmr.labels) OR FIND_IN_SET('", $_REQUEST['searchlabel']) . "', pmr.labels))"; } } // What are we actually searching for? $search_params['search'] = !empty($search_params['search']) ? $search_params['search'] : (isset($_REQUEST['search']) ? stripslashes($_REQUEST['search']) : ''); // If we ain't got nothing - we should error! if (!isset($search_params['search']) || $search_params['search'] == '') { $context['search_errors']['invalid_search_string'] = true; } // Extract phrase parts first (e.g. some words "this is a phrase" some more words.) preg_match_all('~(?:^|\\s)([-]?)"([^"]+)"(?:$|\\s)~' . ($context['utf8'] ? 'u' : ''), $search_params['search'], $matches, PREG_PATTERN_ORDER); $searchArray = $matches[2]; // Remove the phrase parts and extract the words. $tempSearch = explode(' ', preg_replace('~(?:^|\\s)([-]?)"([^"]+)"(?:$|\\s)~' . ($context['utf8'] ? 'u' : ''), ' ', $search_params['search'])); // A minus sign in front of a word excludes the word.... so... $excludedWords = array(); // .. first, we check for things like -"some words", but not "-some words". foreach ($matches[1] as $index => $word) { if ($word == '-') { $word = $func['strtolower'](trim($searchArray[$index])); if (strlen($word) > 0) { $excludedWords[] = addslashes($word); } unset($searchArray[$index]); } } // Now we look for -test, etc.... normaller. foreach ($tempSearch as $index => $word) { if (strpos(trim($word), '-') === 0) { $word = substr($func['strtolower'](trim($word)), 1); if (strlen($word) > 0) { $excludedWords[] = addslashes($word); } unset($tempSearch[$index]); } } $searchArray = array_merge($searchArray, $tempSearch); // Trim everything and make sure there are no words that are the same. foreach ($searchArray as $index => $value) { $searchArray[$index] = $func['strtolower'](trim($value)); if ($searchArray[$index] == '') { unset($searchArray[$index]); } else { // Sort out entities first. $searchArray[$index] = $func['htmlspecialchars']($searchArray[$index]); $searchArray[$index] = addslashes($searchArray[$index]); } } $searchArray = array_unique($searchArray); // Create an array of replacements for highlighting. $context['mark'] = array(); foreach ($searchArray as $word) { $context['mark'][$word] = '<b class="highlight">' . $word . '</b>'; } // This contains *everything* $searchWords = array_merge($searchArray, $excludedWords); // Make sure at least one word is being searched for. if (empty($searchArray)) { $context['search_errors']['invalid_search_string'] = true; } // Sort out the search query so the user can edit it - if they want. $context['search_params'] = $search_params; if (isset($context['search_params']['search'])) { $context['search_params']['search'] = htmlspecialchars($context['search_params']['search']); } if (isset($context['search_params']['userspec'])) { $context['search_params']['userspec'] = htmlspecialchars($context['search_params']['userspec']); } // Now we have all the parameters, combine them together for pagination and the like... $context['params'] = array(); foreach ($search_params as $k => $v) { $context['params'][] = $k . '|\'|' . addslashes($v); } $context['params'] = base64_encode(implode('|"|', $context['params'])); // Compile the subject query part. $andQueryParts = array(); foreach ($searchWords as $index => $word) { if ($word == '') { continue; } if ($search_params['subject_only']) { $andQueryParts[] = "pm.subject" . (in_array($word, $excludedWords) ? ' NOT' : '') . " LIKE '%" . strtr($word, array('_' => '\\_', '%' => '\\%')) . "%'"; } else { $andQueryParts[] = '(pm.subject' . (in_array($word, $excludedWords) ? ' NOT' : '') . " LIKE '%" . strtr($word, array('_' => '\\_', '%' => '\\%')) . "%' " . (in_array($word, $excludedWords) ? 'AND pm.body NOT' : 'OR pm.body') . " LIKE '%" . strtr($word, array('_' => '\\_', '%' => '\\%')) . "%')"; } } $searchQuery = ' 1'; if (!empty($andQueryParts)) { $searchQuery = implode(!empty($search_params['searchtype']) && $search_params['searchtype'] == 2 ? ' OR ' : ' AND ', $andQueryParts); } // If we have errors - return back to the first screen... if (!empty($context['search_errors'])) { $_REQUEST['params'] = $context['params']; return MessageSearch(); } // Get the amount of results. $request = db_query("\n\t\tSELECT COUNT(*)\n\t\tFROM ({$db_prefix}pm_recipients AS pmr, {$db_prefix}personal_messages AS pm)\n\t\tWHERE pm.ID_PM = pmr.ID_PM" . ($context['folder'] == 'inbox' ? "\n\t\t\tAND pmr.ID_MEMBER = {$ID_MEMBER}\n\t\t\tAND pmr.deleted = 0" : "\n\t\t\tAND pm.ID_MEMBER_FROM = {$ID_MEMBER}\n\t\t\tAND pm.deletedBySender = 0") . "\n\t\t\t{$userQuery}{$labelQuery}\n\t\t\tAND ({$searchQuery})", __FILE__, __LINE__); list($numResults) = mysql_fetch_row($request); mysql_free_result($request); // Get all the matching messages... using standard search only (No caching and the like!) // !!! This doesn't support outbox searching yet. $request = db_query("\n\t\tSELECT pm.ID_PM, pm.ID_MEMBER_FROM\n\t\tFROM ({$db_prefix}pm_recipients AS pmr, {$db_prefix}personal_messages AS pm)\n\t\tWHERE pm.ID_PM = pmr.ID_PM" . ($context['folder'] == 'inbox' ? "\n\t\t\tAND pmr.ID_MEMBER = {$ID_MEMBER}\n\t\t\tAND pmr.deleted = 0" : "\n\t\t\tAND pm.ID_MEMBER_FROM = {$ID_MEMBER}\n\t\t\tAND pm.deletedBySender = 0") . "\n\t\t\t{$userQuery}{$labelQuery}\n\t\t\tAND ({$searchQuery})\n\t\tORDER BY {$search_params['sort']} {$search_params['sort_dir']}\n\t\tLIMIT {$context['start']}, {$modSettings['search_results_per_page']}", __FILE__, __LINE__); $foundMessages = array(); $posters = array(); while ($row = mysql_fetch_assoc($request)) { $foundMessages[] = $row['ID_PM']; $posters[] = $row['ID_MEMBER_FROM']; } mysql_free_result($request); // Load the users... $posters = array_unique($posters); if (!empty($posters)) { loadMemberData($posters); } // Sort out the page index. $context['page_index'] = constructPageIndex($scripturl . '?action=pm;sa=search2;params=' . $context['params'], $_GET['start'], $numResults, $modSettings['search_results_per_page'], false); $context['message_labels'] = array(); $context['message_replied'] = array(); $context['personal_messages'] = array(); if (!empty($foundMessages)) { // Now get recipients (but don't include bcc-recipients for your inbox, you're not supposed to know :P!) $request = db_query("\n\t\t\tSELECT\n\t\t\t\tpmr.ID_PM, mem_to.ID_MEMBER AS ID_MEMBER_TO, mem_to.realName AS toName,\n\t\t\t\tpmr.bcc, pmr.labels, pmr.is_read\n\t\t\tFROM {$db_prefix}pm_recipients AS pmr\n\t\t\t\tLEFT JOIN {$db_prefix}members AS mem_to ON (mem_to.ID_MEMBER = pmr.ID_MEMBER)\n\t\t\tWHERE pmr.ID_PM IN (" . implode(', ', $foundMessages) . ")", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) { if ($context['folder'] == 'outbox' || empty($row['bcc'])) { $recipients[$row['ID_PM']][empty($row['bcc']) ? 'to' : 'bcc'][] = empty($row['ID_MEMBER_TO']) ? $txt[28] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER_TO'] . '">' . $row['toName'] . '</a>'; } if ($row['ID_MEMBER_TO'] == $ID_MEMBER && $context['folder'] != 'outbox') { $context['message_replied'][$row['ID_PM']] = $row['is_read'] & 2; $row['labels'] = $row['labels'] == '' ? array() : explode(',', $row['labels']); // This is a special need for linking to messages. foreach ($row['labels'] as $v) { if (isset($context['labels'][(int) $v])) { $context['message_labels'][$row['ID_PM']][(int) $v] = array('id' => $v, 'name' => $context['labels'][(int) $v]['name']); } // Here we find the first label on a message - for linking to posts in results if (!isset($context['first_label'][$row['ID_PM']]) && !in_array('-1', $row['labels'])) { $context['first_label'][$row['ID_PM']] = (int) $v; } } } } // Prepare the query for the callback! $request = db_query("\n\t\t\tSELECT pm.ID_PM, pm.subject, pm.ID_MEMBER_FROM, pm.body, pm.msgtime, pm.fromName\n\t\t\tFROM {$db_prefix}personal_messages AS pm\n\t\t\tWHERE pm.ID_PM IN (" . implode(',', $foundMessages) . ")\n\t\t\tORDER BY {$search_params['sort']} {$search_params['sort_dir']}\n\t\t\tLIMIT " . count($foundMessages), __FILE__, __LINE__); $counter = 0; while ($row = mysql_fetch_assoc($request)) { // If there's no message subject, use the default. $row['subject'] = $row['subject'] == '' ? $txt[24] : $row['subject']; // Load this posters context info, if it ain't there then fill in the essentials... if (!loadMemberContext($row['ID_MEMBER_FROM'])) { $memberContext[$row['ID_MEMBER_FROM']]['name'] = $row['fromName']; $memberContext[$row['ID_MEMBER_FROM']]['id'] = 0; $memberContext[$row['ID_MEMBER_FROM']]['group'] = $txt[28]; $memberContext[$row['ID_MEMBER_FROM']]['link'] = $row['fromName']; $memberContext[$row['ID_MEMBER_FROM']]['email'] = ''; $memberContext[$row['ID_MEMBER_FROM']]['hide_email'] = true; $memberContext[$row['ID_MEMBER_FROM']]['is_guest'] = true; } // Censor anything we don't want to see... censorText($row['body']); censorText($row['subject']); // Parse out any BBC... $row['body'] = parse_bbc($row['body'], true, 'pm' . $row['ID_PM']); $href = $scripturl . '?action=pm;f=' . $context['folder'] . (isset($context['first_label'][$row['ID_PM']]) ? ';l=' . $context['first_label'][$row['ID_PM']] : '') . ';pmid=' . $row['ID_PM'] . '#msg' . $row['ID_PM']; $context['personal_messages'][] = array('id' => $row['ID_PM'], 'member' => &$memberContext[$row['ID_MEMBER_FROM']], 'subject' => $row['subject'], 'body' => $row['body'], 'time' => timeformat($row['msgtime']), 'recipients' => &$recipients[$row['ID_PM']], 'labels' => &$context['message_labels'][$row['ID_PM']], 'fully_labeled' => count($context['message_labels'][$row['ID_PM']]) == count($context['labels']), 'is_replied_to' => &$context['message_replied'][$row['ID_PM']], 'href' => $href, 'link' => '<a href="' . $href . '">' . $row['subject'] . '</a>', 'counter' => ++$counter); } mysql_free_result($request); } // Finish off the context. $context['page_title'] = $txt['pm_search_title']; $context['sub_template'] = 'search_results'; $context['pm_area'] = 'search'; $context['linktree'][] = array('url' => $scripturl . '?action=pm;sa=search', 'name' => $txt['pm_search_bar_title']); }
function editBuddies($memID) { global $txt, $scripturl, $modSettings, $db_prefix; global $context, $user_profile, $memberContext, $func; // Do a quick check to ensure people aren't getting here illegally! if (!$context['user']['is_owner'] || empty($modSettings['enable_buddylist'])) { fatal_lang_error(1, false); } // !!! No page_title. // For making changes! $buddiesArray = explode(',', $user_profile[$memID]['buddy_list']); foreach ($buddiesArray as $k => $dummy) { if ($dummy == '') { unset($buddiesArray[$k]); } } // Removing a buddy? if (isset($_GET['remove'])) { // Heh, I'm lazy, do it the easy way... foreach ($buddiesArray as $key => $buddy) { if ($buddy == (int) $_GET['remove']) { unset($buddiesArray[$key]); } } // Make the changes. $user_profile[$memID]['buddy_list'] = implode(',', $buddiesArray); updateMemberData($memID, array('buddy_list' => "'" . $user_profile[$memID]['buddy_list'] . "'")); // Redirect off the page because we don't like all this ugly query stuff to stick in the history. redirectexit('action=profile;u=' . $memID . ';sa=editBuddies'); } elseif (isset($_POST['new_buddy'])) { // Prepare the string for extraction... $_POST['new_buddy'] = strtr(addslashes($func['htmlspecialchars'](stripslashes($_POST['new_buddy']), ENT_QUOTES)), array('"' => '"')); preg_match_all('~"([^"]+)"~', $_POST['new_buddy'], $matches); $new_buddies = array_unique(array_merge($matches[1], explode(',', preg_replace('~"([^"]+)"~', '', $_POST['new_buddy'])))); foreach ($new_buddies as $k => $dummy) { $new_buddies[$k] = strtr(trim($new_buddies[$k]), array('\\\'' => ''')); if (strlen($new_buddies[$k]) == 0) { unset($new_buddies[$k]); } } if (!empty($new_buddies)) { // Now find out the ID_MEMBER of the buddy. $request = db_query("\n\t\t\t\tSELECT ID_MEMBER\n\t\t\t\tFROM {$db_prefix}members\n\t\t\t\tWHERE memberName IN ('" . implode("','", $new_buddies) . "') OR realName IN ('" . implode("','", $new_buddies) . "')\n\t\t\t\tLIMIT " . count($new_buddies), __FILE__, __LINE__); // Add the new member to the buddies array. while ($row = mysql_fetch_assoc($request)) { $buddiesArray[] = (int) $row['ID_MEMBER']; } mysql_free_result($request); // Now update the current users buddy list. $user_profile[$memID]['buddy_list'] = implode(',', $buddiesArray); updateMemberData($memID, array('buddy_list' => "'" . $user_profile[$memID]['buddy_list'] . "'")); } // Back to the buddy list! redirectexit('action=profile;u=' . $memID . ';sa=editBuddies'); } // Get all the users "buddies"... $buddies = array(); if (!empty($buddiesArray)) { $result = db_query("\n\t\t\tSELECT ID_MEMBER\n\t\t\tFROM {$db_prefix}members\n\t\t\tWHERE ID_MEMBER IN (" . implode(', ', $buddiesArray) . ")\n\t\t\tORDER BY realName\n\t\t\tLIMIT " . (substr_count($user_profile[$memID]['buddy_list'], ',') + 1), __FILE__, __LINE__); while ($row = mysql_fetch_assoc($result)) { $buddies[] = $row['ID_MEMBER']; } mysql_free_result($result); } $context['buddy_count'] = count($buddies); // Load all the members up. loadMemberData($buddies, false, 'profile'); // Setup the context for each buddy. $context['buddies'] = array(); foreach ($buddies as $buddy) { loadMemberContext($buddy); $context['buddies'][$buddy] = $memberContext[$buddy]; } }
function BuddyRemove() { global $smcFunc, $user_info, $user_profile, $context; checkSession('get'); $_GET['u'] = (int) $_GET['u']; $smcFunc['db_query']('', ' DELETE FROM {db_prefix}buddies WHERE id_member = {int:id_member} AND buddy_id = {int:buddy_id}', array('id_member' => $context['user']['id'], 'buddy_id' => $_GET['u'])); $smcFunc['db_query']('', ' DELETE FROM {db_prefix}buddies WHERE buddy_id = {int:buddy_id} AND id_member = {int:id_member}', array('buddy_id' => $context['user']['id'], 'id_member' => $_GET['u'])); // Update SMF's system as well... $user_info['buddies'] = array_diff($user_info['buddies'], array($_GET['u'])); updateMemberData($context['user']['id'], array('buddy_list' => implode(',', $user_info['buddies']))); loadMemberData($_GET['u'], false, 'normal'); $buddies = explode(',', $user_profile[$_GET['u']]['buddy_list']); $buddies = array_diff($buddies, array($context['user']['id'])); updateMemberData($_GET['u'], array('buddy_list' => implode(',', $buddies))); redirectexit('action=profile;area=lists;sa=buddies;u=' . $context['user']['id']); }
function getXmlProfile($xml_format) { global $scripturl, $memberContext, $user_profile, $modSettings, $user_info; // You must input a valid user.... if (empty($_GET['u']) || loadMemberData((int) $_GET['u']) === false) { return array(); } // Make sure the id is a number and not "I like trying to hack the database". $_GET['u'] = (int) $_GET['u']; // Load the member's contextual information! if (!loadMemberContext($_GET['u']) || !allowedTo('profile_view_any')) { return array(); } // Okay, I admit it, I'm lazy. Stupid $_GET['u'] is long and hard to type. $profile =& $memberContext[$_GET['u']]; if ($xml_format == 'rss' || $xml_format == 'rss2') { $data = array(array('title' => cdata_parse($profile['name']), 'link' => $scripturl . '?action=profile;u=' . $profile['id'], 'description' => cdata_parse(isset($profile['group']) ? $profile['group'] : $profile['post_group']), 'comments' => $scripturl . '?action=pm;sa=send;u=' . $profile['id'], 'pubDate' => gmdate('D, d M Y H:i:s \\G\\M\\T', $user_profile[$profile['id']]['dateRegistered']), 'guid' => $scripturl . '?action=profile;u=' . $profile['id'])); } elseif ($xml_format == 'rdf') { $data = array(array('title' => cdata_parse($profile['name']), 'link' => $scripturl . '?action=profile;u=' . $profile['id'], 'description' => cdata_parse(isset($profile['group']) ? $profile['group'] : $profile['post_group']))); } elseif ($xml_format == 'atom') { $data[] = array('title' => cdata_parse($profile['name']), 'link' => $scripturl . '?action=profile;u=' . $profile['id'], 'summary' => cdata_parse(isset($profile['group']) ? $profile['group'] : $profile['post_group']), 'created' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user_profile[$profile['id']]['dateRegistered']), 'issued' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user_profile[$profile['id']]['dateRegistered']), 'modified' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user_profile[$profile['id']]['lastLogin']), 'id' => $scripturl . '?action=profile;u=' . $profile['id']); } else { $data = array('username' => cdata_parse($profile['username']), 'name' => cdata_parse($profile['name']), 'link' => $scripturl . '?action=profile;u=' . $profile['id'], 'posts' => $profile['posts'], 'post-group' => cdata_parse($profile['post_group']), 'language' => cdata_parse($profile['language']), 'last-login' => gmdate('D, d M Y H:i:s \\G\\M\\T', $user_profile[$profile['id']]['lastLogin']), 'registered' => gmdate('D, d M Y H:i:s \\G\\M\\T', $user_profile[$profile['id']]['dateRegistered'])); // Everything below here might not be set, and thus maybe shouldn't be displayed. if ($profile['gender']['name'] != '') { $data['gender'] = cdata_parse($profile['gender']['name']); } if ($profile['avatar']['name'] != '') { $data['avatar'] = $profile['avatar']['url']; } // If they are online, show an empty tag... no reason to put anything inside it. if ($profile['online']['is_online']) { $data['online'] = ''; } if ($profile['signature'] != '') { $data['signature'] = cdata_parse($profile['signature']); } if ($profile['blurb'] != '') { $data['blurb'] = cdata_parse($profile['blurb']); } if ($profile['location'] != '') { $data['location'] = cdata_parse($profile['location']); } if ($profile['title'] != '') { $data['title'] = cdata_parse($profile['title']); } if (!empty($profile['icq']['name']) && !(!empty($modSettings['guest_hideContacts']) && $user_info['is_guest'])) { $data['icq'] = $profile['icq']['name']; } if ($profile['aim']['name'] != '' && !(!empty($modSettings['guest_hideContacts']) && $user_info['is_guest'])) { $data['aim'] = $profile['aim']['name']; } if ($profile['msn']['name'] != '' && !(!empty($modSettings['guest_hideContacts']) && $user_info['is_guest'])) { $data['msn'] = $profile['msn']['name']; } if ($profile['yim']['name'] != '' && !(!empty($modSettings['guest_hideContacts']) && $user_info['is_guest'])) { $data['yim'] = $profile['yim']['name']; } if ($profile['website']['title'] != '') { $data['website'] = array('title' => cdata_parse($profile['website']['title']), 'link' => $profile['website']['url']); } if ($profile['group'] != '') { $data['postition'] = cdata_parse($profile['group']); } if (!empty($modSettings['karmaMode'])) { $data['karma'] = array('good' => $profile['karma']['good'], 'bad' => $profile['karma']['bad']); } if ((empty($profile['hide_email']) || empty($modSettings['allow_hideEmail'])) && !(!empty($modSettings['guest_hideContacts']) && $user_info['is_guest'])) { $data['email'] = $profile['email']; } if (!empty($profile['birth_date']) && substr($profile['birth_date'], 0, 4) != '0000') { list($birth_year, $birth_month, $birth_day) = sscanf($profile['birth_date'], '%d-%d-%d'); $datearray = getdate(forum_time()); $data['age'] = $datearray['year'] - $birth_year - ($datearray['mon'] > $birth_month || $datearray['mon'] == $birth_month && $datearray['mday'] >= $birth_day ? 0 : 1); } } // Save some memory. unset($profile); unset($memberContext[$_GET['u']]); return $data; }
/** * Handles the actual assignment form, validates it and carries it out. * * Primarily this is just about receiving the form, making the same checks that {@link shd_assign()} does and then * logging the action before passing over to {@link shd_commit_assignment()} to actually assign the ticket. * * @see shd_assign() * @see shd_commit_assignment() * @since 1.0 */ function shd_assign2() { global $context, $smcFunc, $user_info, $sourcedir; checkSession(); checkSubmitOnce('check'); if (empty($context['ticket_id'])) { fatal_lang_error('shd_no_ticket'); } $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket'; $assignee = isset($_REQUEST['to_user']) ? (int) $_REQUEST['to_user'] : 0; // Get ticket details - and kick it out if they shouldn't be able to see it. $query = shd_db_query('', ' SELECT id_member_started, id_member_assigned, private, subject, status, id_dept FROM {db_prefix}helpdesk_tickets AS hdt WHERE {query_see_ticket} AND id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'])); $log_params = array(); if ($row = $smcFunc['db_fetch_row']($query)) { list($ticket_starter, $ticket_owner, $private, $subject, $status, $dept) = $row; // The core details that we'll be logging $log_params = array('subject' => $subject, 'ticket' => $context['ticket_id']); } else { $smcFunc['db_free_result']($query); fatal_lang_error('shd_no_ticket'); } // Just in case, are they cancelling? if (isset($_REQUEST['cancel'])) { redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); } if ($status == TICKET_STATUS_CLOSED || $status == TICKET_STATUS_DELETED) { fatal_lang_error('shd_cannot_assign', false); } if (shd_allowed_to('shd_assign_ticket_any', $dept)) { if ($assignee == 0) { shd_log_action('unassign', $log_params); shd_commit_assignment($context['ticket_id'], 0); } else { $members = shd_get_possible_assignees($private, $ticket_starter, $dept); if (in_array($assignee, $members)) { global $user_profile; loadMemberData($assignee, false, 'minimal'); $log_params += array('user_id' => $assignee, 'user_name' => $user_profile[$assignee]['real_name']); shd_log_action('assign', $log_params); shd_commit_assignment($context['ticket_id'], $assignee); } else { fatal_lang_error('shd_assigned_not_permitted', false); } } } elseif (shd_allowed_to('shd_assign_ticket_own', $dept) && shd_allowed_to('shd_staff', $dept)) { if ($ticket_owner == 0) { $log_params += array('user_id' => $user_info['id'], 'user_name' => $user_info['name']); shd_log_action('assign', $log_params); shd_commit_assignment($context['ticket_id'], $user_info['id']); } elseif ($ticket_starter == $user_info['id']) { shd_log_action('unassign', $log_params); shd_commit_assignment($context['ticket_id'], 0); } else { // oops, assigned to somebody else fatal_lang_error('shd_cannot_assign_other', false); } } else { fatal_lang_error('shd_cannot_assign', false); } }
function __construct($request, $total_items, $not_profile = false) { global $context, $txt, $user_info, $scripturl, $options, $memberContext, $modSettings; if (!isset($context['pageindex_multiplier'])) { $context['pageindex_multiplier'] = commonAPI::getMessagesPerPage(); } $cb_name = isset($context['cb_name']) ? $context['cb_name'] : 'topics[]'; while ($row = mysql_fetch_assoc($request)) { censorText($row['subject']); $this->topic_ids[] = $row['id_topic']; $f_post_mem_href = !empty($row['id_member']) ? URL::user($row['id_member'], $row['first_member_name']) : ''; $t_href = URL::topic($row['id_topic'], $row['subject'], 0); $l_post_mem_href = !empty($row['id_member_updated']) ? URL::user($row['id_member_updated'], $row['last_real_name']) : ''; $l_post_msg_href = URL::topic($row['id_topic'], $row['last_subject'], $user_info['is_guest'] ? !empty($options['view_newest_first']) ? 0 : (int) ($row['num_replies'] / $context['pageindex_multiplier']) * $context['pageindex_multiplier'] : 0, $user_info['is_guest'] ? true : false, $user_info['is_guest'] ? '' : '.msg' . $row['id_last_msg'], $user_info['is_guest'] ? '#msg' . $row['id_last_msg'] : '#new'); $this->topiclist[$row['id_topic']] = array('id' => $row['id_topic'], 'id_member_started' => empty($row['id_member']) ? 0 : $row['id_member'], 'first_post' => array('id' => $row['id_first_msg'], 'member' => array('username' => $row['first_member_name'], 'name' => $row['first_member_name'], 'id' => empty($row['id_member']) ? 0 : $row['id_member'], 'href' => $f_post_mem_href, 'link' => !empty($row['id_member']) ? '<a onclick="getMcard(' . $row['id_member'] . ', $(this));return(false);" href="' . $f_post_mem_href . '" title="' . $txt['profile_of'] . ' ' . $row['first_member_name'] . '">' . $row['first_member_name'] . '</a>' : $row['first_member_name']), 'time' => timeformat($row['first_poster_time']), 'timestamp' => forum_time(true, $row['first_poster_time']), 'subject' => $row['subject'], 'icon' => $row['first_icon'], 'icon_url' => getPostIcon($row['first_icon']), 'href' => $t_href, 'link' => '<a href="' . $t_href . '">' . $row['subject'] . '</a>'), 'last_post' => array('id' => $row['id_last_msg'], 'member' => array('username' => $row['last_real_name'], 'name' => $row['last_real_name'], 'id' => $row['id_member_updated'], 'href' => $l_post_mem_href, 'link' => !empty($row['id_member_updated']) ? '<a onclick="getMcard(' . $row['id_member_updated'] . ', $(this));return(false);" href="' . $l_post_mem_href . '">' . $row['last_real_name'] . '</a>' : $row['last_real_name']), 'time' => timeformat($row['last_post_time']), 'timestamp' => forum_time(true, $row['last_post_time']), 'subject' => $row['last_subject'], 'href' => $l_post_msg_href, 'link' => '<a href="' . $l_post_msg_href . ($row['num_replies'] == 0 ? '' : ' rel="nofollow"') . '>' . $row['last_subject'] . '</a>'), 'checkbox_name' => $cb_name, 'subject' => $row['subject'], 'new' => $row['new_from'] <= $row['id_msg_modified'], 'new_from' => $row['new_from'], 'newtime' => $row['new_from'], 'updated' => timeformat($row['poster_time']), 'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new', 'new_link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new">' . $row['subject'] . '</a>', 'replies' => comma_format($row['num_replies']), 'views' => comma_format($row['num_views']), 'approved' => $row['approved'], 'unapproved_posts' => $row['unapproved_posts'], 'is_old' => !empty($modSettings['oldTopicDays']) ? $context['time_now'] - $row['last_post_time'] > $modSettings['oldTopicDays'] * 86400 : false, 'is_posted_in' => false, 'prefix' => '', 'pages' => '', 'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($row['is_sticky']), 'is_locked' => !empty($row['locked']), 'is_poll' => false, 'is_hot' => $row['num_replies'] >= $modSettings['hotTopicPosts'], 'is_very_hot' => $row['num_replies'] >= $modSettings['hotTopicVeryPosts'], 'board' => isset($row['id_board']) && !empty($row['id_board']) ? array('name' => $row['board_name'], 'id' => $row['id_board'], 'href' => URL::board($row['id_board'], $row['board_name'])) : array('name' => '', 'id' => 0, 'href' => '')); determineTopicClass($this->topiclist[$row['id_topic']]); if (!empty($row['id_member']) && ($row['id_member'] != $user_info['id'] || $not_profile)) { $this->users_to_load[$row['id_member']] = $row['id_member']; } } loadMemberData($this->users_to_load); foreach ($this->topiclist as &$topic) { if (!isset($memberContext[$topic['id_member_started']])) { loadMemberContext($topic['id_member_started']); } $topic['first_post']['member']['avatar'] =& $memberContext[$topic['id_member_started']]['avatar']['image']; } // figure out whether we have posted in a topic (but only if we are not the topic starter) if (!empty($modSettings['enableParticipation']) && !$user_info['is_guest'] && !empty($this->topic_ids)) { $result = smf_db_query(' SELECT id_topic FROM {db_prefix}messages WHERE id_topic IN ({array_int:topic_list}) AND id_member = {int:current_member} GROUP BY id_topic LIMIT ' . count($this->topic_ids), array('current_member' => $user_info['id'], 'topic_list' => $this->topic_ids)); while ($row = mysql_fetch_assoc($result)) { if ($this->topiclist[$row['id_topic']]['first_post']['member']['id'] != $user_info['id']) { $this->topiclist[$row['id_topic']]['is_posted_in'] = true; } } mysql_free_result($result); } }
/** * Fetch some member data! * * @param string|null $query_where * @param string|string[] $query_where_params * @param string $query_limit * @param string $query_order * @param string $output_method */ function ssi_queryMembers($query_where = null, $query_where_params = array(), $query_limit = '', $query_order = 'id_member DESC', $output_method = 'echo') { global $memberContext; if ($query_where === null) { return; } require_once SUBSDIR . '/Members.subs.php'; $members_data = retrieveMemberData(array($query_where => $query_where_params, 'limit' => !empty($query_limit) ? (int) $query_limit : 10, 'order_by' => $query_order, 'activated_status' => 1)); $members = array(); foreach ($members_data['member_info'] as $row) { $members[] = $row['id']; } if (empty($members)) { return array(); } // Load the members. loadMemberData($members); // Draw the table! if ($output_method == 'echo') { echo ' <table class="ssi_table">'; } $query_members = array(); foreach ($members as $member) { // Load their context data. if (!loadMemberContext($member)) { continue; } // Store this member's information. $query_members[$member] = $memberContext[$member]; // Only do something if we're echo'ing. if ($output_method == 'echo') { echo ' <tr> <td class="centertext"> ', $query_members[$member]['link'], ' <br />', $query_members[$member]['blurb'], ' <br />', $query_members[$member]['avatar']['image'], ' </td> </tr>'; } } // End the table if appropriate. if ($output_method == 'echo') { echo ' </table>'; } // Send back the data. return $query_members; }
* Spelling mistakes and fixes from community members. * */ require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php'; require_once $link['root'] . 'classes/MailManager.php'; //Initalize Value $from = "*****@*****.**"; $pending_addon_count = 5; $dashboard_link = ""; $official_link = ""; $memberContext = null; //Clear any previously stored value //Unfortunately we don't store user personal details such as email in website's database //so get them from SMF using user ID foreach (MailManager::getAdminEmailList() as $user) { loadMemberData($user['ID_MEMBER']); loadMemberContext($user['ID_MEMBER']); } $subject = "There are " . $pending_addon_count . " addons require your approval!"; $message = file_get_contents($link['root'] . 'pages/mail_templates/pending.addon.dashboard.html'); //now loop through member data and put all the valid email in an array foreach ($memberContext as $user) { //Make sure the emails are valid if (!filter_var($user['email'], FILTER_VALIDATE_EMAIL) === false) { $bindedvalarray = array("{username}" => $user['username'], "{pending_request_count}" => $pending_addon_count, "{dashboard_link}" => $link['addon']['dashboard'], "{official_link}" => $link['home'], "{subject}" => $subject); if (MailManager::sendMail($user['email'], $from, "UTF-8", "text/html", $subject, $message, $bindedvalarray)) { //put some logging function to monitor echo "Mail delivered to " . $user['username'] . "<br/>"; } else { //put some logging function to monitor echo "Mail Could not be delivered";
/** * 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'); }
function get_recommended_user_func() { global $context, $smcFunc, $user_info, $profile, $user_profile, $settings, $scripturl; $user_id = $user_info['id']; if (!empty($user_id)) { $return_user_lists = array(); $total = 0; $user_lists = $context['recommend']; $start = $_REQUEST['start']; $end = $_REQUEST['end']; $return_user_lists = array(); if (isset($user_lists[$user_id])) { unset($user_lists[$user_id]); } if (!empty($user_lists)) { if (isset($_REQUEST['mode']) && $_REQUEST['mode'] == 2) { $check_users = array_keys($user_lists); $valid_users_result = $smcFunc['db_query']('', ' SELECT * FROM {db_prefix}tapatalk_users WHERE userid IN ({array_int:check_users})', array('check_users' => $check_users)); while ($tapausers = $smcFunc['db_fetch_assoc']($valid_users_result)) { unset($user_lists[$tapausers['userid']]); } if ($is_tapa_user) { continue; } } $total = count($user_lists); arsort($user_lists); $num_track = 0; foreach ($user_lists as $uid => $score) { if ($num_track > $start - 1 && $num_track < $end) { loadMemberData($uid); $profile = $user_profile[$uid]; if (!empty($settings['show_user_images']) && empty($profile['options']['show_no_avatars'])) { $avatar = $profile['avatar'] == '' ? $profile['id_attach'] > 0 ? empty($profile['attachment_type']) ? $scripturl . '?action=dlattach;attach=' . $profile['id_attach'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $profile['filename'] : '' : (stristr($profile['avatar'], 'http://') ? $profile['avatar'] : $modSettings['avatar_url'] . '/' . $profile['avatar']); } else { $avatar = ''; } if (!empty($profile)) { $return_user_lists[] = new xmlrpcval(array('username' => new xmlrpcval(basic_clean($user_profile[$uid]['member_name']), 'base64'), 'user_id' => new xmlrpcval($user_profile[$uid]['id_member'], 'string'), 'icon_url' => new xmlrpcval($avatar, 'string')), 'struct'); } $num_track++; } } } } $suggested_users = new xmlrpcval(array('total' => new xmlrpcval($total, 'int'), 'list' => new xmlrpcval($return_user_lists, 'array')), 'struct'); return new xmlrpcresp($suggested_users); }
function getComments($id_page, $limit = array()) { //Check if page exists global $context, $smcFunc, $memberContext; $page = getPage($id_page, true, false); if (empty($page)) { return array(); } $query = $smcFunc['db_query']('', ' SELECT id_comment, id_member, body, date FROM {db_prefix}adk_pages_comments WHERE id_page = {int:id_page} ORDER BY date ASC ' . (!empty($limit) ? 'LIMIT {int:start}, {int:end}' : ''), array('id_page' => $id_page, 'start' => !empty($limit) ? $limit[0] : '', 'end' => !empty($limit) ? $limit[1] : '')); $comments = array(); $id_members = array(); $num_replie = !empty($context['start']) ? $context['start'] : 0; $context['load_id_comments'] = array(); while ($row = $smcFunc['db_fetch_assoc']($query)) { $num_replie++; $context['load_id_comments'][] = $row['id_comment']; $comments[$row['id_comment']] = array('id_page' => $id_page, 'id_comment' => $row['id_comment'], 'body' => parse_bbc($row['body']), 'date' => timeformat($row['date']), 'member_info' => array(), 'num_replie' => $num_replie, 'is_new' => false); $id_members[] = array('id_member' => $row['id_member'], 'id_comment' => $row['id_comment']); } $dont_load_members = array(); //Load Memberinfo if (!empty($id_members)) { foreach ($id_members as $comment) { if (!in_array($comment['id_member'], $dont_load_members)) { loadMemberData($comment['id_member'], false, 'profile'); loadMemberContext($comment['id_member']); //Finaly, make my context string ;) $comments[$comment['id_comment']]['member_info'] = $memberContext[$comment['id_member']]; $dont_load_members[] = $comment['id_member']; } else { $comments[$comment['id_comment']]['member_info'] = $memberContext[$comment['id_member']]; } } } $smcFunc['db_free_result']($query); return $comments; }
function Who() { global $db_prefix, $context, $scripturl, $user_info, $txt, $modSettings, $ID_MEMBER, $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'); // Sort out... the column sorting. $sort_methods = array('user' => 'mem.realName', 'time' => 'lo.logTime'); // By default order by last time online. if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']])) { $context['sort_by'] = 'time'; $_REQUEST['sort'] = 'lo.logTime'; } else { $context['sort_by'] = $_REQUEST['sort']; $_REQUEST['sort'] = $sort_methods[$_REQUEST['sort']]; } $context['sort_direction'] = isset($_REQUEST['asc']) ? 'up' : 'down'; // Get the total amount of members online. $request = db_query("\n\t\tSELECT COUNT(*)\n\t\tFROM {$db_prefix}log_online AS lo\n\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (lo.ID_MEMBER = mem.ID_MEMBER)" . (!allowedTo('moderate_forum') ? "\n\t\tWHERE IFNULL(mem.showOnline, 1) = 1" : ''), __FILE__, __LINE__); list($totalMembers) = mysql_fetch_row($request); mysql_free_result($request); // Prepare some page index variables. $context['page_index'] = constructPageIndex($scripturl . '?action=who;sort=' . $context['sort_by'] . (isset($_REQUEST['asc']) ? ';asc' : ''), $_REQUEST['start'], $totalMembers, $modSettings['defaultMaxMembers']); $context['start'] = $_REQUEST['start']; // Look for people online, provided they don't mind if you see they are. $request = db_query("\n\t\tSELECT\n\t\t\t(UNIX_TIMESTAMP(lo.logTime) - UNIX_TIMESTAMP() + " . time() . ") AS logTime,\n\t\t\tlo.ID_MEMBER, lo.url, INET_NTOA(lo.ip) AS ip, mem.realName, lo.session,\n\t\t\tmg.onlineColor, IFNULL(mem.showOnline, 1) AS showOnline\n\t\tFROM {$db_prefix}log_online AS lo\n\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (lo.ID_MEMBER = mem.ID_MEMBER)\n\t\t\tLEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = IF(mem.ID_GROUP = 0, mem.ID_POST_GROUP, mem.ID_GROUP))" . (!allowedTo('moderate_forum') ? "\n\t\tWHERE IFNULL(mem.showOnline, 1) = 1" : '') . "\n\t\tORDER BY {$_REQUEST['sort']} " . (isset($_REQUEST['asc']) ? 'ASC' : 'DESC') . "\n\t\tLIMIT {$context['start']}, {$modSettings['defaultMaxMembers']}", __FILE__, __LINE__); $context['members'] = array(); $member_ids = array(); $url_data = array(); while ($row = mysql_fetch_assoc($request)) { $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' => strtr(timeformat($row['logTime']), array($txt['smf10'] => '', $txt['smf10b'] => '')), 'timestamp' => forum_time(true, $row['logTime']), 'query' => $actions, 'is_hidden' => $row['showOnline'] == 0, 'color' => empty($row['onlineColor']) ? '' : $row['onlineColor']); $url_data[$row['session']] = array($row['url'], $row['ID_MEMBER']); $member_ids[] = $row['ID_MEMBER']; } mysql_free_result($request); // Load the user data for these members. loadMemberData($member_ids); // Load up the guest user. $memberContext[0] = array('id' => 0, 'name' => $txt[28], 'group' => $txt[28], 'href' => '', 'link' => $txt[28], 'email' => $txt[28], 'is_guest' => true); $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']; $context['members'][$i] += $memberContext[$member['id']]; } // Some people can't send personal messages... $context['can_send_pm'] = allowedTo('pm_send'); }
/** * Handles fetching the information for the helpdesk display within the unread and unread replies pages. * * The content is 'appended' below the unread posts information by way of a template layer. * * @since 2.0 */ function shd_unread_posts() { global $smcFunc, $context, $user_info, $sourcedir, $txt, $scripturl, $user_profile, $modSettings; // Are we using Dragooon's very swish mobile theme, or other wireless? If so, disable this. if (WIRELESS || isset($_REQUEST['thememode']) && $_REQUEST['thememode'] == 'mobile' || isset($_COOKIE['smf4m_cookie']) && $_COOKIE['smf4m_cookie'] == 'mobile') { $modSettings['shd_disable_unread'] = true; } // We're only displaying this to staff. We didn't do this check on bootstrapping, no sense doing it every page load. if (shd_allowed_to('shd_staff', 0) && empty($modSettings['shd_disable_unread'])) { // Get the data $context['shd_preferences'] = shd_load_user_prefs(); $context['shd_unread_info'] = array(); if (empty($context['shd_preferences']['display_unread_type']) || $context['shd_preferences']['display_unread_type'] == 'outstanding') { // Get all the outstanding tickets $context['block_title'] = $txt['shd_tickets_open']; $request = shd_db_query('', ' SELECT hdt.id_ticket, hdt.subject, hdt.id_ticket, hdt.num_replies, hdt.last_updated, hdtr_first.poster_name, hdt.urgency, hdt.status, hdt.id_member_started, hdt.id_member_assigned, hdt.id_last_msg AS log_read FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) WHERE {query_see_ticket} AND hdt.status IN ({array_int:status}) ORDER BY hdt.urgency DESC, hdt.last_updated', array('status' => array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_STAFF))); } elseif ($context['shd_preferences']['display_unread_type'] == 'unread') { // Only unread ones $context['block_title'] = $txt['shd_unread_tickets']; $request = shd_db_query('', ' SELECT hdt.id_ticket, hdt.subject, hdt.id_ticket, hdt.num_replies, hdt.last_updated, hdtr_first.poster_name, hdt.urgency, hdt.status, hdt.id_member_started, hdt.id_member_assigned, IFNULL(hdlr.id_msg, 0) AS log_read FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdt.id_ticket = hdlr.id_ticket AND hdlr.id_member = {int:user}) WHERE {query_see_ticket} AND hdt.status IN ({array_int:status}) AND (hdlr.id_msg IS NULL OR hdlr.id_msg < hdt.id_last_msg) ORDER BY hdt.urgency DESC, hdt.last_updated', array('user' => $context['user']['id'], 'status' => array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_STAFF))); } if (!empty($request)) { $members = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $row['id_ticket_display'] = str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT); $row['updated'] = timeformat($row['last_updated']); $context['shd_unread_info'][] = $row; if ($row['id_member_started'] != 0) { $members[] = $row['id_member_started']; } if ($row['id_member_assigned'] != 0) { $members[] = $row['id_member_assigned']; } } loadMemberData(array_unique($members)); foreach ($context['shd_unread_info'] as $key => $ticket) { if (!empty($user_profile[$ticket['id_member_started']])) { $context['shd_unread_info'][$key]['ticket_starter'] = shd_profile_link($user_profile[$ticket['id_member_started']]['member_name'], $ticket['id_member_started']); } else { $context['shd_unread_info'][$key]['ticket_starter'] = $ticket['poster_name']; } if (!empty($user_profile[$ticket['id_member_assigned']])) { $context['shd_unread_info'][$key]['ticket_assigned'] = shd_profile_link($user_profile[$ticket['id_member_assigned']]['member_name'], $ticket['id_member_assigned']); } else { $context['shd_unread_info'][$key]['ticket_assigned'] = '<span class="error">' . $txt['shd_unassigned'] . '</span>'; } } // And set up the template too. loadTemplate('sd_template/SimpleDesk-Unread', 'helpdesk'); $context['template_layers'][] = 'shd_unread'; } } // OK, time to get out of here. If we're here, it's because we have a $_REQUEST['action'] of 'unread' or 'unreadreplies', both of which // are defined in $context['shd_unread_actions'] thanks to shd_init_actions back in Subs-SimpleDesk.php. require_once $sourcedir . '/' . $context['shd_unread_actions'][$_REQUEST['action']][0]; $context['shd_unread_actions'][$_REQUEST['action']][1](); }
function Display() { global $scripturl, $txt, $modSettings, $context, $settings; global $options, $sourcedir, $user_info, $board_info, $topic, $board; global $attachments, $messages_request, $topicinfo, $language, $smcFunc; // What are you gonna display if these are empty?! if (empty($topic)) { fatal_lang_error('no_board', false); } // Load the proper template and/or sub template. if (WIRELESS) { $context['sub_template'] = WIRELESS_PROTOCOL . '_display'; } else { loadTemplate('Display'); } // 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']) && !WIRELESS ? $options['messages_per_page'] : $modSettings['defaultMaxMessages']; // 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) { // Just prepare some variables that are used in the query. $gt_lt = $_REQUEST['prev_next'] == 'prev' ? '>' : '<'; $order = $_REQUEST['prev_next'] == 'prev' ? '' : ' DESC'; $request = $smcFunc['db_query']('', ' SELECT t2.id_topic FROM {db_prefix}topics AS t INNER JOIN {db_prefix}topics AS t2 ON (' . (empty($modSettings['enableStickyTopics']) ? ' t2.id_last_msg ' . $gt_lt . ' t.id_last_msg' : ' (t2.id_last_msg ' . $gt_lt . ' t.id_last_msg AND t2.is_sticky ' . $gt_lt . '= t.is_sticky) OR t2.is_sticky ' . $gt_lt . ' t.is_sticky') . ') WHERE t.id_topic = {int:current_topic} AND t2.id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' AND (t2.approved = {int:is_approved} OR (t2.id_member_started != {int:id_member_started} AND t2.id_member_started = {int:current_member}))') . ' ORDER BY' . (empty($modSettings['enableStickyTopics']) ? '' : ' t2.is_sticky' . $order . ',') . ' t2.id_last_msg' . $order . ' LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic, 'is_approved' => 1, 'id_member_started' => 0)); // No more left. if ($smcFunc['db_num_rows']($request) == 0) { $smcFunc['db_free_result']($request); // Roll over - if we're going prev, get the last - otherwise the first. $request = $smcFunc['db_query']('', ' SELECT id_topic FROM {db_prefix}topics WHERE id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' AND (approved = {int:is_approved} OR (id_member_started != {int:id_member_started} AND id_member_started = {int:current_member}))') . ' ORDER BY' . (empty($modSettings['enableStickyTopics']) ? '' : ' is_sticky' . $order . ',') . ' id_last_msg' . $order . ' LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'is_approved' => 1, 'id_member_started' => 0)); } // Now you can be sure $topic is the id_topic to view. list($topic) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); $context['current_topic'] = $topic; } // Go to the newest message on this topic. $_REQUEST['start'] = 'new'; } // Add 1 to the number of views of this topic. if (empty($_SESSION['last_read_topic']) || $_SESSION['last_read_topic'] != $topic) { $smcFunc['db_query']('', ' UPDATE {db_prefix}topics SET num_views = num_views + 1 WHERE id_topic = {int:current_topic}', array('current_topic' => $topic)); $_SESSION['last_read_topic'] = $topic; } // Get all the important topic info. $request = $smcFunc['db_query']('', ' SELECT t.num_replies, t.num_views, t.locked, ms.subject, t.is_sticky, t.id_poll, t.id_member_started, t.id_first_msg, t.id_last_msg, t.approved, t.unapproved_posts, ' . ($user_info['is_guest'] ? 't.id_last_msg + 1' : 'IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1') . ' AS new_from ' . (!empty($modSettings['recycle_board']) && $modSettings['recycle_board'] == $board ? ', id_previous_board, id_previous_topic' : '') . ' FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)' . ($user_info['is_guest'] ? '' : ' LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member}) LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member})') . ' WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_member' => $user_info['id'], 'current_topic' => $topic, 'current_board' => $board)); if ($smcFunc['db_num_rows']($request) == 0) { fatal_lang_error('not_a_topic', false); } $topicinfo = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); $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']; // Add up unapproved replies to get real number of replies... if ($modSettings['postmod_active'] && allowedTo('approve_posts')) { $context['real_num_replies'] += $topicinfo['unapproved_posts'] - ($topicinfo['approved'] ? 0 : 1); } // If this topic has unapproved posts, we need to work out how many posts the user can see, for page indexing. if ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !$user_info['is_guest'] && !allowedTo('approve_posts')) { $request = $smcFunc['db_query']('', ' SELECT COUNT(id_member) AS my_unapproved_posts FROM {db_prefix}messages WHERE id_topic = {int:current_topic} AND id_member = {int:current_member} AND approved = 0', array('current_topic' => $topic, 'current_member' => $user_info['id'])); list($myUnapprovedPosts) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); $context['total_visible_posts'] = $context['num_replies'] + $myUnapprovedPosts + ($topicinfo['approved'] ? 1 : 0); } else { $context['total_visible_posts'] = $context['num_replies'] + $topicinfo['unapproved_posts'] + ($topicinfo['approved'] ? 1 : 0); } // When was the last time this topic was replied to? Should we warn them about it? $request = $smcFunc['db_query']('', ' SELECT poster_time FROM {db_prefix}messages WHERE id_msg = {int:id_last_msg} LIMIT 1', array('id_last_msg' => $topicinfo['id_last_msg'])); list($lastPostTime) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); $context['oldTopicError'] = !empty($modSettings['oldTopicDays']) && $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time() && empty($sticky); // The start isn't a number; it's information about what to do, where to go. if (!is_numeric($_REQUEST['start'])) { // Redirect to the page and post with new messages, originally by Omar Bazavilvazo. if ($_REQUEST['start'] == 'new') { // Guests automatically go to the last post. if ($user_info['is_guest']) { $context['start_from'] = $context['total_visible_posts'] - 1; $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : 0; } else { // Find the earliest unread message in the topic. (the use of topics here is just for both tables.) $request = $smcFunc['db_query']('', ' SELECT IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1 AS new_from FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member}) LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member}) WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic)); list($new_from) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // Fall through to the next if statement. $_REQUEST['start'] = 'msg' . $new_from; } } // Start from a certain time index, not a message. if (substr($_REQUEST['start'], 0, 4) == 'from') { $timestamp = (int) substr($_REQUEST['start'], 4); if ($timestamp === 0) { $_REQUEST['start'] = 0; } else { // Find the number of messages posted before said time... $request = $smcFunc['db_query']('', ' SELECT COUNT(*) FROM {db_prefix}messages WHERE poster_time < {int:timestamp} AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts') ? ' AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), array('current_topic' => $topic, 'current_member' => $user_info['id'], 'is_approved' => 1, 'timestamp' => $timestamp)); list($context['start_from']) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // Handle view_newest_first options, and get the correct start value. $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1; } } elseif (substr($_REQUEST['start'], 0, 3) == 'msg') { $virtual_msg = (int) substr($_REQUEST['start'], 3); if (!$topicinfo['unapproved_posts'] && $virtual_msg >= $topicinfo['id_last_msg']) { $context['start_from'] = $context['total_visible_posts'] - 1; } elseif (!$topicinfo['unapproved_posts'] && $virtual_msg <= $topicinfo['id_first_msg']) { $context['start_from'] = 0; } else { // Find the start value for that message...... $request = $smcFunc['db_query']('', ' SELECT COUNT(*) FROM {db_prefix}messages WHERE id_msg < {int:virtual_msg} AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts') ? ' AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'virtual_msg' => $virtual_msg, 'is_approved' => 1, 'no_member' => 0)); list($context['start_from']) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); } // We need to reverse the start as well in this case. $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1; } } // Create a previous next string if the selected theme has it as a selected option. $context['previous_next'] = $modSettings['enablePreviousNext'] ? '<a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=prev#new">' . $txt['previous_next_back'] . '</a> <a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=next#new">' . $txt['previous_next_forward'] . '</a>' : ''; // Check if spellchecking is both enabled and actually working. (for quick reply.) $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new'); // Do we need to show the visual verification image? $context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1); if ($context['require_verification']) { require_once $sourcedir . '/Subs-Editor.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 already an article? $request = $smcFunc['db_query']('', ' SELECT id_message FROM {db_prefix}sp_articles WHERE id_message = {int:message}', array('message' => $context['topic_first_message'])); list($context['topic_is_article']) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // Is this topic sticky, or can it even be? $topicinfo['is_sticky'] = empty($modSettings['enableStickyTopics']) ? '0' : $topicinfo['is_sticky']; // Default this topic to not marked for notifications... of course... $context['is_marked_notify'] = false; // Did we report a post to a moderator just now? $context['report_sent'] = isset($_GET['reportsent']); // Let's get nosey, who is viewing this topic? if (!empty($settings['display_who_viewing'])) { // Start out with no one at all viewing it. $context['view_members'] = array(); $context['view_members_list'] = array(); $context['view_num_hidden'] = 0; // Search for members who have this topic set in their GET data. $request = $smcFunc['db_query']('', ' SELECT lo.id_member, lo.log_time, mem.real_name, mem.member_name, mem.show_online, mg.online_color, mg.id_group, mg.group_name FROM {db_prefix}log_online AS lo LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member) LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_id_group} THEN mem.id_post_group ELSE mem.id_group END) WHERE INSTR(lo.url, {string:in_url_string}) > 0 OR lo.session = {string:session}', array('reg_id_group' => 0, 'in_url_string' => 's:5:"topic";i:' . $topic . ';', 'session' => $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id())); while ($row = $smcFunc['db_fetch_assoc']($request)) { if (empty($row['id_member'])) { continue; } if (!empty($row['online_color'])) { $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '" style="color: ' . $row['online_color'] . ';">' . $row['real_name'] . '</a>'; } else { $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>'; } $is_buddy = in_array($row['id_member'], $user_info['buddies']); if ($is_buddy) { $link = '<strong>' . $link . '</strong>'; } // Add them both to the list and to the more detailed list. if (!empty($row['show_online']) || allowedTo('moderate_forum')) { $context['view_members_list'][$row['log_time'] . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link; } $context['view_members'][$row['log_time'] . $row['member_name']] = array('id' => $row['id_member'], 'username' => $row['member_name'], 'name' => $row['real_name'], 'group' => $row['id_group'], 'href' => $scripturl . '?action=profile;u=' . $row['id_member'], 'link' => $link, 'is_buddy' => $is_buddy, 'hidden' => empty($row['show_online'])); if (empty($row['show_online'])) { $context['view_num_hidden']++; } } // The number of guests is equal to the rows minus the ones we actually used ;). $context['view_num_guests'] = $smcFunc['db_num_rows']($request) - count($context['view_members']); $smcFunc['db_free_result']($request); // Sort the list. krsort($context['view_members']); krsort($context['view_members_list']); } // If all is set, but not allowed... just unset it. $can_show_all = !empty($modSettings['enableAllMessages']) && $context['total_visible_posts'] > $context['messages_per_page'] && $context['total_visible_posts'] < $modSettings['enableAllMessages']; if (isset($_REQUEST['all']) && !$can_show_all) { unset($_REQUEST['all']); } elseif (isset($_REQUEST['all'])) { $_REQUEST['start'] = -1; } // Construct the page index, allowing for the .START method... $context['page_index'] = constructPageIndex($scripturl . '?topic=' . $topic . '.%1$d', $_REQUEST['start'], $context['total_visible_posts'], $context['messages_per_page'], true); $context['start'] = $_REQUEST['start']; // This is information about which page is current, and which page we're on - in case you don't like the constructed page index. (again, wireles..) $context['page_info'] = array('current_page' => $_REQUEST['start'] / $context['messages_per_page'] + 1, 'num_pages' => floor(($context['total_visible_posts'] - 1) / $context['messages_per_page']) + 1); // Figure out all the link to the next/prev/first/last/etc. for wireless mainly. $context['links'] = array('first' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.0' : '', 'prev' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] - $context['messages_per_page']) : '', 'next' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] + $context['messages_per_page']) : '', 'last' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . floor($context['total_visible_posts'] / $context['messages_per_page']) * $context['messages_per_page'] : '', 'up' => $scripturl . '?board=' . $board . '.0'); // If they are viewing all the posts, show all the posts, otherwise limit the number. if ($can_show_all) { if (isset($_REQUEST['all'])) { // No limit! (actually, there is a limit, but...) $context['messages_per_page'] = -1; $context['page_index'] .= empty($modSettings['compactTopicPagesEnable']) ? '<strong>' . $txt['all'] . '</strong> ' : '[<strong>' . $txt['all'] . '</strong>] '; // Set start back to 0... $_REQUEST['start'] = 0; } else { $context['page_index'] .= ' <a href="' . $scripturl . '?topic=' . $topic . '.0;all">' . $txt['all'] . '</a> '; } } // Build the link tree. $context['linktree'][] = array('url' => $scripturl . '?topic=' . $topic . '.0', 'name' => $topicinfo['subject'], 'extra_before' => $settings['linktree_inline'] ? $txt['topic'] . ': ' : ''); // Build a list of this board's moderators. $context['moderators'] =& $board_info['moderators']; $context['link_moderators'] = array(); if (!empty($board_info['moderators'])) { // Add a link for each moderator... foreach ($board_info['moderators'] as $mod) { $context['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $mod['id'] . '" title="' . $txt['board_moderator'] . '">' . $mod['name'] . '</a>'; } // And show it after the board's name. $context['linktree'][count($context['linktree']) - 2]['extra_after'] = ' (' . (count($context['link_moderators']) == 1 ? $txt['moderator'] : $txt['moderators']) . ': ' . implode(', ', $context['link_moderators']) . ')'; } // Information about the current topic... $context['is_locked'] = $topicinfo['locked']; $context['is_sticky'] = $topicinfo['is_sticky']; $context['is_very_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicVeryPosts']; $context['is_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicPosts']; $context['is_approved'] = $topicinfo['approved']; // We don't want to show the poll icon in the topic class here, so pretend it's not one. $context['is_poll'] = false; determineTopicClass($context); $context['is_poll'] = $topicinfo['id_poll'] > 0 && $modSettings['pollMode'] == '1' && allowedTo('poll_view'); // Did this user start the topic or not? $context['user']['started'] = $user_info['id'] == $topicinfo['id_member_started'] && !$user_info['is_guest']; $context['topic_starter_id'] = $topicinfo['id_member_started']; // Set the topic's information for the template. $context['subject'] = $topicinfo['subject']; $context['num_views'] = $topicinfo['num_views']; $context['mark_unread_time'] = $topicinfo['new_from']; // Set a canonical URL for this page. $context['canonical_url'] = $scripturl . '?topic=' . $topic . '.' . $context['start']; // For quick reply we need a response prefix in the default forum language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix', 600))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } cache_put_data('response_prefix', $context['response_prefix'], 600); } // If we want to show event information in the topic, prepare the data. if (allowedTo('calendar_view') && !empty($modSettings['cal_showInTopic']) && !empty($modSettings['cal_enabled'])) { // First, try create a better time format, ignoring the "time" elements. if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) { $date_string = $user_info['time_format']; } else { $date_string = $matches[0]; } // Any calendar information for this topic? $request = $smcFunc['db_query']('', ' SELECT cal.id_event, cal.start_date, cal.end_date, cal.title, cal.id_member, mem.real_name FROM {db_prefix}calendar AS cal LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = cal.id_member) WHERE cal.id_topic = {int:current_topic} ORDER BY start_date', array('current_topic' => $topic)); $context['linked_calendar_events'] = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Prepare the dates for being formatted. $start_date = sscanf($row['start_date'], '%04d-%02d-%02d'); $start_date = mktime(12, 0, 0, $start_date[1], $start_date[2], $start_date[0]); $end_date = sscanf($row['end_date'], '%04d-%02d-%02d'); $end_date = mktime(12, 0, 0, $end_date[1], $end_date[2], $end_date[0]); $context['linked_calendar_events'][] = array('id' => $row['id_event'], 'title' => $row['title'], 'can_edit' => allowedTo('calendar_edit_any') || $row['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own'), 'modify_href' => $scripturl . '?action=post;msg=' . $topicinfo['id_first_msg'] . ';topic=' . $topic . '.0;calendar;eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], 'start_date' => timeformat($start_date, $date_string, 'none'), 'start_timestamp' => $start_date, 'end_date' => timeformat($end_date, $date_string, 'none'), 'end_timestamp' => $end_date, 'is_last' => false); } $smcFunc['db_free_result']($request); if (!empty($context['linked_calendar_events'])) { $context['linked_calendar_events'][count($context['linked_calendar_events']) - 1]['is_last'] = true; } } // Create the poll info if it exists. if ($context['is_poll']) { // Get the question and if it's locked. $request = $smcFunc['db_query']('', ' SELECT p.question, p.voting_locked, p.hide_results, p.expire_time, p.max_votes, p.change_vote, p.guest_vote, p.id_member, IFNULL(mem.real_name, p.poster_name) AS poster_name, p.num_guest_voters, p.reset_poll FROM {db_prefix}polls AS p LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = p.id_member) WHERE p.id_poll = {int:id_poll} LIMIT 1', array('id_poll' => $topicinfo['id_poll'])); $pollinfo = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); $request = $smcFunc['db_query']('', ' SELECT COUNT(DISTINCT id_member) AS total FROM {db_prefix}log_polls WHERE id_poll = {int:id_poll} AND id_member != {int:not_guest}', array('id_poll' => $topicinfo['id_poll'], 'not_guest' => 0)); list($pollinfo['total']) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // Total voters needs to include guest voters $pollinfo['total'] += $pollinfo['num_guest_voters']; // Get all the options, and calculate the total votes. $request = $smcFunc['db_query']('', ' SELECT pc.id_choice, pc.label, pc.votes, IFNULL(lp.id_choice, -1) AS voted_this FROM {db_prefix}poll_choices AS pc LEFT JOIN {db_prefix}log_polls AS lp ON (lp.id_choice = pc.id_choice AND lp.id_poll = {int:id_poll} AND lp.id_member = {int:current_member} AND lp.id_member != {int:not_guest}) WHERE pc.id_poll = {int:id_poll}', array('current_member' => $user_info['id'], 'id_poll' => $topicinfo['id_poll'], 'not_guest' => 0)); $pollOptions = array(); $realtotal = 0; $pollinfo['has_voted'] = false; while ($row = $smcFunc['db_fetch_assoc']($request)) { censorText($row['label']); $pollOptions[$row['id_choice']] = $row; $realtotal += $row['votes']; $pollinfo['has_voted'] |= $row['voted_this'] != -1; } $smcFunc['db_free_result']($request); // If this is a guest we need to do our best to work out if they have voted, and what they voted for. if ($user_info['is_guest'] && $pollinfo['guest_vote'] && allowedTo('poll_vote')) { if (!empty($_COOKIE['guest_poll_vote']) && preg_match('~^[0-9,;]+$~', $_COOKIE['guest_poll_vote']) && strpos($_COOKIE['guest_poll_vote'], ';' . $topicinfo['id_poll'] . ',') !== false) { // ;id,timestamp,[vote,vote...]; etc $guestinfo = explode(';', $_COOKIE['guest_poll_vote']); // Find the poll we're after. foreach ($guestinfo as $i => $guestvoted) { $guestvoted = explode(',', $guestvoted); if ($guestvoted[0] == $topicinfo['id_poll']) { break; } } // Has the poll been reset since guest voted? if ($pollinfo['reset_poll'] > $guestvoted[1]) { // Remove the poll info from the cookie to allow guest to vote again unset($guestinfo[$i]); if (!empty($guestinfo)) { $_COOKIE['guest_poll_vote'] = ';' . implode(';', $guestinfo); } else { unset($_COOKIE['guest_poll_vote']); } } else { // What did they vote for? unset($guestvoted[0], $guestvoted[1]); foreach ($pollOptions as $choice => $details) { $pollOptions[$choice]['voted_this'] = in_array($choice, $guestvoted) ? 1 : -1; $pollinfo['has_voted'] |= $pollOptions[$choice]['voted_this'] != -1; } unset($choice, $details, $guestvoted); } unset($guestinfo, $guestvoted, $i); } } // Set up the basic poll information. $context['poll'] = array('id' => $topicinfo['id_poll'], 'image' => 'normal_' . (empty($pollinfo['voting_locked']) ? 'poll' : 'locked_poll'), 'question' => parse_bbc($pollinfo['question']), 'total_votes' => $pollinfo['total'], 'change_vote' => !empty($pollinfo['change_vote']), 'is_locked' => !empty($pollinfo['voting_locked']), 'options' => array(), 'lock' => allowedTo('poll_lock_any') || $context['user']['started'] && allowedTo('poll_lock_own'), 'edit' => allowedTo('poll_edit_any') || $context['user']['started'] && allowedTo('poll_edit_own'), 'allowed_warning' => $pollinfo['max_votes'] > 1 ? sprintf($txt['poll_options6'], min(count($pollOptions), $pollinfo['max_votes'])) : '', 'is_expired' => !empty($pollinfo['expire_time']) && $pollinfo['expire_time'] < time(), 'expire_time' => !empty($pollinfo['expire_time']) ? timeformat($pollinfo['expire_time']) : 0, 'has_voted' => !empty($pollinfo['has_voted']), 'starter' => array('id' => $pollinfo['id_member'], 'name' => $row['poster_name'], 'href' => $pollinfo['id_member'] == 0 ? '' : $scripturl . '?action=profile;u=' . $pollinfo['id_member'], 'link' => $pollinfo['id_member'] == 0 ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $pollinfo['id_member'] . '">' . $row['poster_name'] . '</a>')); // Make the lock and edit permissions defined above more directly accessible. $context['allow_lock_poll'] = $context['poll']['lock']; $context['allow_edit_poll'] = $context['poll']['edit']; // You're allowed to vote if: // 1. the poll did not expire, and // 2. you're either not a guest OR guest voting is enabled... and // 3. you're not trying to view the results, and // 4. the poll is not locked, and // 5. you have the proper permissions, and // 6. you haven't already voted before. $context['allow_vote'] = !$context['poll']['is_expired'] && (!$user_info['is_guest'] || $pollinfo['guest_vote'] && allowedTo('poll_vote')) && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && !$context['poll']['has_voted']; // You're allowed to view the results if: // 1. you're just a super-nice-guy, or // 2. anyone can see them (hide_results == 0), or // 3. you can see them after you voted (hide_results == 1), or // 4. you've waited long enough for the poll to expire. (whether hide_results is 1 or 2.) $context['allow_poll_view'] = allowedTo('moderate_board') || $pollinfo['hide_results'] == 0 || $pollinfo['hide_results'] == 1 && $context['poll']['has_voted'] || $context['poll']['is_expired']; $context['poll']['show_results'] = $context['allow_poll_view'] && (isset($_REQUEST['viewresults']) || isset($_REQUEST['viewResults'])); $context['show_view_results_button'] = $context['allow_vote'] && (!$context['allow_poll_view'] || !$context['poll']['show_results'] || !$context['poll']['has_voted']); // You're allowed to change your vote if: // 1. the poll did not expire, and // 2. you're not a guest... and // 3. the poll is not locked, and // 4. you have the proper permissions, and // 5. you have already voted, and // 6. the poll creator has said you can! $context['allow_change_vote'] = !$context['poll']['is_expired'] && !$user_info['is_guest'] && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && $context['poll']['has_voted'] && $context['poll']['change_vote']; // You're allowed to return to voting options if: // 1. you are (still) allowed to vote. // 2. you are currently seeing the results. $context['allow_return_vote'] = $context['allow_vote'] && $context['poll']['show_results']; // Calculate the percentages and bar lengths... $divisor = $realtotal == 0 ? 1 : $realtotal; // Determine if a decimal point is needed in order for the options to add to 100%. $precision = $realtotal == 100 ? 0 : 1; // Now look through each option, and... foreach ($pollOptions as $i => $option) { // First calculate the percentage, and then the width of the bar... $bar = round($option['votes'] * 100 / $divisor, $precision); $barWide = $bar == 0 ? 1 : floor($bar * 8 / 3); // Now add it to the poll's contextual theme data. $context['poll']['options'][$i] = array('id' => 'options-' . $i, 'percent' => $bar, 'votes' => $option['votes'], 'voted_this' => $option['voted_this'] != -1, 'bar' => '<span style="white-space: nowrap;"><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'right' : 'left') . '.gif" alt="" /><img src="' . $settings['images_url'] . '/poll_middle.gif" width="' . $barWide . '" height="12" alt="-" /><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'left' : 'right') . '.gif" alt="" /></span>', 'bar_ndt' => $bar > 0 ? '<div class="bar" style="width: ' . ($bar * 3.5 + 4) . 'px;"><div style="width: ' . $bar * 3.5 . 'px;"></div></div>' : '', 'bar_width' => $barWide, 'option' => parse_bbc($option['label']), 'vote_button' => '<input type="' . ($pollinfo['max_votes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="input_' . ($pollinfo['max_votes'] > 1 ? 'check' : 'radio') . '" />'); } } // Calculate the fastest way to get the messages! $ascending = empty($options['view_newest_first']); $start = $_REQUEST['start']; $limit = $context['messages_per_page']; $firstIndex = 0; if ($start >= $context['total_visible_posts'] / 2 && $context['messages_per_page'] != -1) { $ascending = !$ascending; $limit = $context['total_visible_posts'] <= $start + $limit ? $context['total_visible_posts'] - $start : $limit; $start = $context['total_visible_posts'] <= $start + $limit ? 0 : $context['total_visible_posts'] - $start - $limit; $firstIndex = $limit - 1; } // Get each post and poster in this topic. $request = $smcFunc['db_query']('display_get_post_poster', ' SELECT id_msg, id_member, approved FROM {db_prefix}messages WHERE id_topic = {int:current_topic}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : (!empty($modSettings['db_mysql_group_by_fix']) ? '' : ' GROUP BY id_msg') . ' HAVING (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')') . ' ORDER BY id_msg ' . ($ascending ? '' : 'DESC') . ($context['messages_per_page'] == -1 ? '' : ' LIMIT ' . $start . ', ' . $limit), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'is_approved' => 1, 'blank_id_member' => 0)); $messages = array(); $all_posters = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { if (!empty($row['id_member'])) { $all_posters[$row['id_msg']] = $row['id_member']; } $messages[] = $row['id_msg']; } $smcFunc['db_free_result']($request); $posters = array_unique($all_posters); // Guests can't mark topics read or for notifications, just can't sorry. if (!$user_info['is_guest']) { $mark_at_msg = max($messages); if ($mark_at_msg >= $topicinfo['id_last_msg']) { $mark_at_msg = $modSettings['maxMsgID']; } if ($mark_at_msg >= $topicinfo['new_from']) { $smcFunc['db_insert']($topicinfo['new_from'] == 0 ? 'ignore' : 'replace', '{db_prefix}log_topics', array('id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int'), array($user_info['id'], $topic, $mark_at_msg), array('id_member', 'id_topic')); } // Check for notifications on this topic OR board. $request = $smcFunc['db_query']('', ' SELECT sent, id_topic FROM {db_prefix}log_notify WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board}) AND id_member = {int:current_member} LIMIT 2', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic)); $do_once = true; while ($row = $smcFunc['db_fetch_assoc']($request)) { // Find if this topic is marked for notification... if (!empty($row['id_topic'])) { $context['is_marked_notify'] = true; } // Only do this once, but mark the notifications as "not sent yet" for next time. if (!empty($row['sent']) && $do_once) { $smcFunc['db_query']('', ' UPDATE {db_prefix}log_notify SET sent = {int:is_not_sent} WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board}) AND id_member = {int:current_member}', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic, 'is_not_sent' => 0)); $do_once = false; } } // Have we recently cached the number of new topics in this board, and it's still a lot? if (isset($_REQUEST['topicseen']) && isset($_SESSION['topicseen_cache'][$board]) && $_SESSION['topicseen_cache'][$board] > 5) { $_SESSION['topicseen_cache'][$board]--; } elseif (isset($_REQUEST['topicseen'])) { // Use the mark read tables... and the last visit to figure out if this should be read or not. $request = $smcFunc['db_query']('', ' SELECT COUNT(*) FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = {int:current_board} AND lb.id_member = {int:current_member}) LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) WHERE t.id_board = {int:current_board} AND t.id_last_msg > IFNULL(lb.id_msg, 0) AND t.id_last_msg > IFNULL(lt.id_msg, 0)' . (empty($_SESSION['id_msg_last_visit']) ? '' : ' AND t.id_last_msg > {int:id_msg_last_visit}'), array('current_board' => $board, 'current_member' => $user_info['id'], 'id_msg_last_visit' => (int) $_SESSION['id_msg_last_visit'])); list($numNewTopics) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // If there're no real new topics in this board, mark the board as seen. if (empty($numNewTopics)) { $_REQUEST['boardseen'] = true; } else { $_SESSION['topicseen_cache'][$board] = $numNewTopics; } } elseif (isset($_SESSION['topicseen_cache'][$board])) { $_SESSION['topicseen_cache'][$board]--; } // Mark board as seen if we came using last post link from BoardIndex. (or other places...) if (isset($_REQUEST['boardseen'])) { $smcFunc['db_insert']('replace', '{db_prefix}log_boards', array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), array($modSettings['maxMsgID'], $user_info['id'], $board), array('id_member', 'id_board')); } } $attachments = array(); // If there _are_ messages here... (probably an error otherwise :!) if (!empty($messages)) { // Fetch attachments. if (!empty($modSettings['attachmentEnable']) && allowedTo('view_attachments')) { $request = $smcFunc['db_query']('', ' SELECT a.id_attach, a.id_folder, a.id_msg, a.filename, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved, a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ', IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . ' FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ' LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . ' WHERE a.id_msg IN ({array_int:message_list}) AND a.attachment_type = {int:attachment_type}', array('message_list' => $messages, 'attachment_type' => 0, 'is_approved' => 1)); $temp = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id'])) { continue; } $temp[$row['id_attach']] = $row; if (!isset($attachments[$row['id_msg']])) { $attachments[$row['id_msg']] = array(); } } $smcFunc['db_free_result']($request); // This is better than sorting it with the query... ksort($temp); foreach ($temp as $row) { $attachments[$row['id_msg']][] = $row; } } // What? It's not like it *couldn't* be only guests in this topic... if (!empty($posters)) { loadMemberData($posters); } $messages_request = $smcFunc['db_query']('', ' SELECT id_msg, icon, subject, poster_time, poster_ip, id_member, modified_time, modified_name, body, smileys_enabled, poster_name, poster_email, approved, id_msg_modified < {int:new_from} AS is_read FROM {db_prefix}messages WHERE id_msg IN ({array_int:message_list}) ORDER BY id_msg' . (empty($options['view_newest_first']) ? '' : ' DESC'), array('message_list' => $messages, 'new_from' => $topicinfo['new_from'])); // Go to the last message if the given time is beyond the time of the last message. if (isset($context['start_from']) && $context['start_from'] >= $topicinfo['num_replies']) { $context['start_from'] = $topicinfo['num_replies']; } // Since the anchor information is needed on the top of the page we load these variables beforehand. $context['first_message'] = isset($messages[$firstIndex]) ? $messages[$firstIndex] : $messages[0]; if (empty($options['view_newest_first'])) { $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['start_from']; } else { $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $topicinfo['num_replies'] - $context['start_from']; } } else { $messages_request = false; $context['first_message'] = 0; $context['first_new_message'] = false; } $context['jump_to'] = array('label' => addslashes(un_htmlspecialchars($txt['jump_to'])), 'board_name' => htmlspecialchars(strtr(strip_tags($board_info['name']), array('&' => '&'))), 'child_level' => $board_info['child_level']); // Set the callback. (do you REALIZE how much memory all the messages would take?!?) $context['get_message'] = 'prepareDisplayContext'; // Now set all the wonderful, wonderful permissions... like moderation ones... $common_permissions = array('can_approve' => 'approve_posts', 'can_ban' => 'manage_bans', 'can_sticky' => 'make_sticky', 'can_merge' => 'merge_any', 'can_split' => 'split_any', 'calendar_post' => 'calendar_post', 'can_mark_notify' => 'mark_any_notify', 'can_send_topic' => 'send_topic', 'can_send_pm' => 'pm_send', 'can_report_moderator' => 'report_any', 'can_moderate_forum' => 'moderate_forum', 'can_issue_warning' => 'issue_warning', 'can_restore_topic' => 'move_any', 'can_restore_msg' => 'move_any'); foreach ($common_permissions as $contextual => $perm) { $context[$contextual] = allowedTo($perm); } // Permissions with _any/_own versions. $context[YYY] => ZZZ_any/_own. $anyown_permissions = array('can_move' => 'move', 'can_lock' => 'lock', 'can_delete' => 'remove', 'can_add_poll' => 'poll_add', 'can_remove_poll' => 'poll_remove', 'can_reply' => 'post_reply', 'can_reply_unapproved' => 'post_unapproved_replies'); foreach ($anyown_permissions as $contextual => $perm) { $context[$contextual] = allowedTo($perm . '_any') || $context['user']['started'] && allowedTo($perm . '_own'); } // Cleanup all the permissions with extra stuff... $context['can_mark_notify'] &= !$context['user']['is_guest']; $context['can_sticky'] &= !empty($modSettings['enableStickyTopics']); $context['calendar_post'] &= !empty($modSettings['cal_enabled']); $context['can_add_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['id_poll'] <= 0; $context['can_remove_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['id_poll'] > 0; $context['can_reply'] &= empty($topicinfo['locked']) || allowedTo('moderate_board'); $context['can_reply_unapproved'] &= $modSettings['postmod_active'] && (empty($topicinfo['locked']) || allowedTo('moderate_board')); $context['can_issue_warning'] &= in_array('w', $context['admin_features']) && $modSettings['warning_settings'][0] == 1; // Handle approval flags... $context['can_reply_approved'] = $context['can_reply']; $context['can_reply'] |= $context['can_reply_unapproved']; $context['can_quote'] = $context['can_reply'] && (empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']))); $context['can_mark_unread'] = !$user_info['is_guest'] && $settings['show_mark_read']; $context['can_send_topic'] = (!$modSettings['postmod_active'] || $topicinfo['approved']) && allowedTo('send_topic'); // Start this off for quick moderation - it will be or'd for each post. $context['can_remove_post'] = allowedTo('delete_any') || allowedTo('delete_replies') && $context['user']['started']; // Can restore topic? That's if the topic is in the recycle board and has a previous restore state. $context['can_restore_topic'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_board']); $context['can_restore_msg'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_topic']); // Wireless shows a "more" if you can do anything special. if (WIRELESS && WIRELESS_PROTOCOL != 'wap') { $context['wireless_more'] = $context['can_sticky'] || $context['can_lock'] || allowedTo('modify_any'); $context['wireless_moderate'] = isset($_GET['moderate']) ? ';moderate' : ''; } // 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'] : ''; } }
AutoTask(); } // Register an error handler. set_error_handler('error_handler'); // Start the session. (assuming it hasn't already been.) loadSession(); $sc = $_SESSION['session_value']; $_GET[$_SESSION['session_var']] = $_SESSION['session_value']; $_POST[$_SESSION['session_var']] = $_SESSION['session_value']; define('WIRELESS', false); if (isset($_GET['user_id'])) { $user = loadMemberData(intval($_GET['user_id']), false, 'profile'); } elseif (isset($_GET['username'])) { $user = loadMemberData(base64_decode($_GET['username']), true, 'profile'); if (empty($user)) { $user = loadMemberData($_GET['username'], true, 'profile'); } } else { exit; } $url = ''; if (isset($user[0]) && !empty($user[0])) { if (empty($url)) { $memID = $user[0]; $context['id_member'] = $user[0]; $GLOBALS['cur_profile'] = $GLOBALS['user_profile'][$memID]; loadMemberContext($memID); if (isset($GLOBALS['memberContext'][$memID]['avatar']['href'])) { $url = $GLOBALS['memberContext'][$memID]['avatar']['href']; header("Location: {$url}", 0, 303); @ob_end_clean();
function ViewErrorLog() { global $scripturl, $txt, $context, $modSettings, $user_profile, $filter, $boarddir, $sourcedir, $themedir, $smcFunc; // Viewing contents of a file? if (isset($_GET['file'])) { return ViewFile(); } // Check for the administrative permission to do this. isAllowedTo('admin_forum'); // Templates, etc... loadLanguage('ManageMaintenance'); loadTemplate('Errors'); // You can filter by any of the following columns: $filters = array('id_member' => $txt['username'], 'ip' => $txt['ip_address'], 'session' => $txt['session'], 'url' => $txt['error_url'], 'message' => $txt['error_message'], 'error_type' => $txt['error_type'], 'file' => $txt['file'], 'line' => $txt['line']); // Set up the filtering... if (isset($_GET['value'], $_GET['filter']) && isset($filters[$_GET['filter']])) { $filter = array('variable' => $_GET['filter'], 'value' => array('sql' => in_array($_GET['filter'], array('message', 'url', 'file')) ? base64_decode(strtr($_GET['value'], array(' ' => '+'))) : $smcFunc['db_escape_wildcard_string']($_GET['value'])), 'href' => ';filter=' . $_GET['filter'] . ';value=' . $_GET['value'], 'entity' => $filters[$_GET['filter']]); } // Deleting, are we? if (isset($_POST['delall']) || isset($_POST['delete'])) { deleteErrors(); } // Just how many errors are there? $result = $smcFunc['db_query']('', ' SELECT COUNT(*) FROM {db_prefix}log_errors' . (isset($filter) ? ' WHERE ' . $filter['variable'] . ' LIKE {string:filter}' : ''), array('filter' => isset($filter) ? $filter['value']['sql'] : '')); list($num_errors) = $smcFunc['db_fetch_row']($result); $smcFunc['db_free_result']($result); // If this filter is empty... if ($num_errors == 0 && isset($filter)) { redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '')); } // Clean up start. if (!isset($_GET['start']) || $_GET['start'] < 0) { $_GET['start'] = 0; } // Do we want to reverse error listing? $context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up'; // Set the page listing up. $context['page_index'] = constructPageIndex($scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : '') . (isset($filter) ? $filter['href'] : ''), $_GET['start'], $num_errors, $modSettings['defaultMaxMessages']); $context['start'] = $_GET['start']; // Find and sort out the errors. $request = $smcFunc['db_query']('', ' SELECT id_error, id_member, ip, url, log_time, message, session, error_type, file, line FROM {db_prefix}log_errors' . (isset($filter) ? ' WHERE ' . $filter['variable'] . ' LIKE {string:filter}' : '') . ' ORDER BY id_error ' . ($context['sort_direction'] == 'down' ? 'DESC' : '') . ' LIMIT ' . $_GET['start'] . ', ' . $modSettings['defaultMaxMessages'], array('filter' => isset($filter) ? $filter['value']['sql'] : '')); $context['errors'] = array(); $members = array(); for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++) { $search_message = preg_replace('~<span class="remove">(.+?)</span>~', '%', $smcFunc['db_escape_wildcard_string']($row['message'])); if ($search_message == $filter['value']['sql']) { $search_message = $smcFunc['db_escape_wildcard_string']($row['message']); } $show_message = strtr(strtr(preg_replace('~<span class="remove">(.+?)</span>~', '$1', $row['message']), array("\r" => '', '<br />' => "\n", '<' => '<', '>' => '>', '"' => '"')), array("\n" => '<br />')); $context['errors'][$row['id_error']] = array('alternate' => $i % 2 == 0, 'member' => array('id' => $row['id_member'], 'ip' => $row['ip'], 'session' => $row['session']), 'time' => timeformat($row['log_time']), 'timestamp' => $row['log_time'], 'url' => array('html' => htmlspecialchars((substr($row['url'], 0, 1) == '?' ? $scripturl : '') . $row['url']), 'href' => base64_encode($smcFunc['db_escape_wildcard_string']($row['url']))), 'message' => array('html' => $show_message, 'href' => base64_encode($search_message)), 'id' => $row['id_error'], 'error_type' => array('type' => $row['error_type'], 'name' => isset($txt['errortype_' . $row['error_type']]) ? $txt['errortype_' . $row['error_type']] : $row['error_type']), 'file' => array()); if (!empty($row['file']) && !empty($row['line'])) { // Eval'd files rarely point to the right location and cause havoc for linking, so don't link them. $linkfile = strpos($row['file'], 'eval') === false || strpos($row['file'], '?') === false; // De Morgan's Law. Want this true unless both are present. $context['errors'][$row['id_error']]['file'] = array('file' => $row['file'], 'line' => $row['line'], 'href' => $scripturl . '?action=admin;area=logs;sa=errorlog;file=' . base64_encode($row['file']) . ';line=' . $row['line'], 'link' => $linkfile ? '<a href="' . $scripturl . '?action=admin;area=logs;sa=errorlog;file=' . base64_encode($row['file']) . ';line=' . $row['line'] . '" onclick="return reqWin(this.href, 600, 400, false);">' . $row['file'] . '</a>' : $row['file'], 'search' => base64_encode($row['file'])); } // Make a list of members to load later. $members[$row['id_member']] = $row['id_member']; } $smcFunc['db_free_result']($request); // Load the member data. if (!empty($members)) { // Get some additional member info... $request = $smcFunc['db_query']('', ' SELECT id_member, member_name, real_name FROM {db_prefix}members WHERE id_member IN ({array_int:member_list}) LIMIT ' . count($members), array('member_list' => $members)); while ($row = $smcFunc['db_fetch_assoc']($request)) { $members[$row['id_member']] = $row; } $smcFunc['db_free_result']($request); // This is a guest... $members[0] = array('id_member' => 0, 'member_name' => '', 'real_name' => $txt['guest_title']); // Go through each error and tack the data on. foreach ($context['errors'] as $id => $dummy) { $memID = $context['errors'][$id]['member']['id']; $context['errors'][$id]['member']['username'] = $members[$memID]['member_name']; $context['errors'][$id]['member']['name'] = $members[$memID]['real_name']; $context['errors'][$id]['member']['href'] = empty($memID) ? '' : $scripturl . '?action=profile;u=' . $memID; $context['errors'][$id]['member']['link'] = empty($memID) ? $txt['guest_title'] : '<a href="' . $scripturl . '?action=profile;u=' . $memID . '">' . $context['errors'][$id]['member']['name'] . '</a>'; } } // Filtering anything? if (isset($filter)) { $context['filter'] =& $filter; // Set the filtering context. if ($filter['variable'] == 'id_member') { $id = $filter['value']['sql']; loadMemberData($id, false, 'minimal'); $context['filter']['value']['html'] = '<a href="' . $scripturl . '?action=profile;u=' . $id . '">' . $user_profile[$id]['real_name'] . '</a>'; } elseif ($filter['variable'] == 'url') { $context['filter']['value']['html'] = '\'' . strtr(htmlspecialchars((substr($filter['value']['sql'], 0, 1) == '?' ? $scripturl : '') . $filter['value']['sql']), array('\\_' => '_')) . '\''; } elseif ($filter['variable'] == 'message') { $context['filter']['value']['html'] = '\'' . strtr(htmlspecialchars($filter['value']['sql']), array("\n" => '<br />', '<br />' => '<br />', "\t" => ' ', '\\_' => '_', '\\%' => '%', '\\\\' => '\\')) . '\''; $context['filter']['value']['html'] = preg_replace('~&lt;span class=&quot;remove&quot;&gt;(.+?)&lt;/span&gt;~', '$1', $context['filter']['value']['html']); } elseif ($filter['variable'] == 'error_type') { $context['filter']['value']['html'] = '\'' . strtr(htmlspecialchars($filter['value']['sql']), array("\n" => '<br />', '<br />' => '<br />', "\t" => ' ', '\\_' => '_', '\\%' => '%', '\\\\' => '\\')) . '\''; } else { $context['filter']['value']['html'] =& $filter['value']['sql']; } } $context['error_types'] = array(); $context['error_types']['all'] = array('label' => $txt['errortype_all'], 'description' => isset($txt['errortype_all_desc']) ? $txt['errortype_all_desc'] : '', 'url' => $scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : ''), 'is_selected' => empty($filter)); $sum = 0; // What type of errors do we have and how many do we have? $request = $smcFunc['db_query']('', ' SELECT error_type, COUNT(*) AS num_errors FROM {db_prefix}log_errors GROUP BY error_type ORDER BY error_type = {string:critical_type} DESC, error_type ASC', array('critical_type' => 'critical')); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Total errors so far? $sum += $row['num_errors']; $context['error_types'][$sum] = array('label' => (isset($txt['errortype_' . $row['error_type']]) ? $txt['errortype_' . $row['error_type']] : $row['error_type']) . ' (' . $row['num_errors'] . ')', 'description' => isset($txt['errortype_' . $row['error_type'] . '_desc']) ? $txt['errortype_' . $row['error_type'] . '_desc'] : '', 'url' => $scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : '') . ';filter=error_type;value=' . $row['error_type'], 'is_selected' => isset($filter) && $filter['value']['sql'] == $smcFunc['db_escape_wildcard_string']($row['error_type'])); } $smcFunc['db_free_result']($request); // Update the all errors tab with the total number of errors $context['error_types']['all']['label'] .= ' (' . $sum . ')'; // Finally, work out what is the last tab! if (isset($context['error_types'][$sum])) { $context['error_types'][$sum]['is_last'] = true; } else { $context['error_types']['all']['is_last'] = true; } // And this is pretty basic ;). $context['page_title'] = $txt['errlog']; $context['has_filter'] = isset($filter); $context['sub_template'] = 'error_log'; }
function verify_smf_userids_from_names($names) { $direct_ids = array(); $valid_names = array(); $verified_ids = array(); foreach ($names as $index => $user) { if (is_numeric($user) && $user == intval($user)) { $direct_ids[] = $user; } else { $valid_names[] = $user; } } if (!empty($valid_names)) { $loaded_ids = loadMemberData($valid_names, true); //make sure tids only contains integer values if (is_array($loaded_ids)) { foreach ($loaded_ids as $idx => $loaded_id) { if (is_numeric($loaded_id) && $loaded_id == intval($loaded_id)) { $verified_ids[] = $loaded_id; } } } else { if (is_numeric($loaded_ids) && $loaded_ids == intval($loaded_ids)) { $verified_ids[] = $loaded_ids; } } } $verified_ids = array_unique(array_merge($direct_ids, $verified_ids)); return $verified_ids; }