Facebook  Twitter 

SMFHacks.com

+-

SMFHacks.com

+- User Information

Welcome, Guest.
Please login or register.
 
 
 
Forgot your password?

+- Forum Stats

Members
Total Members: 4255
Latest: andreios
New This Month: 3
New This Week: 1
New Today: 0
Stats
Total Posts: 43259
Total Topics: 7518
Most Online Today: 201
Most Online Ever: 2482
(April 09, 2011, 07:02:45 pm)
Users Online
Members: 0
Guests: 183
Total: 183

Author Topic: Modification allowing Admins to view Private Messages  (Read 31464 times)

0 Members and 1 Guest are viewing this topic.

Offline Transition

  • Member
  • *
  • Posts: 3
    • View Profile
Modification allowing Admins to view Private Messages
« on: June 14, 2013, 11:01:00 pm »
I understand this has been a long debated topic on whether it is ethical for Admins to read private messages between members, but I'm not really here to talk about that. I understand that SMF is against such a mod. However, I have good reason to in my position. In my case, I have members who first try going against the rules publicly conversing about trading other programmer's source code which they sell. I know that on many occasions members have complained about PMs asking for quick free copies.

When looking up this topic on the net, I came across the post below. It looks like someone was able to create a mod that is read-only view of the PM traffic. Unfortunately those Mediafire files are down. Does anyone have those particular files, or has such a complete mod like this?

http://www.smfhacks.com/index.php/topic,226.msg27271.html#msg27271

Thanks in advance for any help!

BTW, I'm running 1.1.18

Offline AcEAndroid

  • Member
  • *
  • Posts: 3
    • View Profile
Re: Modification allowing Admins to view Private Messages
« Reply #1 on: June 15, 2013, 04:30:54 am »
The links have been updated.

This mod is confirmed working on SMF 2.0, 2.0.1, and 2.0.2 (hasn't been tested on anything newer) I can't guarantee it will work on 1.1.18, as the managepm.php file is a modified pm.php file from 2.0. However, your free to try, its a separate file, so it can't break anything, and its easy to remove it if doesn't work.

Offline Transition

  • Member
  • *
  • Posts: 3
    • View Profile
Re: Modification allowing Admins to view Private Messages
« Reply #2 on: June 15, 2013, 05:02:00 pm »
Thanks for re-upping the files! Unfortunately, it doesn't seem to work with 1.1.18, but when I have some free time I'll see if I could port it over. I'm sure there can't be too many differences between the two pm.php files.

Offline AcEAndroid

  • Member
  • *
  • Posts: 3
    • View Profile
Re: Modification allowing Admins to view Private Messages
« Reply #3 on: June 15, 2013, 08:34:38 pm »
If you upload a copy of the 1.1.18 pm.php file, I might have some time to look at it.

Offline Transition

  • Member
  • *
  • Posts: 3
    • View Profile
Re: Modification allowing Admins to view Private Messages
« Reply #4 on: June 28, 2013, 07:37:04 pm »
If you upload a copy of the 1.1.18 pm.php file, I might have some time to look at it.

Is the file named PersonalMessage.php in Sources what you would need? The code for it is below...

[code]<?php
/**********************************************************************************
* PersonalMessage.php                                                             *
***********************************************************************************
* SMF: Simple Machines Forum                                                      *
* Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com)                    *
* =============================================================================== *
* Software Version:           SMF 1.1.10                                          *
* Software by:                Simple Machines (http://www.simplemachines.org)     *
* Copyright 2006-2009 by:     Simple Machines LLC (http://www.simplemachines.org) *
*           2001-2006 by:     Lewis Media (http://www.lewismedia.com)             *
* Support, News, Updates at:  http://www.simplemachines.org                       *
***********************************************************************************
* This program is free software; you may redistribute it and/or modify it under   *
* the terms of the provided license as published by Simple Machines LLC.          *
*                                                                                 *
* This program is distributed in the hope that it is and will be useful, but      *
* WITHOUT ANY WARRANTIES; without even any implied warranty of MERCHANTABILITY    *
* or FITNESS FOR A PARTICULAR PURPOSE.                                            *
*                                                                                 *
* See the "license.txt" file for details of the Simple Machines license.          *
* The latest version can always be found at http://www.simplemachines.org.        *
**********************************************************************************/
if (!defined('SMF'))
   die('Hacking attempt...');

/*   This file is mainly meant for viewing personal messages.  It also sends,
   deletes, and marks personal messages.  For compatibility reasons, they are
   often called "instant messages".  The following functions are used:

   void MessageMain()
      // !!! ?action=pm

   void messageIndexBar(string area)
      // !!!

   void MessageFolder()
      // !!! ?action=pm;sa=folder

   void prepareMessageContext(bool reset = false)
      // !!!

   void MessageSearch()
      // !!!

   void MessageSearch2()
      // !!!

   void MessagePost()
      // !!! ?action=pm;sa=post

   void messagePostError(array error_types, string to, string bcc)
      // !!!

   void MessagePost2()
      // !!! ?action=pm;sa=post2

   void WirelessAddBuddy()
      // !!!

   void MessageActionsApply()
      // !!! ?action=pm;sa=pmactions

   void MessageKillAllQuery()
      // !!! ?action=pm;sa=killall

   void MessageKillAll()
      // !!! ?action=pm;sa=killall2

   void MessagePrune()
      // !!! ?action=pm;sa=prune

   void deleteMessages(array personal_messages, string folder,
         int owner = user)
      // !!!

   void markMessages(array personal_messages = all, int label = all,
         int owner = user)
      - marks the specified personal_messages read.
      - if label is set, only marks messages with that label.
      - if owner is set, marks messages owned by that member id.

   void ManageLabels()
      // !!!

   void ReportMessage()
      - allows the user to report a personal message to an administrator.
      - in the first instance requires that the ID of the message to report
        is passed through $_GET.
      - allows the user to report to either a particular administrator - or
        the whole admin team.
      - will forward on a copy of the original message without allowing the
        reporter to make changes.
      - uses the report_message sub-template.
*/

// This helps organize things...
function MessageMain()
{
   global $txt, $scripturl, $sourcedir, $context, $user_info, $user_settings, $db_prefix, $ID_MEMBER;

   // No guests!
   is_not_guest();

   // You're not supposed to be here at all, if you can't even read PMs.
   isAllowedTo('pm_read');

   // This file contains the basic functions for sending a PM.
   require_once($sourcedir . '/Subs-Post.php');

   if (loadLanguage('PersonalMessage', '', false) === false)
      loadLanguage('InstantMessage');
   if (WIRELESS)
      $context['sub_template'] = WIRELESS_PROTOCOL . '_pm';
   else
   {
      if (loadTemplate('PersonalMessage', false) === false)
         loadTemplate('InstantMessage');
   }

   // Load up the members maximum message capacity.
   if (!$user_info['is_admin'])
   {
      // !!! Why do we do this?  It seems like if they have any limit we should use it.
      $request = db_query("
         SELECT MAX(maxMessages) AS topLimit, MIN(maxMessages) AS bottomLimit
         FROM {$db_prefix}membergroups
         WHERE ID_GROUP IN (" . implode(', ', $user_info['groups']) . ')', __FILE__, __LINE__);
      list ($maxMessage, $minMessage) = mysql_fetch_row($request);
      mysql_free_result($request);

      $context['message_limit'] = $minMessage == 0 ? 0 : $maxMessage;
   }
   else
      $context['message_limit'] = 0;

   // Prepare the context for the capacity bar.
   if (!empty($context['message_limit']))
   {
      $bar = ($user_info['messages'] * 100) / $context['message_limit'];

      $context['limit_bar'] = array(
         'messages' => $user_info['messages'],
         'allowed' => $context['message_limit'],
         'percent' => $bar,
         'bar' => min(100, (int) $bar),
         'text' => sprintf($txt['pm_currently_using'], $user_info['messages'], round($bar, 1)),
      );
   }

   // We should probably cache this information for speed.
   $context['labels'] = $user_settings['messageLabels'] == '' ? array() : explode(',', $user_settings['messageLabels']);
   foreach ($context['labels'] as $k => $v)
      $context['labels'][(int) $k] = array('id' => $k, 'name' => trim($v), 'messages' => 0, 'unread_messages' => 0);
   $context['labels'][-1] = array('id' => -1, 'name' => $txt['pm_msg_label_inbox'], 'messages' => 0, 'unread_messages' => 0);

   // !!! The idea would be to cache this information in the members table, and invlidate it when they are sent messages.
   $result = db_query("
      SELECT labels, is_read, COUNT(*) AS num
      FROM {$db_prefix}pm_recipients
      WHERE ID_MEMBER = $ID_MEMBER
      GROUP BY labels, is_read", __FILE__, __LINE__);
   while ($row = mysql_fetch_assoc($result))
   {
      $this_labels = explode(',', $row['labels']);
      foreach ($this_labels as $this_label)
      {
         $context['labels'][(int) $this_label]['messages'] += $row['num'];
         if (!($row['is_read'] & 1))
            $context['labels'][(int) $this_label]['unread_messages'] += $row['num'];
      }
   }
   mysql_free_result($result);

   // This determines if we have more labels than just the standard inbox.
   $context['currently_using_labels'] = count($context['labels']) > 1 ? 1 : 0;

   // Some stuff for the labels...
   $context['current_label_id'] = isset($_REQUEST['l']) && isset($context['labels'][(int) $_REQUEST['l']]) ? (int) $_REQUEST['l'] : -1;
   $context['current_label'] = &$context['labels'][(int) $context['current_label_id']]['name'];
   $context['folder'] = !isset($_REQUEST['f']) || $_REQUEST['f'] != 'outbox' ? 'inbox' : 'outbox';

   // This is convenient.  Do you know how annoying it is to do this every time?!
   $context['current_label_redirect'] = 'action=pm;f=' . $context['folder'] . (isset($_GET['start']) ? ';start=' . $_GET['start'] : '') . (isset($_REQUEST['l']) ? ';l=' . $_REQUEST['l'] : '');

   // Build the linktree for all the actions...
   $context['linktree'][] = array(
      'url' => $scripturl . '?action=pm',
      'name' => $txt[144]
   );

   $subActions = array(
      'addbuddy' => 'WirelessAddBuddy',
      'manlabels' => 'ManageLabels',
      'outbox' => 'MessageFolder',
      'pmactions' => 'MessageActionsApply',
      'prune' => 'MessagePrune',
      'removeall' => 'MessageKillAllQuery',
      'removeall2' => 'MessageKillAll',
      'report' => 'ReportMessage',
      'search' => 'MessageSearch',
      'search2' => 'MessageSearch2',
      'send' => 'MessagePost',
      'send2' => 'MessagePost2',
   );

   if (!isset($_REQUEST['sa']) || !isset($subActions[$_REQUEST['sa']]))
      MessageFolder();
   else
   {
      messageIndexBar($_REQUEST['sa']);
      $subActions[$_REQUEST['sa']]();
   }
}

// A sidebar to easily access different areas of the section
function messageIndexBar($area)
{
   global $txt, $context, $scripturl, $sc, $modSettings, $settings, $user_info;

   $context['pm_areas'] = array(
      'folders' => array(
         'title' => $txt['pm_messages'],
         'areas' => array(
            'send' => array('link' => '<a href="' . $scripturl . '?action=pm;sa=send">' . $txt[321] . '</a>', 'href' => $scripturl . '?action=pm;sa=send'),
            '' => array(),
            'inbox' => array('link' => '<a href="' . $scripturl . '?action=pm">' . $txt[316] . '</a>', 'href' => $scripturl . '?action=pm'),
            'outbox' => array('link' => '<a href="' . $scripturl . '?action=pm;f=outbox">' . $txt[320] . '</a>', 'href' => $scripturl . '?action=pm;f=outbox'),
         ),
      ),
      'labels' => array(
         'title' => $txt['pm_labels'],
         'areas' => array(),
      ),
      'pref' => array(
         'title' => $txt['pm_preferences'],
         'areas' => array(
            'search' => array('link' => '<a href="' . $scripturl . '?action=pm;sa=search">' . $txt['pm_search_bar_title'] . '</a>', 'href' => $scripturl . '?action=pm;sa=search'),
            'manlabels' => array('link' => '<a href="' . $scripturl . '?action=pm;sa=manlabels">' . $txt['pm_manage_labels'] . '</a>', 'href' => $scripturl . '?action=pm;sa=manlabels'),
            'prune' => array('link' => '<a href="' . $scripturl . '?action=pm;sa=prune">' . $txt['pm_prune'] . '</a>', 'href' => $scripturl . '?action=pm;sa=prune'),
         ),
      ),
   );

   // Handle labels.
   if (empty($context['currently_using_labels']))
      unset($context['pm_areas']['labels']);
   else
   {
      // Note we send labels by id as it will have less problems in the querystring.
      foreach ($context['labels'] as $label)
      {
         if ($label['id'] == -1)
            continue;
         $context['pm_areas']['labels']['areas']['label' . $label['id']] = array(
            'link' => '<a href="' . $scripturl . '?action=pm;l=' . $label['id'] . '">' . $label['name'] . '</a>',
            'href' => $scripturl . '?action=pm;l=' . $label['id'],
            'unread_messages' => &$context['labels'][(int) $label['id']]['unread_messages'],
            'messages' => &$context['labels'][(int) $label['id']]['messages'],
         );
      }
   }

   $context['pm_areas']['folders']['areas']['inbox']['unread_messages'] = &$context['labels'][-1]['unread_messages'];
   $context['pm_areas']['folders']['areas']['inbox']['messages'] = &$context['labels'][-1]['messages'];

   // Do we have a limit on the amount of messages we can keep?
   if (!empty($context['message_limit']))
   {
      $bar = round(($user_info['messages'] * 100) / $context['message_limit'], 1);

      $context['limit_bar'] = array(
         'messages' => $user_info['messages'],
         'allowed' => $context['message_limit'],
         'percent' => $bar,
         'bar' => $bar > 100 ? 100 : (int) $bar,
         'text' => sprintf($txt['pm_currently_using'], $user_info['messages'], $bar)
      );

      // Force it in to somewhere.
      $context['pm_areas']['pref']['areas']['limit_bar'] = array('limit_bar' => true);
   }

   // Where we are now.
   $context['pm_area'] = $area;

   // obExit will know what to do!
   if (!WIRELESS)
      $context['template_layers'][] = 'pm';
}

// A folder, ie. outbox/inbox.
function MessageFolder()
{
   global $txt, $scripturl, $db_prefix, $ID_MEMBER, $modSettings, $context;
   global $messages_request, $user_info, $recipients, $options;

   // Make sure the starting location is valid.
   if (isset($_GET['start']) && $_GET['start'] != 'new')
      $_GET['start'] = (int) $_GET['start'];
   elseif (!isset($_GET['start']) && !empty($options['view_newest_pm_first']))
      $_GET['start'] = 0;
   else
      $_GET['start'] = 'new';

   // Set up some basic theme stuff.
   $context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']);
   $context['from_or_to'] = $context['folder'] != 'outbox' ? 'from' : 'to';
   $context['get_pmessage'] = 'prepareMessageContext';

   $labelQuery = $context['folder'] != 'outbox' ? "
         AND FIND_IN_SET('$context[current_label_id]', pmr.labels)" : '';

   // Set the index bar correct!
   messageIndexBar($context['current_label_id'] == -1 ? $context['folder'] : 'label' . $context['current_label_id']);

   // Sorting the folder.
   $sort_methods = array(
      'date' => 'pm.ID_PM',
      'name' => "IFNULL(mem.realName, '')",
      'subject' => 'pm.subject',
   );

   // They didn't pick one, use the forum default.
   if (!isset($_GET['sort']) || !isset($sort_methods[$_GET['sort']]))
   {
      $context['sort_by'] = 'date';
      $_GET['sort'] = 'pm.ID_PM';
      $descending = false;
   }
   // Otherwise use the defaults: ascending, by date.
   else
   {
      $context['sort_by'] = $_GET['sort'];
      $_GET['sort'] = $sort_methods[$_GET['sort']];
      $descending = isset($_GET['desc']);
   }

   if (!empty($options['view_newest_pm_first']))
      $descending = !$descending;

   $context['sort_direction'] = $descending ? 'down' : 'up';

   // Why would you want access to your outbox if you're not allowed to send anything?
   if ($context['folder'] == 'outbox')
      isAllowedTo('pm_send');

   // Set the text to resemble the current folder.
   $pmbox = $context['folder'] != 'outbox' ? $txt[316] : $txt[320];
   $txt[412] = str_replace('PMBOX', $pmbox, $txt[412]);

   // Now, build the link tree!
   $context['linktree'][] = array(
      'url' => $scripturl . '?action=pm;f=' . $context['folder'],
      'name' => $pmbox
   );

   // Build it further for a label.
   if ($context['current_label_id'] != -1)
      $context['linktree'][] = array(
         'url' => $scripturl . '?action=pm;f=' . $context['folder'] . ';l=' . $context['current_label_id'],
         'name' => $txt['pm_current_label'] . ': ' . $context['current_label']
      );

   // Mark all messages as read if in the inbox.
   if ($context['folder'] != 'outbox' && !empty($context['labels'][(int) $context['current_label_id']]['unread_messages']))
      markMessages(null, $context['current_label_id']);

   // Figure out how many messages there are.
   if ($context['folder'] == 'outbox')
      $request = db_query("
         SELECT COUNT(*)
         FROM {$db_prefix}personal_messages
         WHERE ID_MEMBER_FROM = $ID_MEMBER
            AND deletedBySender = 0", __FILE__, __LINE__);
   else
      $request = db_query("
         SELECT COUNT(*)
         FROM {$db_prefix}pm_recipients AS pmr
         WHERE pmr.ID_MEMBER = $ID_MEMBER
            AND pmr.deleted = 0$labelQuery", __FILE__, __LINE__);
   list ($max_messages) = mysql_fetch_row($request);
   mysql_free_result($request);

   // Only show the button if there are messages to delete.
   $context['show_delete'] = $max_messages > 0;

   // Start on the last page.
   if (!is_numeric($_GET['start']) || $_GET['start'] >= $max_messages)
      $_GET['start'] = ($max_messages - 1) - (($max_messages - 1) % $modSettings['defaultMaxMessages']);
   elseif ($_GET['start'] < 0)
      $_GET['start'] = 0;

   // ... but wait - what if we want to start from a specific message?
   if (isset($_GET['pmid']))
   {
      $_GET['pmid'] = (int) $_GET['pmid'];

      // With only one page of PM's we're gonna want page 1.
      if ($max_messages <= $modSettings['defaultMaxMessages'])
         $_GET['start'] = 0;
      else
      {
         if ($context['folder'] == 'outbox')
            $request = db_query("
               SELECT COUNT(*)
               FROM {$db_prefix}personal_messages
               WHERE ID_MEMBER_FROM = $ID_MEMBER
                  AND deletedBySender = 0
                  AND ID_PM " . ($descending ? '>' : '<') . " $_GET[pmid]", __FILE__, __LINE__);
         else
            $request = db_query("
               SELECT COUNT(*)
               FROM {$db_prefix}pm_recipients AS pmr
               WHERE pmr.ID_MEMBER = $ID_MEMBER
                  AND pmr.deleted = 0$labelQuery
                  AND ID_PM " . ($descending ? '>' : '<') . " $_GET[pmid]", __FILE__, __LINE__);

         list ($_GET['start']) = mysql_fetch_row($request);
         mysql_free_result($request);

         // To stop the page index's being abnormal, start the page on the page the message would normally be located on...
         $_GET['start'] = $modSettings['defaultMaxMessages'] * (int) ($_GET['start'] / $modSettings['defaultMaxMessages']);
      }
   }

   // Set up the page index.
   $context['page_index'] = constructPageIndex($scripturl . '?action=pm;f=' . $context['folder'] . (isset($_REQUEST['l']) ? ';l=' . (int) $_REQUEST['l'] : '') . ';sort=' . $context['sort_by'] . (isset($_GET['desc']) ? ';desc' : ''), $_GET['start'], $max_messages, $modSettings['defaultMaxMessages']);
   $context['start'] = $_GET['start'];

   // Determine the navigation context (especially useful for the wireless template).
   $context['links'] = array(
      'first' => $_GET['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?action=pm;start=0' : '',
      'prev' => $_GET['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?action=pm;start=' . ($_GET['start'] - $modSettings['defaultMaxMessages']) : '',
      'next' => $_GET['start'] + $modSettings['defaultMaxMessages'] < $max_messages ? $scripturl . '?action=pm;start=' . ($_GET['start'] + $modSettings['defaultMaxMessages']) : '',
      'last' => $_GET['start'] + $modSettings['defaultMaxMessages'] < $max_messages ? $scripturl . '?action=pm;start=' . (floor(($max_messages - 1) / $modSettings['defaultMaxMessages']) * $modSettings['defaultMaxMessages']) : '',
      'up' => $scripturl,
   );
   $context['page_info'] = array(
      'current_page' => $_GET['start'] / $modSettings['defaultMaxMessages'] + 1,
      'num_pages' => floor(($max_messages - 1) / $modSettings['defaultMaxMessages']) + 1
   );

   // Load the messages up...
   // !!!SLOW This query uses a filesort. (inbox only.)
   $request = db_query("
      SELECT pm.ID_PM, pm.ID_MEMBER_FROM
      FROM ({$db_prefix}personal_messages AS pm" . ($context['folder'] == 'outbox' ? ')' . ($context['sort_by'] == 'name' ? "
         LEFT JOIN {$db_prefix}pm_recipients AS pmr ON (pmr.ID_PM = pm.ID_PM)" : '') : ", {$db_prefix}pm_recipients AS pmr)") . ($context['sort_by'] == 'name' ? ("
         LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = " . ($context['folder'] == 'outbox' ? 'pmr.ID_MEMBER' : 'pm.ID_MEMBER_FROM') . ")") : '') . "
      WHERE " . ($context['folder'] == 'outbox' ? "pm.ID_MEMBER_FROM = $ID_MEMBER
         AND pm.deletedBySender = 0" : "pmr.ID_PM = pm.ID_PM
         AND pmr.ID_MEMBER = $ID_MEMBER
         AND pmr.deleted = 0$labelQuery") . (empty($_GET['pmsg']) ? '' : "
         AND pm.ID_PM = " . (int) $_GET['pmsg']) . "
      ORDER BY " . ($_GET['sort'] == 'pm.ID_PM' && $context['folder'] != 'outbox' ? 'pmr.ID_PM' : $_GET['sort']) . ($descending ? ' DESC' : ' ASC') . (empty($_GET['pmsg']) ? "
      LIMIT $_GET[start], $modSettings[defaultMaxMessages]" : ''), __FILE__, __LINE__);

   // Load the ID_PMs and ID_MEMBERs and initialize recipients.
   $pms = array();
   $posters = $context['folder'] == 'outbox' ? array($ID_MEMBER) : array();
   $recipients = array();
   while ($row = mysql_fetch_assoc($request))
   {
      if (!isset($recipients[$row['ID_PM']]))
      {
         $pms[] = $row['ID_PM'];
         if (!empty($row['ID_MEMBER_FROM']) && $context['folder'] != 'outbox')
            $posters[] = $row['ID_MEMBER_FROM'];
         $recipients[$row['ID_PM']] = array(
            'to' => array(),
            'bcc' => array()
         );
      }
   }
   mysql_free_result($request);

   if (!empty($pms))
   {
      // Get recipients (don't include bcc-recipients for your inbox, you're not supposed to know :P).
      $request = db_query("
         SELECT pmr.ID_PM, mem_to.ID_MEMBER AS ID_MEMBER_TO, mem_to.realName AS toName, pmr.bcc, pmr.labels, pmr.is_read
         FROM {$db_prefix}pm_recipients AS pmr
            LEFT JOIN {$db_prefix}members AS mem_to ON (mem_to.ID_MEMBER = pmr.ID_MEMBER)
         WHERE pmr.ID_PM IN (" . implode(', ', $pms) . ")", __FILE__, __LINE__);
      $context['message_labels'] = array();
      $context['message_replied'] = array();
      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']);
            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']);
            }
         }
      }
      mysql_free_result($request);

      // Load any users....
      $posters = array_unique($posters);
      if (!empty($posters))
         loadMemberData($posters);

      // Execute the query!
      $messages_request = db_query("
         SELECT pm.ID_PM, pm.subject, pm.ID_MEMBER_FROM, pm.body, pm.msgtime, pm.fromName
         FROM {$db_prefix}personal_messages AS pm" . ($context['folder'] == 'outbox' ? "
            LEFT JOIN {$db_prefix}pm_recipients AS pmr ON (pmr.ID_PM = pm.ID_PM)" : '') . ($context['sort_by'] == 'name' ? "
            LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = " . ($context['folder'] == 'outbox' ? 'pmr.ID_MEMBER' : 'pm.ID_MEMBER_FROM') . ")" : '') . "
         WHERE pm.ID_PM IN (" . implode(',', $pms) . ")" . ($context['folder'] == 'outbox' ? "
         GROUP BY pm.ID_PM" : '') . "
         ORDER BY $_GET[sort] " . ($descending ? ' DESC' : ' ASC') . "
         LIMIT " . count($pms), __FILE__, __LINE__);
   }
   else
      $messages_request = false;

   $context['can_send_pm'] = allowedTo('pm_send');
   if (!WIRELESS)
      $context['sub_template'] = 'folder';
   $context['page_title'] = $txt[143];
}

// Get a personal message for the theme.  (used to save memory.)
function prepareMessageContext($reset = false)
{
   global $txt, $scripturl, $modSettings, $context, $messages_request, $memberContext, $recipients;

   // Count the current message number....
   static $counter = null;
   if ($counter === null || $reset)
      $counter = $context['start'];

   static $temp_pm_selected = null;
   if ($temp_pm_selected === null)
   {
      $temp_pm_selected = isset($_SESSION['pm_selected']) ? $_SESSION['pm_selected'] : array();
      $_SESSION['pm_selected'] = array();
   }

   // Bail if it's false, ie. no messages.
   if ($messages_request == false)
      return false;

   // Reset the data?
   if ($reset == true)
      return @mysql_data_seek($messages_request, 0);

   // Get the next one... bail if anything goes wrong.
   $message = mysql_fetch_assoc($messages_request);
   if (!$message)
      return(false);

   // Use '(no subject)' if none was specified.
   $message['subject'] = $message['subject'] == '' ? $txt[24] : $message['subject'];

   // Load the message's information - if it's not there, load the guest information.
   if (!loadMemberContext($message['ID_MEMBER_FROM']))
   {
      $memberContext[$message['ID_MEMBER_FROM']]['name'] = $message['fromName'];
      $memberContext[$message['ID_MEMBER_FROM']]['id'] = 0;
      $memberContext[$message['ID_MEMBER_FROM']]['group'] = $txt[28];
      $memberContext[$message['ID_MEMBER_FROM']]['link'] = $message['fromName'];
      $memberContext[$message['ID_MEMBER_FROM']]['email'] = '';
      $memberContext[$message['ID_MEMBER_FROM']]['hide_email'] = true;
      $memberContext[$message['ID_MEMBER_FROM']]['is_guest'] = true;
   }

   // Censor all the important text...
   censorText($message['body']);
   censorText($message['subject']);

   // Run UBBC interpreter on the message.
   $message['body'] = parse_bbc($message['body'], true, 'pm' . $message['ID_PM']);

   // Send the array.
   $output = array(
      'alternate' => $counter % 2,
      'id' => $message['ID_PM'],
      'member' => &$memberContext[$message['ID_MEMBER_FROM']],
      'subject' => $message['subject'],
      'time' => timeformat($message['msgtime']),
      'timestamp' => forum_time(true, $message['msgtime']),
      'counter' => $counter,
      'body' => $message['body'],
      'recipients' => &$recipients[$message['ID_PM']],
      'number_recipients' => count($recipients[$message['ID_PM']]['to']),
      'labels' => &$context['message_labels'][$message['ID_PM']],
      'fully_labeled' => count($context['message_labels'][$message['ID_PM']]) == count($context['labels']),
      'is_replied_to' => &$context['message_replied'][$message['ID_PM']],
      'is_selected' => !empty($temp_pm_selected) && in_array($message['ID_PM'], $temp_pm_selected),
   );

   $counter++;

   return $output;
}

function MessageSearch()
{
   global $context, $txt, $scripturl, $modSettings;

   if (isset($_REQUEST['params']))
   {
      $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))));
      $context['search_params'] = array();
      foreach ($temp_params as $i => $data)
      {
         @list ($k, $v) = explode('|\'|', $data);
         $context['search_params'][$k] = stripslashes($v);
      }
   }
   if (isset($_REQUEST['search']))
      $context['search_params']['search'] = stripslashes(un_htmlspecialchars($_REQUEST['search']));

   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(stripslashes($context['search_params']['userspec']));

   if (!empty($context['search_params']['searchtype']))
      $context['search_params']['searchtype'] = 2;

   if (!empty($context['search_params']['minage']))
      $context['search_params']['minage'] = (int) $context['search_params']['minage'];

   if (!empty($context['search_params']['maxage']))
      $context['search_params']['maxage'] = (int) $context['search_params']['maxage'];

   $context['search_params']['subject_only'] = !empty($context['search_params']['subject_only']);
   $context['search_params']['show_complete'] = !empty($context['search_params']['show_complete']);

   // Create the array of labels to be searched.
   $context['search_labels'] = array();
   $searchedLabels = isset($context['search_params']['labels']) && $context['search_params']['labels'] != '' ? explode(',', $context['search_params']['labels']) : array();
   foreach ($context['labels'] as $label)
   {
      $context['search_labels'][] = array(
         'id' => $label['id'],
         'name' => $label['name'],
         'checked' => !empty($searchedLabels) ? in_array($label['id'], $searchedLabels) : true,
      );
   }

   // Are all the labels checked?
   $context['check_all'] = empty($searchedLabels) || count($context['search_labels']) == count($searchedLabels);

   // Load the error text strings if there were errors in the search.
   if (!empty($context['search_errors']))
   {
      loadLanguage('Errors');
      $context['search_errors']['messages'] = array();
      foreach ($context['search_errors'] as $search_error => $dummy)
      {
         if ($search_error == 'messages')
            continue;

         $context['search_errors']['messages'][] = $txt['error_' . $search_error];
      }
   }

   $context['simple_search'] = isset($context['search_params']['advanced']) ? empty($context['search_params']['advanced']) : !empty($modSettings['simpleSearch']) && !isset($_REQUEST['advanced']);
   $context['page_title'] = $txt['pm_search_title'];
   $context['sub_template'] = 'search';
   $context['linktree'][] = array(
      'url' => $scripturl . '?action=pm;sa=search',
      'name' => $txt['pm_search_bar_title'],
   );
}

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('&quot;' => '"'));
      $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("
         SELECT ID_MEMBER
         FROM {$db_prefix}members
         WHERE 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;
      // Otherwise prepare the query!
      elseif (count($_REQUEST['searchlabel']) != count($context['labels']))
         $labelQuery = "
         AND (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("
      SELECT COUNT(*)
      FROM ({$db_prefix}pm_recipients AS pmr, {$db_prefix}personal_messages AS pm)
      WHERE pm.ID_PM = pmr.ID_PM" . ($context['folder'] == 'inbox' ? "
         AND pmr.ID_MEMBER = $ID_MEMBER
         AND pmr.deleted = 0" : "
         AND pm.ID_MEMBER_FROM = $ID_MEMBER
         AND pm.deletedBySender = 0") . "
         $userQuery$labelQuery
         AND ($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("
      SELECT pm.ID_PM, pm.ID_MEMBER_FROM
      FROM ({$db_prefix}pm_recipients AS pmr, {$db_prefix}personal_messages AS pm)
      WHERE pm.ID_PM = pmr.ID_PM" . ($context['folder'] == 'inbox' ? "
         AND pmr.ID_MEMBER = $ID_MEMBER
         AND pmr.deleted = 0" : "
         AND pm.ID_MEMBER_FROM = $ID_MEMBER
         AND pm.deletedBySender = 0") . "
         $userQuery$labelQuery
         AND ($searchQuery)
      ORDER BY $search_params[sort] $search_params[sort_dir]
      LIMIT $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("
         SELECT
            pmr.ID_PM, mem_to.ID_MEMBER AS ID_MEMBER_TO, mem_to.realName AS toName,
            pmr.bcc, pmr.labels, pmr.is_read
         FROM {$db_prefix}pm_recipients AS pmr
            LEFT JOIN {$db_prefix}members AS mem_to ON (mem_to.ID_MEMBER = pmr.ID_MEMBER)
         WHERE 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("
         SELECT pm.ID_PM, pm.subject, pm.ID_MEMBER_FROM, pm.body, pm.msgtime, pm.fromName
         FROM {$db_prefix}personal_messages AS pm
         WHERE pm.ID_PM IN (" . implode(',', $foundMessages) . ")
         ORDER BY $search_params[sort] $search_params[sort_dir]
         LIMIT " . 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'],
   );
}

// Send a new message?
function MessagePost()
{
   global $txt, $sourcedir, $db_prefix, $ID_MEMBER, $scripturl, $modSettings;
   global $context, $options, $func, $language, $user_info;

   isAllowedTo('pm_send');

   if (loadLanguage('PersonalMessage', '', false) === false)
      loadLanguage('InstantMessage');
   // Just in case it was loaded from somewhere else.
   if (!WIRELESS)
   {
      if (loadTemplate('PersonalMessage', false) === false)
         loadTemplate('InstantMessage');
      $context['sub_template'] = 'send';
   }

   // Extract out the spam settings - cause it's neat.
   list ($modSettings['max_pm_recipients'], $modSettings['pm_posts_verification'], $modSettings['pm_posts_per_hour']) = explode(',', $modSettings['pm_spam_settings']);

   $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new');

   // Set the title...
   $context['page_title'] = $txt[148];

   $context['reply'] = isset($_REQUEST['pmsg']) || isset($_REQUEST['quote']);

   // Check whether we've gone over the limit of messages we can send per hour.
   if (!empty($modSettings['pm_posts_per_hour']) && !allowedTo(array('admin_forum', 'moderate_forum', 'send_mail')))
   {
      // How many have they sent this last hour?
      $request = db_query("
         SELECT COUNT(pr.ID_PM) AS postCount
         FROM ({$db_prefix}personal_messages AS pm, {$db_prefix}pm_recipients AS pr)
         WHERE pm.ID_MEMBER_FROM = $ID_MEMBER
            AND pm.msgtime > " . (time() - 3600) . "
            AND pr.ID_PM = pm.ID_PM", __FILE__, __LINE__);
      list ($postCount) = mysql_fetch_row($request);
      mysql_free_result($request);

      if (!empty($postCount) && $postCount >= $modSettings['pm_posts_per_hour'])
      {
         // Excempt moderators.
         $request = db_query("
            SELECT ID_MEMBER
            FROM {$db_prefix}moderators
            WHERE ID_MEMBER = $ID_MEMBER", __FILE__, __LINE__);
         if (mysql_num_rows($request) == 0)
            fatal_error(sprintf($txt['pm_too_many_per_hour'], $modSettings['pm_posts_per_hour']));
         mysql_free_result($request);
      }
   }

   // Quoting/Replying to a message?
   if (!empty($_REQUEST['pmsg']))
   {
      $_REQUEST['pmsg'] = (int) $_REQUEST['pmsg'];

      // Get the quoted message (and make sure you're allowed to see this quote!).
      $request = db_query("
         SELECT
            pm.ID_PM, pm.body, pm.subject, pm.msgtime, mem.memberName,
            IFNULL(mem.ID_MEMBER, 0) AS ID_MEMBER, IFNULL(mem.realName, pm.fromName) AS realName
         FROM ({$db_prefix}personal_messages AS pm" . ($context['folder'] == 'outbox' ? '' : ", {$db_prefix}pm_recipients AS pmr") . ")
            LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = pm.ID_MEMBER_FROM)
         WHERE pm.ID_PM = $_REQUEST[pmsg]" . ($context['folder'] == 'outbox' ? "
            AND pm.ID_MEMBER_FROM = $ID_MEMBER" : "
            AND pmr.ID_PM = $_REQUEST[pmsg]
            AND pmr.ID_MEMBER = $ID_MEMBER") . "
         LIMIT 1", __FILE__, __LINE__);
      if (mysql_num_rows($request) == 0)
         fatal_lang_error('pm_not_yours', false);
      $row_quoted = mysql_fetch_assoc($request);
      mysql_free_result($request);

      // Censor the message.
      censorText($row_quoted['subject']);
      censorText($row_quoted['body']);

      // Add 'Re: ' to it...

Offline Nicole

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: Modification allowing Admins to view Private Messages
« Reply #5 on: June 30, 2013, 09:05:55 am »
I would be most happy if this was avaiable for SMF 1.1.18, too! I'm keeping my fingers crossed you can make a SMF 1.1.18 compatible version please. Thank you!

 

Related Topics

  Subject / Started by Replies Last post
0 Replies
9194 Views
Last post March 08, 2007, 09:17:12 am
by origin
2 Replies
6907 Views
Last post July 01, 2008, 07:26:28 pm
by rgsknr
28 Replies
17293 Views
Last post January 09, 2012, 01:22:35 pm
by 1stAngel
5 Replies
6939 Views
Last post August 01, 2012, 04:24:33 pm
by SMFHacks
2 Replies
1467 Views
Last post November 26, 2022, 11:27:34 am
by VisiGod

+- Recent Topics

No thumbnails on new uploads by SMFHacks
March 27, 2024, 02:10:41 pm

Display the Contact Page for guests by SMFHacks
March 27, 2024, 10:55:43 am

is it possible to add support for odysee.com by fvlog19
March 21, 2024, 08:47:51 am

Request for admin notification by davejo
March 10, 2024, 01:31:59 am

I need help with torrent upload by Ineedsmfhelp
March 09, 2024, 10:01:13 pm

an idea for new mod (( content type with different display )) by SMFHacks
February 27, 2024, 01:36:27 pm

[Mod] RSS Feed Poster by SMFHacks
February 27, 2024, 11:57:18 am

find duplicate pictures by fvlog19
February 14, 2024, 02:22:40 pm

Error uploading video. by SMFHacks
February 08, 2024, 02:04:16 pm

Gallery icon as last added image by fvlog19
February 01, 2024, 01:04:56 pm

Powered by EzPortal