Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_privmsgs.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 64.94 KiB


 0001  <?php
 0002  /**
 0003  *
 0004  * This file is part of the phpBB Forum Software package.
 0005  *
 0006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 0007  * @license GNU General Public License, version 2 (GPL-2.0)
 0008  *
 0009  * For full copyright and license information, please see
 0010  * the docs/CREDITS.txt file.
 0011  *
 0012  */
 0013   
 0014  /**
 0015  */
 0016  if (!defined('IN_PHPBB'))
 0017  {
 0018      exit;
 0019  }
 0020   
 0021  /*
 0022      Ability to simply add own rules by doing three things:
 0023          1) Add an appropriate constant
 0024          2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required)
 0025          3) Implement the rule logic in the check_rule() function
 0026          4) Add a new language variable to ucp.php
 0027   
 0028          The user is then able to select the new rule. It will be checked against and handled as specified.
 0029          To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified.
 0030  */
 0031   
 0032  define('RULE_IS_LIKE', 1);        // Is Like
 0033  define('RULE_IS_NOT_LIKE', 2);    // Is Not Like
 0034  define('RULE_IS', 3);            // Is
 0035  define('RULE_IS_NOT', 4);        // Is Not
 0036  define('RULE_BEGINS_WITH', 5);    // Begins with
 0037  define('RULE_ENDS_WITH', 6);    // Ends with
 0038  define('RULE_IS_FRIEND', 7);    // Is Friend
 0039  define('RULE_IS_FOE', 8);        // Is Foe
 0040  define('RULE_IS_USER', 9);        // Is User
 0041  define('RULE_IS_GROUP', 10);    // Is In Usergroup
 0042  define('RULE_ANSWERED', 11);    // Answered
 0043  define('RULE_FORWARDED', 12);    // Forwarded
 0044  define('RULE_TO_GROUP', 14);    // Usergroup
 0045  define('RULE_TO_ME', 15);        // Me
 0046   
 0047  define('ACTION_PLACE_INTO_FOLDER', 1);
 0048  define('ACTION_MARK_AS_READ', 2);
 0049  define('ACTION_MARK_AS_IMPORTANT', 3);
 0050  define('ACTION_DELETE_MESSAGE', 4);
 0051   
 0052  define('CHECK_SUBJECT', 1);
 0053  define('CHECK_SENDER', 2);
 0054  define('CHECK_MESSAGE', 3);
 0055  define('CHECK_STATUS', 4);
 0056  define('CHECK_TO', 5);
 0057   
 0058  /**
 0059  * Global private message rules
 0060  * These rules define what to do if a rule is hit
 0061  */
 0062  $global_privmsgs_rules = array(
 0063      CHECK_SUBJECT    => array(
 0064          RULE_IS_LIKE        => array('check0' => 'message_subject'),
 0065          RULE_IS_NOT_LIKE    => array('check0' => 'message_subject'),
 0066          RULE_IS                => array('check0' => 'message_subject'),
 0067          RULE_IS_NOT            => array('check0' => 'message_subject'),
 0068          RULE_BEGINS_WITH    => array('check0' => 'message_subject'),
 0069          RULE_ENDS_WITH        => array('check0' => 'message_subject'),
 0070      ),
 0071   
 0072      CHECK_SENDER    => array(
 0073          RULE_IS_LIKE        => array('check0' => 'username'),
 0074          RULE_IS_NOT_LIKE    => array('check0' => 'username'),
 0075          RULE_IS                => array('check0' => 'username'),
 0076          RULE_IS_NOT            => array('check0' => 'username'),
 0077          RULE_BEGINS_WITH    => array('check0' => 'username'),
 0078          RULE_ENDS_WITH        => array('check0' => 'username'),
 0079          RULE_IS_FRIEND        => array('check0' => 'friend'),
 0080          RULE_IS_FOE            => array('check0' => 'foe'),
 0081          RULE_IS_USER        => array('check0' => 'author_id'),
 0082          RULE_IS_GROUP        => array('check0' => 'author_in_group'),
 0083      ),
 0084   
 0085      CHECK_MESSAGE    => array(
 0086          RULE_IS_LIKE        => array('check0' => 'message_text'),
 0087          RULE_IS_NOT_LIKE    => array('check0' => 'message_text'),
 0088          RULE_IS                => array('check0' => 'message_text'),
 0089          RULE_IS_NOT            => array('check0' => 'message_text'),
 0090      ),
 0091   
 0092      CHECK_STATUS    => array(
 0093          RULE_ANSWERED        => array('check0' => 'pm_replied'),
 0094          RULE_FORWARDED        => array('check0' => 'pm_forwarded'),
 0095      ),
 0096   
 0097      CHECK_TO        => array(
 0098          RULE_TO_GROUP        => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group'),
 0099          RULE_TO_ME            => array('check0' => 'to', 'check1' => 'bcc'),
 0100      )
 0101  );
 0102   
 0103  /**
 0104  * This is for defining which condition fields to show for which Rule
 0105  */
 0106  $global_rule_conditions = array(
 0107      RULE_IS_LIKE        => 'text',
 0108      RULE_IS_NOT_LIKE    => 'text',
 0109      RULE_IS                => 'text',
 0110      RULE_IS_NOT            => 'text',
 0111      RULE_BEGINS_WITH    => 'text',
 0112      RULE_ENDS_WITH        => 'text',
 0113      RULE_IS_USER        => 'user',
 0114      RULE_IS_GROUP        => 'group'
 0115  );
 0116   
 0117  /**
 0118  * Get all folder
 0119  */
 0120  function get_folder($user_id, $folder_id = false)
 0121  {
 0122      global $db, $user, $template;
 0123      global $phpbb_root_path, $phpEx;
 0124   
 0125      $folder = array();
 0126   
 0127      // Get folder information
 0128      $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread
 0129          FROM ' . PRIVMSGS_TO_TABLE . "
 0130          WHERE user_id = $user_id
 0131              AND folder_id <> " . PRIVMSGS_NO_BOX . '
 0132          GROUP BY folder_id';
 0133      $result = $db->sql_query($sql);
 0134   
 0135      $num_messages = $num_unread = array();
 0136      while ($row = $db->sql_fetchrow($result))
 0137      {
 0138          $num_messages[(int) $row['folder_id']] = $row['num_messages'];
 0139          $num_unread[(int) $row['folder_id']] = $row['num_unread'];
 0140      }
 0141      $db->sql_freeresult($result);
 0142   
 0143      // Make sure the default boxes are defined
 0144      $available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX);
 0145   
 0146      foreach ($available_folder as $default_folder)
 0147      {
 0148          if (!isset($num_messages[$default_folder]))
 0149          {
 0150              $num_messages[$default_folder] = 0;
 0151          }
 0152   
 0153          if (!isset($num_unread[$default_folder]))
 0154          {
 0155              $num_unread[$default_folder] = 0;
 0156          }
 0157      }
 0158   
 0159      // Adjust unread status for outbox
 0160      $num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX];
 0161   
 0162      $folder[PRIVMSGS_INBOX] = array(
 0163          'folder_name'        => $user->lang['PM_INBOX'],
 0164          'num_messages'        => $num_messages[PRIVMSGS_INBOX],
 0165          'unread_messages'    => $num_unread[PRIVMSGS_INBOX]
 0166      );
 0167   
 0168      // Custom Folder
 0169      $sql = 'SELECT folder_id, folder_name, pm_count
 0170          FROM ' . PRIVMSGS_FOLDER_TABLE . "
 0171              WHERE user_id = $user_id";
 0172      $result = $db->sql_query($sql);
 0173   
 0174      while ($row = $db->sql_fetchrow($result))
 0175      {
 0176          $folder[$row['folder_id']] = array(
 0177              'folder_name'        => $row['folder_name'],
 0178              'num_messages'        => $row['pm_count'],
 0179              'unread_messages'    => ((isset($num_unread[$row['folder_id']])) ? $num_unread[$row['folder_id']] : 0)
 0180          );
 0181      }
 0182      $db->sql_freeresult($result);
 0183   
 0184      $folder[PRIVMSGS_OUTBOX] = array(
 0185          'folder_name'        => $user->lang['PM_OUTBOX'],
 0186          'num_messages'        => $num_messages[PRIVMSGS_OUTBOX],
 0187          'unread_messages'    => $num_unread[PRIVMSGS_OUTBOX]
 0188      );
 0189   
 0190      $folder[PRIVMSGS_SENTBOX] = array(
 0191          'folder_name'        => $user->lang['PM_SENTBOX'],
 0192          'num_messages'        => $num_messages[PRIVMSGS_SENTBOX],
 0193          'unread_messages'    => $num_unread[PRIVMSGS_SENTBOX]
 0194      );
 0195   
 0196      // Define Folder Array for template designers (and for making custom folders usable by the template too)
 0197      foreach ($folder as $f_id => $folder_ary)
 0198      {
 0199          $folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox');
 0200   
 0201          $template->assign_block_vars('folder', array(
 0202              'FOLDER_ID'            => $f_id,
 0203              'FOLDER_NAME'        => $folder_ary['folder_name'],
 0204              'NUM_MESSAGES'        => $folder_ary['num_messages'],
 0205              'UNREAD_MESSAGES'    => $folder_ary['unread_messages'],
 0206   
 0207              'U_FOLDER'            => ($f_id > 0) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $f_id) : append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $folder_id_name),
 0208   
 0209              'S_CUR_FOLDER'        => ($f_id === $folder_id) ? true : false,
 0210              'S_UNREAD_MESSAGES'    => ($folder_ary['unread_messages']) ? true : false,
 0211              'S_CUSTOM_FOLDER'    => ($f_id > 0) ? true : false)
 0212          );
 0213      }
 0214   
 0215      if ($folder_id !== false && $folder_id !== PRIVMSGS_HOLD_BOX && !isset($folder[$folder_id]))
 0216      {
 0217          trigger_error('UNKNOWN_FOLDER');
 0218      }
 0219   
 0220      return $folder;
 0221  }
 0222   
 0223  /**
 0224  * Delete Messages From Sentbox
 0225  * we are doing this here because this saves us a bunch of checks and queries
 0226  */
 0227  function clean_sentbox($num_sentbox_messages)
 0228  {
 0229      global $db, $user;
 0230   
 0231      // Check Message Limit
 0232      if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit'])
 0233      {
 0234          // Delete old messages
 0235          $sql = 'SELECT t.msg_id
 0236              FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
 0237              WHERE t.msg_id = p.msg_id
 0238                  AND t.user_id = ' . $user->data['user_id'] . '
 0239                  AND t.folder_id = ' . PRIVMSGS_SENTBOX . '
 0240              ORDER BY p.message_time ASC';
 0241          $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit']));
 0242   
 0243          $delete_ids = array();
 0244          while ($row = $db->sql_fetchrow($result))
 0245          {
 0246              $delete_ids[] = $row['msg_id'];
 0247          }
 0248          $db->sql_freeresult($result);
 0249          delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX);
 0250      }
 0251  }
 0252   
 0253  /**
 0254  * Check Rule against Message Information
 0255  */
 0256  function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
 0257  {
 0258      if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
 0259      {
 0260          return false;
 0261      }
 0262   
 0263      $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']];
 0264   
 0265      $result = false;
 0266   
 0267      $check0 = $message_row[$check_ary['check0']];
 0268   
 0269      switch ($rule_row['rule_connection'])
 0270      {
 0271          case RULE_IS_LIKE:
 0272              $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
 0273          break;
 0274   
 0275          case RULE_IS_NOT_LIKE:
 0276              $result = !preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
 0277          break;
 0278   
 0279          case RULE_IS:
 0280              $result = ($check0 == $rule_row['rule_string']);
 0281          break;
 0282   
 0283          case RULE_IS_NOT:
 0284              $result = ($check0 != $rule_row['rule_string']);
 0285          break;
 0286   
 0287          case RULE_BEGINS_WITH:
 0288              $result = preg_match("/^" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
 0289          break;
 0290   
 0291          case RULE_ENDS_WITH:
 0292              $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '$/i', $check0);
 0293          break;
 0294   
 0295          case RULE_IS_FRIEND:
 0296          case RULE_IS_FOE:
 0297          case RULE_ANSWERED:
 0298          case RULE_FORWARDED:
 0299              $result = ($check0 == 1);
 0300          break;
 0301   
 0302          case RULE_IS_USER:
 0303              $result = ($check0 == $rule_row['rule_user_id']);
 0304          break;
 0305   
 0306          case RULE_IS_GROUP:
 0307              $result = in_array($rule_row['rule_group_id'], $check0);
 0308          break;
 0309   
 0310          case RULE_TO_GROUP:
 0311              $result = (in_array('g_' . $message_row[$check_ary['check2']], $check0) || in_array('g_' . $message_row[$check_ary['check2']], $message_row[$check_ary['check1']]));
 0312          break;
 0313   
 0314          case RULE_TO_ME:
 0315              $result = (in_array('u_' . $user_id, $check0) || in_array('u_' . $user_id, $message_row[$check_ary['check1']]));
 0316          break;
 0317      }
 0318   
 0319      if (!$result)
 0320      {
 0321          return false;
 0322      }
 0323   
 0324      switch ($rule_row['rule_action'])
 0325      {
 0326          case ACTION_PLACE_INTO_FOLDER:
 0327              return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']);
 0328          break;
 0329   
 0330          case ACTION_MARK_AS_READ:
 0331          case ACTION_MARK_AS_IMPORTANT:
 0332              return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
 0333          break;
 0334   
 0335          case ACTION_DELETE_MESSAGE:
 0336              global $db;
 0337   
 0338              // Check for admins/mods - users are not allowed to remove those messages...
 0339              // We do the check here to make sure the data we use is consistent
 0340              $sql = 'SELECT user_id, user_type, user_permissions
 0341                  FROM ' . USERS_TABLE . '
 0342                  WHERE user_id = ' . (int) $message_row['author_id'];
 0343              $result = $db->sql_query($sql);
 0344              $userdata = $db->sql_fetchrow($result);
 0345              $db->sql_freeresult($result);
 0346   
 0347              $auth2 = new \phpbb\auth\auth();
 0348              $auth2->acl($userdata);
 0349   
 0350              if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_'))
 0351              {
 0352                  return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
 0353              }
 0354   
 0355              return false;
 0356          break;
 0357   
 0358          default:
 0359              return false;
 0360      }
 0361   
 0362      return false;
 0363  }
 0364   
 0365  /**
 0366  * Update user PM count
 0367  */
 0368  function update_pm_counts()
 0369  {
 0370      global $user, $db;
 0371   
 0372      // Update unread count
 0373      $sql = 'SELECT COUNT(msg_id) as num_messages
 0374          FROM ' . PRIVMSGS_TO_TABLE . '
 0375          WHERE pm_unread = 1
 0376              AND folder_id <> ' . PRIVMSGS_OUTBOX . '
 0377              AND user_id = ' . $user->data['user_id'];
 0378      $result = $db->sql_query($sql);
 0379      $user->data['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages');
 0380      $db->sql_freeresult($result);
 0381   
 0382      // Update new pm count
 0383      $sql = 'SELECT COUNT(msg_id) as num_messages
 0384          FROM ' . PRIVMSGS_TO_TABLE . '
 0385          WHERE pm_new = 1
 0386              AND folder_id IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
 0387              AND user_id = ' . $user->data['user_id'];
 0388      $result = $db->sql_query($sql);
 0389      $user->data['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages');
 0390      $db->sql_freeresult($result);
 0391   
 0392      $db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
 0393          'user_unread_privmsg'    => (int) $user->data['user_unread_privmsg'],
 0394          'user_new_privmsg'        => (int) $user->data['user_new_privmsg'],
 0395      )) . ' WHERE user_id = ' . $user->data['user_id']);
 0396   
 0397      // Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag.
 0398      if (!$user->data['user_new_privmsg'])
 0399      {
 0400          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 0401              SET pm_new = 0
 0402              WHERE pm_new = 1
 0403                  AND folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
 0404                  AND user_id = ' . $user->data['user_id'];
 0405          $db->sql_query($sql);
 0406      }
 0407  }
 0408   
 0409  /**
 0410  * Place new messages into appropriate folder
 0411  */
 0412  function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
 0413  {
 0414      global $db, $user, $config;
 0415   
 0416      if (!$user->data['user_new_privmsg'])
 0417      {
 0418          return array('not_moved' => 0, 'removed' => 0);
 0419      }
 0420   
 0421      $user_message_rules = (int) $user->data['user_message_rules'];
 0422      $user_id = (int) $user->data['user_id'];
 0423   
 0424      $action_ary = $move_into_folder = array();
 0425      $num_removed = 0;
 0426   
 0427      // Newly processing on-hold messages
 0428      if ($release)
 0429      {
 0430          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 0431              SET folder_id = ' . PRIVMSGS_NO_BOX . '
 0432              WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . "
 0433                  AND user_id = $user_id";
 0434          $db->sql_query($sql);
 0435      }
 0436   
 0437      // Get those messages not yet placed into any box
 0438      $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
 0439          FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u
 0440          WHERE t.user_id = $user_id
 0441              AND p.author_id = u.user_id
 0442              AND t.folder_id = " . PRIVMSGS_NO_BOX . '
 0443              AND t.msg_id = p.msg_id';
 0444   
 0445      // Just place into the appropriate arrays if no rules need to be checked
 0446      if (!$user_message_rules)
 0447      {
 0448          $result = $db->sql_query($retrieve_sql);
 0449   
 0450          while ($row = $db->sql_fetchrow($result))
 0451          {
 0452              $action_ary[$row['msg_id']][] = array('action' => false);
 0453          }
 0454          $db->sql_freeresult($result);
 0455      }
 0456      else
 0457      {
 0458          $user_rules = $zebra = $check_rows = array();
 0459          $user_ids = $memberships = array();
 0460   
 0461          // First of all, grab all rules and retrieve friends/foes
 0462          $sql = 'SELECT *
 0463              FROM ' . PRIVMSGS_RULES_TABLE . "
 0464              WHERE user_id = $user_id";
 0465          $result = $db->sql_query($sql);
 0466          $user_rules = $db->sql_fetchrowset($result);
 0467          $db->sql_freeresult($result);
 0468   
 0469          if (sizeof($user_rules))
 0470          {
 0471              $sql = 'SELECT zebra_id, friend, foe
 0472                  FROM ' . ZEBRA_TABLE . "
 0473                  WHERE user_id = $user_id";
 0474              $result = $db->sql_query($sql);
 0475   
 0476              while ($row = $db->sql_fetchrow($result))
 0477              {
 0478                  $zebra[$row['zebra_id']] = $row;
 0479              }
 0480              $db->sql_freeresult($result);
 0481          }
 0482   
 0483          // Now build a bare-bone check_row array
 0484          $result = $db->sql_query($retrieve_sql);
 0485   
 0486          while ($row = $db->sql_fetchrow($result))
 0487          {
 0488              $check_rows[] = array_merge($row, array(
 0489                  'to'                => explode(':', $row['to_address']),
 0490                  'bcc'                => explode(':', $row['bcc_address']),
 0491                  'friend'            => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0,
 0492                  'foe'                => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0,
 0493                  'user_in_group'        => array($user->data['group_id']),
 0494                  'author_in_group'    => array())
 0495              );
 0496   
 0497              $user_ids[] = $row['user_id'];
 0498          }
 0499          $db->sql_freeresult($result);
 0500   
 0501          // Retrieve user memberships
 0502          if (sizeof($user_ids))
 0503          {
 0504              $sql = 'SELECT *
 0505                  FROM ' . USER_GROUP_TABLE . '
 0506                  WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
 0507                      AND user_pending = 0';
 0508              $result = $db->sql_query($sql);
 0509   
 0510              while ($row = $db->sql_fetchrow($result))
 0511              {
 0512                  $memberships[$row['user_id']][] = $row['group_id'];
 0513              }
 0514              $db->sql_freeresult($result);
 0515          }
 0516   
 0517          // Now place into the appropriate folder
 0518          foreach ($check_rows as $row)
 0519          {
 0520              // Add membership if set
 0521              if (isset($memberships[$row['author_id']]))
 0522              {
 0523                  $row['author_in_group'] = $memberships[$row['user_id']];
 0524              }
 0525   
 0526              // Check Rule - this should be very quick since we have all information we need
 0527              $is_match = false;
 0528              foreach ($user_rules as $rule_row)
 0529              {
 0530                  if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false)
 0531                  {
 0532                      $is_match = true;
 0533                      $action_ary[$row['msg_id']][] = $action;
 0534                  }
 0535              }
 0536   
 0537              if (!$is_match)
 0538              {
 0539                  $action_ary[$row['msg_id']][] = array('action' => false);
 0540              }
 0541          }
 0542   
 0543          unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
 0544      }
 0545   
 0546      // We place actions into arrays, to save queries.
 0547      $unread_ids = $delete_ids = $important_ids = array();
 0548   
 0549      foreach ($action_ary as $msg_id => $msg_ary)
 0550      {
 0551          // It is allowed to execute actions more than once, except placing messages into folder
 0552          $folder_action = $message_removed = false;
 0553   
 0554          foreach ($msg_ary as $pos => $rule_ary)
 0555          {
 0556              if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER)
 0557              {
 0558                  continue;
 0559              }
 0560   
 0561              switch ($rule_ary['action'])
 0562              {
 0563                  case ACTION_PLACE_INTO_FOLDER:
 0564                      // Folder actions have precedence, so we will remove any other ones
 0565                      $folder_action = true;
 0566                      $move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id;
 0567                  break;
 0568   
 0569                  case ACTION_MARK_AS_READ:
 0570                      if ($rule_ary['pm_unread'])
 0571                      {
 0572                          $unread_ids[] = $msg_id;
 0573                      }
 0574                  break;
 0575   
 0576                  case ACTION_DELETE_MESSAGE:
 0577                      $delete_ids[] = $msg_id;
 0578                      $message_removed = true;
 0579                  break;
 0580   
 0581                  case ACTION_MARK_AS_IMPORTANT:
 0582                      if (!$rule_ary['pm_marked'])
 0583                      {
 0584                          $important_ids[] = $msg_id;
 0585                      }
 0586                  break;
 0587              }
 0588          }
 0589   
 0590          // We place this here because it could happen that the messages are doubled if a rule marks a message and then moves it into a specific
 0591          // folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder.
 0592          if (!$folder_action && !$message_removed)
 0593          {
 0594              $move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
 0595          }
 0596      }
 0597   
 0598      // Do not change the order of processing
 0599      // The number of queries needed to be executed here highly depends on the defined rules and are
 0600      // only gone through if new messages arrive.
 0601   
 0602      // Delete messages
 0603      if (sizeof($delete_ids))
 0604      {
 0605          $num_removed += sizeof($delete_ids);
 0606          delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX);
 0607      }
 0608   
 0609      // Set messages to Unread
 0610      if (sizeof($unread_ids))
 0611      {
 0612          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 0613              SET pm_unread = 0
 0614              WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "
 0615                  AND user_id = $user_id
 0616                  AND folder_id = " . PRIVMSGS_NO_BOX;
 0617          $db->sql_query($sql);
 0618      }
 0619   
 0620      // mark messages as important
 0621      if (sizeof($important_ids))
 0622      {
 0623          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 0624              SET pm_marked = 1 - pm_marked
 0625              WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
 0626                  AND user_id = $user_id
 0627                  AND " . $db->sql_in_set('msg_id', $important_ids);
 0628          $db->sql_query($sql);
 0629      }
 0630   
 0631      // Move into folder
 0632      $folder = array();
 0633   
 0634      if (sizeof($move_into_folder))
 0635      {
 0636          // Determine Full Folder Action - we need the move to folder id later eventually
 0637          $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
 0638   
 0639          $sql_folder = array_keys($move_into_folder);
 0640          if ($full_folder_action >= 0)
 0641          {
 0642              $sql_folder[] = $full_folder_action;
 0643          }
 0644   
 0645          $sql = 'SELECT folder_id, pm_count
 0646              FROM ' . PRIVMSGS_FOLDER_TABLE . '
 0647              WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "
 0648                  AND user_id = $user_id";
 0649          $result = $db->sql_query($sql);
 0650   
 0651          while ($row = $db->sql_fetchrow($result))
 0652          {
 0653              $folder[(int) $row['folder_id']] = (int) $row['pm_count'];
 0654          }
 0655          $db->sql_freeresult($result);
 0656   
 0657          unset($sql_folder);
 0658   
 0659          if (isset($move_into_folder[PRIVMSGS_INBOX]))
 0660          {
 0661              $sql = 'SELECT COUNT(msg_id) as num_messages
 0662                  FROM ' . PRIVMSGS_TO_TABLE . "
 0663                  WHERE user_id = $user_id
 0664                      AND folder_id = " . PRIVMSGS_INBOX;
 0665              $result = $db->sql_query($sql);
 0666              $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages');
 0667              $db->sql_freeresult($result);
 0668          }
 0669      }
 0670   
 0671      // Here we have ideally only one folder to move into
 0672      foreach ($move_into_folder as $folder_id => $msg_ary)
 0673      {
 0674          $dest_folder = $folder_id;
 0675          $full_folder_action = FULL_FOLDER_NONE;
 0676   
 0677          // Check Message Limit - we calculate with the complete array, most of the time it is one message
 0678          // But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
 0679          if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit'])
 0680          {
 0681              $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
 0682   
 0683              // If destination folder itself is full...
 0684              if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit'])
 0685              {
 0686                  $full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1));
 0687              }
 0688   
 0689              // If Full Folder Action is to move to another folder, we simply adjust the destination folder
 0690              if ($full_folder_action >= 0)
 0691              {
 0692                  $dest_folder = $full_folder_action;
 0693              }
 0694              else if ($full_folder_action == FULL_FOLDER_DELETE)
 0695              {
 0696                  // Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
 0697                  $sql = 'SELECT msg_id
 0698                      FROM ' . PRIVMSGS_TO_TABLE . "
 0699                      WHERE user_id = $user_id
 0700                          AND folder_id = $dest_folder
 0701                      ORDER BY msg_id ASC";
 0702                  $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit']));
 0703   
 0704                  $delete_ids = array();
 0705                  while ($row = $db->sql_fetchrow($result))
 0706                  {
 0707                      $delete_ids[] = $row['msg_id'];
 0708                  }
 0709                  $db->sql_freeresult($result);
 0710   
 0711                  $num_removed += sizeof($delete_ids);
 0712                  delete_pm($user_id, $delete_ids, $dest_folder);
 0713              }
 0714          }
 0715   
 0716          //
 0717          if ($full_folder_action == FULL_FOLDER_HOLD)
 0718          {
 0719              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 0720                  SET folder_id = ' . PRIVMSGS_HOLD_BOX . '
 0721                  WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
 0722                      AND user_id = $user_id
 0723                      AND " . $db->sql_in_set('msg_id', $msg_ary);
 0724              $db->sql_query($sql);
 0725          }
 0726          else
 0727          {
 0728              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
 0729                  SET folder_id = $dest_folder, pm_new = 0
 0730                  WHERE folder_id = " . PRIVMSGS_NO_BOX . "
 0731                      AND user_id = $user_id
 0732                      AND pm_new = 1
 0733                      AND " . $db->sql_in_set('msg_id', $msg_ary);
 0734              $db->sql_query($sql);
 0735   
 0736              if ($dest_folder != PRIVMSGS_INBOX)
 0737              {
 0738                  $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . '
 0739                      SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "
 0740                      WHERE folder_id = $dest_folder
 0741                          AND user_id = $user_id";
 0742                  $db->sql_query($sql);
 0743              }
 0744          }
 0745      }
 0746   
 0747      if (sizeof($action_ary))
 0748      {
 0749          // Move from OUTBOX to SENTBOX
 0750          // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
 0751          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 0752              SET folder_id = ' . PRIVMSGS_SENTBOX . '
 0753              WHERE folder_id = ' . PRIVMSGS_OUTBOX . '
 0754                  AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
 0755          $db->sql_query($sql);
 0756      }
 0757   
 0758      // Update new/unread count
 0759      update_pm_counts();
 0760   
 0761      // Now check how many messages got not moved...
 0762      $sql = 'SELECT COUNT(msg_id) as num_messages
 0763          FROM ' . PRIVMSGS_TO_TABLE . "
 0764          WHERE user_id = $user_id
 0765              AND folder_id = " . PRIVMSGS_HOLD_BOX;
 0766      $result = $db->sql_query($sql);
 0767      $num_not_moved = (int) $db->sql_fetchfield('num_messages');
 0768      $db->sql_freeresult($result);
 0769   
 0770      return array('not_moved' => $num_not_moved, 'removed' => $num_removed);
 0771  }
 0772   
 0773  /**
 0774  * Move PM from one to another folder
 0775  */
 0776  function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id)
 0777  {
 0778      global $db, $user;
 0779      global $phpbb_root_path, $phpEx;
 0780   
 0781      $num_moved = 0;
 0782   
 0783      if (!is_array($move_msg_ids))
 0784      {
 0785          $move_msg_ids = array($move_msg_ids);
 0786      }
 0787   
 0788      if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) &&
 0789          !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder)
 0790      {
 0791          // We have to check the destination folder ;)
 0792          if ($dest_folder != PRIVMSGS_INBOX)
 0793          {
 0794              $sql = 'SELECT folder_id, folder_name, pm_count
 0795                  FROM ' . PRIVMSGS_FOLDER_TABLE . "
 0796                  WHERE folder_id = $dest_folder
 0797                      AND user_id = $user_id";
 0798              $result = $db->sql_query($sql);
 0799              $row = $db->sql_fetchrow($result);
 0800              $db->sql_freeresult($result);
 0801   
 0802              if (!$row)
 0803              {
 0804                  send_status_line(403, 'Forbidden');
 0805                  trigger_error('NOT_AUTHORISED');
 0806              }
 0807   
 0808              if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit)
 0809              {
 0810                  $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />';
 0811                  $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']);
 0812                  trigger_error($message);
 0813              }
 0814          }
 0815          else
 0816          {
 0817              $sql = 'SELECT COUNT(msg_id) as num_messages
 0818                  FROM ' . PRIVMSGS_TO_TABLE . '
 0819                  WHERE folder_id = ' . PRIVMSGS_INBOX . "
 0820                      AND user_id = $user_id";
 0821              $result = $db->sql_query($sql);
 0822              $num_messages = (int) $db->sql_fetchfield('num_messages');
 0823              $db->sql_freeresult($result);
 0824   
 0825              if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit)
 0826              {
 0827                  $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />';
 0828                  $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox') . '">', '</a>', $user->lang['PM_INBOX']);
 0829                  trigger_error($message);
 0830              }
 0831          }
 0832   
 0833          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
 0834              SET folder_id = $dest_folder
 0835              WHERE folder_id = $cur_folder_id
 0836                  AND user_id = $user_id
 0837                  AND " . $db->sql_in_set('msg_id', $move_msg_ids);
 0838          $db->sql_query($sql);
 0839          $num_moved = $db->sql_affectedrows();
 0840   
 0841          // Update pm counts
 0842          if ($num_moved)
 0843          {
 0844              if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)))
 0845              {
 0846                  $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
 0847                      SET pm_count = pm_count - $num_moved
 0848                      WHERE folder_id = $cur_folder_id
 0849                          AND user_id = $user_id";
 0850                  $db->sql_query($sql);
 0851              }
 0852   
 0853              if ($dest_folder != PRIVMSGS_INBOX)
 0854              {
 0855                  $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
 0856                      SET pm_count = pm_count + $num_moved
 0857                      WHERE folder_id = $dest_folder
 0858                          AND user_id = $user_id";
 0859                  $db->sql_query($sql);
 0860              }
 0861          }
 0862      }
 0863      else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)))
 0864      {
 0865          trigger_error('CANNOT_MOVE_SPECIAL');
 0866      }
 0867   
 0868      return $num_moved;
 0869  }
 0870   
 0871  /**
 0872  * Update unread message status
 0873  */
 0874  function update_unread_status($unread, $msg_id, $user_id, $folder_id)
 0875  {
 0876      if (!$unread)
 0877      {
 0878          return;
 0879      }
 0880   
 0881      global $db, $user, $phpbb_container;
 0882   
 0883      /* @var $phpbb_notifications \phpbb\notification\manager */
 0884      $phpbb_notifications = $phpbb_container->get('notification_manager');
 0885   
 0886      $phpbb_notifications->mark_notifications('notification.type.pm', $msg_id, $user_id);
 0887   
 0888      $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
 0889          SET pm_unread = 0
 0890          WHERE msg_id = $msg_id
 0891              AND user_id = $user_id
 0892              AND folder_id = $folder_id
 0893              AND pm_unread = 1";
 0894      $db->sql_query($sql);
 0895   
 0896      // If the message is already marked as read, we just skip the rest to avoid negative PM count
 0897      if (!$db->sql_affectedrows())
 0898      {
 0899          return;
 0900      }
 0901   
 0902      $sql = 'UPDATE ' . USERS_TABLE . "
 0903          SET user_unread_privmsg = user_unread_privmsg - 1
 0904          WHERE user_id = $user_id";
 0905      $db->sql_query($sql);
 0906   
 0907      if ($user->data['user_id'] == $user_id)
 0908      {
 0909          $user->data['user_unread_privmsg']--;
 0910   
 0911          // Try to cope with previous wrong conversions...
 0912          if ($user->data['user_unread_privmsg'] < 0)
 0913          {
 0914              $sql = 'UPDATE ' . USERS_TABLE . "
 0915                  SET user_unread_privmsg = 0
 0916                  WHERE user_id = $user_id";
 0917              $db->sql_query($sql);
 0918   
 0919              $user->data['user_unread_privmsg'] = 0;
 0920          }
 0921      }
 0922  }
 0923   
 0924  function mark_folder_read($user_id, $folder_id)
 0925  {
 0926      global $db;
 0927   
 0928      $sql = 'SELECT msg_id
 0929          FROM ' . PRIVMSGS_TO_TABLE . '
 0930          WHERE folder_id = ' . ((int) $folder_id) . '
 0931              AND user_id = ' . ((int) $user_id) . '
 0932              AND pm_unread = 1';
 0933      $result = $db->sql_query($sql);
 0934   
 0935      while ($row = $db->sql_fetchrow($result))
 0936      {
 0937          update_unread_status(true, $row['msg_id'], $user_id, $folder_id);
 0938      }
 0939      $db->sql_freeresult($result);
 0940  }
 0941   
 0942  /**
 0943  * Handle all actions possible with marked messages
 0944  */
 0945  function handle_mark_actions($user_id, $mark_action)
 0946  {
 0947      global $db, $user, $phpbb_root_path, $phpEx, $request;
 0948   
 0949      $msg_ids        = $request->variable('marked_msg_id', array(0));
 0950      $cur_folder_id    = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX);
 0951   
 0952      if (!sizeof($msg_ids))
 0953      {
 0954          return false;
 0955      }
 0956   
 0957      switch ($mark_action)
 0958      {
 0959          case 'mark_important':
 0960   
 0961              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
 0962                  SET pm_marked = 1 - pm_marked
 0963                  WHERE folder_id = $cur_folder_id
 0964                      AND user_id = $user_id
 0965                      AND " . $db->sql_in_set('msg_id', $msg_ids);
 0966              $db->sql_query($sql);
 0967   
 0968          break;
 0969   
 0970          case 'delete_marked':
 0971   
 0972              global $auth;
 0973   
 0974              if (!$auth->acl_get('u_pm_delete'))
 0975              {
 0976                  send_status_line(403, 'Forbidden');
 0977                  trigger_error('NO_AUTH_DELETE_MESSAGE');
 0978              }
 0979   
 0980              if (confirm_box(true))
 0981              {
 0982                  delete_pm($user_id, $msg_ids, $cur_folder_id);
 0983   
 0984                  $success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED';
 0985                  $redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $cur_folder_id);
 0986   
 0987                  meta_refresh(3, $redirect);
 0988                  trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>'));
 0989              }
 0990              else
 0991              {
 0992                  $s_hidden_fields = array(
 0993                      'cur_folder_id'    => $cur_folder_id,
 0994                      'mark_option'    => 'delete_marked',
 0995                      'submit_mark'    => true,
 0996                      'marked_msg_id'    => $msg_ids
 0997                  );
 0998   
 0999                  confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields));
 1000              }
 1001   
 1002          break;
 1003   
 1004          default:
 1005              return false;
 1006      }
 1007   
 1008      return true;
 1009  }
 1010   
 1011  /**
 1012  * Delete PM(s)
 1013  */
 1014  function delete_pm($user_id, $msg_ids, $folder_id)
 1015  {
 1016      global $db, $user, $phpbb_container, $phpbb_dispatcher;
 1017   
 1018      $user_id    = (int) $user_id;
 1019      $folder_id    = (int) $folder_id;
 1020   
 1021      if (!$user_id)
 1022      {
 1023          return false;
 1024      }
 1025   
 1026      if (!is_array($msg_ids))
 1027      {
 1028          if (!$msg_ids)
 1029          {
 1030              return false;
 1031          }
 1032          $msg_ids = array($msg_ids);
 1033      }
 1034   
 1035      if (!sizeof($msg_ids))
 1036      {
 1037          return false;
 1038      }
 1039   
 1040      /**
 1041      * Get all info for PM(s) before they are deleted
 1042      *
 1043      * @event core.delete_pm_before
 1044      * @var    int    user_id     ID of the user requested the message delete
 1045      * @var    array    msg_ids    array of all messages to be deleted
 1046      * @var    int    folder_id    ID of the user folder where the messages are stored
 1047      * @since 3.1.0-b5
 1048      */
 1049      $vars = array('user_id', 'msg_ids', 'folder_id');
 1050      extract($phpbb_dispatcher->trigger_event('core.delete_pm_before', compact($vars)));
 1051   
 1052      // Get PM Information for later deleting
 1053      $sql = 'SELECT msg_id, pm_unread, pm_new
 1054          FROM ' . PRIVMSGS_TO_TABLE . '
 1055          WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . "
 1056              AND folder_id = $folder_id
 1057              AND user_id = $user_id";
 1058      $result = $db->sql_query($sql);
 1059   
 1060      $delete_rows = array();
 1061      $num_unread = $num_new = $num_deleted = 0;
 1062      while ($row = $db->sql_fetchrow($result))
 1063      {
 1064          $num_unread += (int) $row['pm_unread'];
 1065          $num_new += (int) $row['pm_new'];
 1066   
 1067          $delete_rows[$row['msg_id']] = 1;
 1068      }
 1069      $db->sql_freeresult($result);
 1070      unset($msg_ids);
 1071   
 1072      if (!sizeof($delete_rows))
 1073      {
 1074          return false;
 1075      }
 1076   
 1077      $db->sql_transaction('begin');
 1078   
 1079      // if no one has read the message yet (meaning it is in users outbox)
 1080      // then mark the message as deleted...
 1081      if ($folder_id == PRIVMSGS_OUTBOX)
 1082      {
 1083          // Remove PM from Outbox
 1084          $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
 1085              WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . '
 1086                  AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
 1087          $db->sql_query($sql);
 1088   
 1089          // Update PM Information for safety
 1090          $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = ''
 1091              WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows));
 1092          $db->sql_query($sql);
 1093   
 1094          // Set delete flag for those intended to receive the PM
 1095          // We do not remove the message actually, to retain some basic information (sent time for example)
 1096          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 1097              SET pm_deleted = 1
 1098              WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
 1099          $db->sql_query($sql);
 1100   
 1101          $num_deleted = $db->sql_affectedrows();
 1102      }
 1103      else
 1104      {
 1105          // Delete private message data
 1106          $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
 1107              WHERE user_id = $user_id
 1108                  AND folder_id = $folder_id
 1109                  AND " . $db->sql_in_set('msg_id', array_keys($delete_rows));
 1110          $db->sql_query($sql);
 1111          $num_deleted = $db->sql_affectedrows();
 1112      }
 1113   
 1114      // if folder id is user defined folder then decrease pm_count
 1115      if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX)))
 1116      {
 1117          $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
 1118              SET pm_count = pm_count - $num_deleted
 1119              WHERE folder_id = $folder_id";
 1120          $db->sql_query($sql);
 1121      }
 1122   
 1123      // Update unread and new status field
 1124      if ($num_unread || $num_new)
 1125      {
 1126          $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
 1127   
 1128          if ($num_new)
 1129          {
 1130              $set_sql .= ($set_sql != '') ? ', ' : '';
 1131              $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
 1132          }
 1133   
 1134          $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
 1135   
 1136          $user->data['user_new_privmsg'] -= $num_new;
 1137          $user->data['user_unread_privmsg'] -= $num_unread;
 1138      }
 1139   
 1140      /* @var $phpbb_notifications \phpbb\notification\manager */
 1141      $phpbb_notifications = $phpbb_container->get('notification_manager');
 1142   
 1143      $phpbb_notifications->delete_notifications('notification.type.pm', array_keys($delete_rows));
 1144   
 1145      // Now we have to check which messages we can delete completely
 1146      $sql = 'SELECT msg_id
 1147          FROM ' . PRIVMSGS_TO_TABLE . '
 1148          WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
 1149      $result = $db->sql_query($sql);
 1150   
 1151      while ($row = $db->sql_fetchrow($result))
 1152      {
 1153          unset($delete_rows[$row['msg_id']]);
 1154      }
 1155      $db->sql_freeresult($result);
 1156   
 1157      $delete_ids = array_keys($delete_rows);
 1158   
 1159      if (sizeof($delete_ids))
 1160      {
 1161          // Check if there are any attachments we need to remove
 1162          /** @var \phpbb\attachment\manager $attachment_manager */
 1163          $attachment_manager = $phpbb_container->get('attachment.manager');
 1164          $attachment_manager->delete('message', $delete_ids, false);
 1165          unset($attachment_manager);
 1166   
 1167          $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
 1168              WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
 1169          $db->sql_query($sql);
 1170      }
 1171   
 1172      $db->sql_transaction('commit');
 1173   
 1174      return true;
 1175  }
 1176   
 1177  /**
 1178  * Delete all PM(s) for a given user and delete the ones without references
 1179  *
 1180  * @param    int        $user_id    ID of the user whose private messages we want to delete
 1181  *
 1182  * @return    boolean        False if there were no pms found, true otherwise.
 1183  */
 1184  function phpbb_delete_user_pms($user_id)
 1185  {
 1186      $user_id = (int) $user_id;
 1187   
 1188      if (!$user_id)
 1189      {
 1190          return false;
 1191      }
 1192   
 1193      return phpbb_delete_users_pms(array($user_id));
 1194  }
 1195   
 1196  /**
 1197  * Delete all PM(s) for given users and delete the ones without references
 1198  *
 1199  * @param    array        $user_ids    IDs of the users whose private messages we want to delete
 1200  *
 1201  * @return    boolean        False if there were no pms found, true otherwise.
 1202  */
 1203  function phpbb_delete_users_pms($user_ids)
 1204  {
 1205      global $db, $phpbb_container;
 1206   
 1207      $user_id_sql = $db->sql_in_set('user_id', $user_ids);
 1208      $author_id_sql = $db->sql_in_set('author_id', $user_ids);
 1209   
 1210      // Get PM Information for later deleting
 1211      // The two queries where split, so we can use our indexes
 1212      $undelivered_msg = $delete_ids = array();
 1213   
 1214      // Part 1: get PMs the user received
 1215      $sql = 'SELECT msg_id
 1216          FROM ' . PRIVMSGS_TO_TABLE . '
 1217          WHERE ' . $user_id_sql;
 1218      $result = $db->sql_query($sql);
 1219   
 1220      while ($row = $db->sql_fetchrow($result))
 1221      {
 1222          $msg_id = (int) $row['msg_id'];
 1223          $delete_ids[$msg_id] = $msg_id;
 1224      }
 1225      $db->sql_freeresult($result);
 1226   
 1227      // Part 2: get PMs the users sent, but are yet to be received.
 1228      // We cannot simply delete them. First we have to check
 1229      // whether another user already received and read the message.
 1230      $sql = 'SELECT msg_id
 1231          FROM ' . PRIVMSGS_TO_TABLE . '
 1232          WHERE ' . $author_id_sql . '
 1233              AND folder_id = ' . PRIVMSGS_NO_BOX;
 1234      $result = $db->sql_query($sql);
 1235   
 1236      while ($row = $db->sql_fetchrow($result))
 1237      {
 1238          $msg_id = (int) $row['msg_id'];
 1239          $undelivered_msg[$msg_id] = $msg_id;
 1240      }
 1241      $db->sql_freeresult($result);
 1242   
 1243      if (empty($delete_ids) && empty($undelivered_msg))
 1244      {
 1245          return false;
 1246      }
 1247   
 1248      $db->sql_transaction('begin');
 1249   
 1250      /* @var $phpbb_notifications \phpbb\notification\manager */
 1251      $phpbb_notifications = $phpbb_container->get('notification_manager');
 1252   
 1253      if (!empty($undelivered_msg))
 1254      {
 1255          // A pm is delivered, if for any recipient the message was moved
 1256          // from their NO_BOX to another folder. We do not delete such
 1257          // messages, but only delete them for users, who have not yet
 1258          // received them.
 1259          $sql = 'SELECT msg_id
 1260              FROM ' . PRIVMSGS_TO_TABLE . '
 1261              WHERE ' . $author_id_sql . '
 1262                  AND folder_id <> ' . PRIVMSGS_NO_BOX . '
 1263                  AND folder_id <> ' . PRIVMSGS_OUTBOX . '
 1264                  AND folder_id <> ' . PRIVMSGS_SENTBOX;
 1265          $result = $db->sql_query($sql);
 1266   
 1267          $delivered_msg = array();
 1268          while ($row = $db->sql_fetchrow($result))
 1269          {
 1270              $msg_id = (int) $row['msg_id'];
 1271              $delivered_msg[$msg_id] = $msg_id;
 1272              unset($undelivered_msg[$msg_id]);
 1273          }
 1274          $db->sql_freeresult($result);
 1275   
 1276          $undelivered_user = array();
 1277   
 1278          // Count the messages we delete, so we can correct the user pm data
 1279          $sql = 'SELECT user_id, COUNT(msg_id) as num_undelivered_privmsgs
 1280              FROM ' . PRIVMSGS_TO_TABLE . '
 1281              WHERE ' . $author_id_sql . '
 1282                  AND folder_id = ' . PRIVMSGS_NO_BOX . '
 1283                      AND ' . $db->sql_in_set('msg_id', array_merge($undelivered_msg, $delivered_msg)) . '
 1284              GROUP BY user_id';
 1285          $result = $db->sql_query($sql);
 1286   
 1287          while ($row = $db->sql_fetchrow($result))
 1288          {
 1289              $num_pms = (int) $row['num_undelivered_privmsgs'];
 1290              $undelivered_user[$num_pms][] = (int) $row['user_id'];
 1291   
 1292              if (sizeof($undelivered_user[$num_pms]) > 50)
 1293              {
 1294                  // If there are too many users affected the query might get
 1295                  // too long, so we update the value for the first bunch here.
 1296                  $sql = 'UPDATE ' . USERS_TABLE . '
 1297                      SET user_new_privmsg = user_new_privmsg - ' . $num_pms . ',
 1298                          user_unread_privmsg = user_unread_privmsg - ' . $num_pms . '
 1299                      WHERE ' . $db->sql_in_set('user_id', $undelivered_user[$num_pms]);
 1300                  $db->sql_query($sql);
 1301                  unset($undelivered_user[$num_pms]);
 1302              }
 1303          }
 1304          $db->sql_freeresult($result);
 1305   
 1306          foreach ($undelivered_user as $num_pms => $undelivered_user_set)
 1307          {
 1308              $sql = 'UPDATE ' . USERS_TABLE . '
 1309                  SET user_new_privmsg = user_new_privmsg - ' . $num_pms . ',
 1310                      user_unread_privmsg = user_unread_privmsg - ' . $num_pms . '
 1311                  WHERE ' . $db->sql_in_set('user_id', $undelivered_user_set);
 1312              $db->sql_query($sql);
 1313          }
 1314   
 1315          if (!empty($delivered_msg))
 1316          {
 1317              $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
 1318                  WHERE folder_id = ' . PRIVMSGS_NO_BOX . '
 1319                      AND ' . $db->sql_in_set('msg_id', $delivered_msg);
 1320              $db->sql_query($sql);
 1321   
 1322              $phpbb_notifications->delete_notifications('notification.type.pm', $delivered_msg);
 1323          }
 1324   
 1325          if (!empty($undelivered_msg))
 1326          {
 1327              $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
 1328                  WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg);
 1329              $db->sql_query($sql);
 1330   
 1331              $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
 1332                  WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg);
 1333              $db->sql_query($sql);
 1334   
 1335              $phpbb_notifications->delete_notifications('notification.type.pm', $undelivered_msg);
 1336          }
 1337      }
 1338   
 1339      // Reset the user's pm count to 0
 1340      $sql = 'UPDATE ' . USERS_TABLE . '
 1341          SET user_new_privmsg = 0,
 1342              user_unread_privmsg = 0
 1343          WHERE ' . $user_id_sql;
 1344      $db->sql_query($sql);
 1345   
 1346      // Delete private message data of the user
 1347      $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
 1348          WHERE ' . $user_id_sql;
 1349      $db->sql_query($sql);
 1350   
 1351      if (!empty($delete_ids))
 1352      {
 1353          // Now we have to check which messages we can delete completely
 1354          $sql = 'SELECT msg_id
 1355              FROM ' . PRIVMSGS_TO_TABLE . '
 1356              WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
 1357          $result = $db->sql_query($sql);
 1358   
 1359          while ($row = $db->sql_fetchrow($result))
 1360          {
 1361              unset($delete_ids[$row['msg_id']]);
 1362          }
 1363          $db->sql_freeresult($result);
 1364   
 1365          if (!empty($delete_ids))
 1366          {
 1367              // Check if there are any attachments we need to remove
 1368              /** @var \phpbb\attachment\manager $attachment_manager */
 1369              $attachment_manager = $phpbb_container->get('attachment.manager');
 1370              $attachment_manager->delete('message', $delete_ids, false);
 1371              unset($attachment_manager);
 1372   
 1373              $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
 1374                  WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
 1375              $db->sql_query($sql);
 1376   
 1377              $phpbb_notifications->delete_notifications('notification.type.pm', $delete_ids);
 1378          }
 1379      }
 1380   
 1381      // Set the remaining author id to anonymous
 1382      // This way users are still able to read messages from users being removed
 1383      $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 1384          SET author_id = ' . ANONYMOUS . '
 1385          WHERE ' . $author_id_sql;
 1386      $db->sql_query($sql);
 1387   
 1388      $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
 1389          SET author_id = ' . ANONYMOUS . '
 1390          WHERE ' . $author_id_sql;
 1391      $db->sql_query($sql);
 1392   
 1393      $db->sql_transaction('commit');
 1394   
 1395      return true;
 1396  }
 1397   
 1398  /**
 1399  * Rebuild message header
 1400  */
 1401  function rebuild_header($check_ary)
 1402  {
 1403      $address = array();
 1404   
 1405      foreach ($check_ary as $check_type => $address_field)
 1406      {
 1407          // Split Addresses into users and groups
 1408          preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
 1409   
 1410          $u = $g = array();
 1411          foreach ($match[1] as $id => $type)
 1412          {
 1413              ${$type}[] = (int) $match[2][$id];
 1414          }
 1415   
 1416          $_types = array('u', 'g');
 1417          foreach ($_types as $type)
 1418          {
 1419              if (sizeof(${$type}))
 1420              {
 1421                  foreach (${$type} as $id)
 1422                  {
 1423                      $address[$type][$id] = $check_type;
 1424                  }
 1425              }
 1426          }
 1427      }
 1428   
 1429      return $address;
 1430  }
 1431   
 1432  /**
 1433  * Print out/assign recipient information
 1434  */
 1435  function write_pm_addresses($check_ary, $author_id, $plaintext = false)
 1436  {
 1437      global $db, $user, $template, $phpbb_root_path, $phpEx, $phpbb_container;
 1438   
 1439      /** @var \phpbb\group\helper $group_helper */
 1440      $group_helper = $phpbb_container->get('group_helper');
 1441   
 1442      $addresses = array();
 1443   
 1444      foreach ($check_ary as $check_type => $address_field)
 1445      {
 1446          if (!is_array($address_field))
 1447          {
 1448              // Split Addresses into users and groups
 1449              preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
 1450   
 1451              $u = $g = array();
 1452              foreach ($match[1] as $id => $type)
 1453              {
 1454                  ${$type}[] = (int) $match[2][$id];
 1455              }
 1456          }
 1457          else
 1458          {
 1459              $u = $address_field['u'];
 1460              $g = $address_field['g'];
 1461          }
 1462   
 1463          $address = array();
 1464          if (sizeof($u))
 1465          {
 1466              $sql = 'SELECT user_id, username, user_colour
 1467                  FROM ' . USERS_TABLE . '
 1468                  WHERE ' . $db->sql_in_set('user_id', $u);
 1469              $result = $db->sql_query($sql);
 1470   
 1471              while ($row = $db->sql_fetchrow($result))
 1472              {
 1473                  if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
 1474                  {
 1475                      if ($plaintext)
 1476                      {
 1477                          $address[] = $row['username'];
 1478                      }
 1479                      else
 1480                      {
 1481                          $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']);
 1482                      }
 1483                  }
 1484              }
 1485              $db->sql_freeresult($result);
 1486          }
 1487   
 1488          if (sizeof($g))
 1489          {
 1490              if ($plaintext)
 1491              {
 1492                  $sql = 'SELECT group_name, group_type
 1493                      FROM ' . GROUPS_TABLE . '
 1494                          WHERE ' . $db->sql_in_set('group_id', $g);
 1495                  $result = $db->sql_query($sql);
 1496   
 1497                  while ($row = $db->sql_fetchrow($result))
 1498                  {
 1499                      if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
 1500                      {
 1501                          $address[] = $group_helper->get_name($row['group_name']);
 1502                      }
 1503                  }
 1504                  $db->sql_freeresult($result);
 1505              }
 1506              else
 1507              {
 1508                  $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id
 1509                      FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
 1510                          WHERE ' . $db->sql_in_set('g.group_id', $g) . '
 1511                          AND g.group_id = ug.group_id
 1512                          AND ug.user_pending = 0';
 1513                  $result = $db->sql_query($sql);
 1514   
 1515                  while ($row = $db->sql_fetchrow($result))
 1516                  {
 1517                      if (!isset($address['group'][$row['group_id']]))
 1518                      {
 1519                          if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
 1520                          {
 1521                              $row['group_name'] = $group_helper->get_name($row['group_name']);
 1522                              $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
 1523                          }
 1524                      }
 1525   
 1526                      if (isset($address['user'][$row['user_id']]))
 1527                      {
 1528                          $address['user'][$row['user_id']]['in_group'] = $row['group_id'];
 1529                      }
 1530                  }
 1531                  $db->sql_freeresult($result);
 1532              }
 1533          }
 1534   
 1535          if (sizeof($address) && !$plaintext)
 1536          {
 1537              $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true);
 1538   
 1539              foreach ($address as $type => $adr_ary)
 1540              {
 1541                  foreach ($adr_ary as $id => $row)
 1542                  {
 1543                      $tpl_ary = array(
 1544                          'IS_GROUP'    => ($type == 'group') ? true : false,
 1545                          'IS_USER'    => ($type == 'user') ? true : false,
 1546                          'UG_ID'        => $id,
 1547                          'NAME'        => $row['name'],
 1548                          'COLOUR'    => ($row['colour']) ? '#' . $row['colour'] : '',
 1549                          'TYPE'        => $type,
 1550                      );
 1551   
 1552                      if ($type == 'user')
 1553                      {
 1554                          $tpl_ary = array_merge($tpl_ary, array(
 1555                              'U_VIEW'        => get_username_string('profile', $id, $row['name'], $row['colour']),
 1556                              'NAME_FULL'        => get_username_string('full', $id, $row['name'], $row['colour']),
 1557                          ));
 1558                      }
 1559                      else
 1560                      {
 1561                          $tpl_ary = array_merge($tpl_ary, array(
 1562                              'U_VIEW'        => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $id),
 1563                          ));
 1564                      }
 1565   
 1566                      $template->assign_block_vars($check_type . '_recipient', $tpl_ary);
 1567                  }
 1568              }
 1569          }
 1570   
 1571          $addresses[$check_type] = $address;
 1572      }
 1573   
 1574      return $addresses;
 1575  }
 1576   
 1577  /**
 1578  * Get folder status
 1579  */
 1580  function get_folder_status($folder_id, $folder)
 1581  {
 1582      global $user;
 1583   
 1584      if (isset($folder[$folder_id]))
 1585      {
 1586          $folder = $folder[$folder_id];
 1587      }
 1588      else
 1589      {
 1590          return false;
 1591      }
 1592   
 1593      $return = array(
 1594          'folder_name'    => $folder['folder_name'],
 1595          'cur'            => $folder['num_messages'],
 1596          'remaining'        => ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0,
 1597          'max'            => $user->data['message_limit'],
 1598          'percent'        => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? floor(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0,
 1599      );
 1600   
 1601      $return['message']    = $user->lang('FOLDER_STATUS_MSG', $user->lang('MESSAGES_COUNT', (int) $return['max']), (int) $return['cur'], $return['percent']);
 1602   
 1603      return $return;
 1604  }
 1605   
 1606  //
 1607  // COMPOSE MESSAGES
 1608  //
 1609   
 1610  /**
 1611  * Submit PM
 1612  */
 1613  function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true)
 1614  {
 1615      global $db, $auth, $config, $user, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $request;
 1616   
 1617      // We do not handle erasing pms here
 1618      if ($mode == 'delete')
 1619      {
 1620          return false;
 1621      }
 1622   
 1623      $current_time = time();
 1624   
 1625      $data = $data_ary;
 1626      /**
 1627      * Get all parts of the PM that are to be submited to the DB.
 1628      *
 1629      * @event core.submit_pm_before
 1630      * @var    string    mode    PM Post mode - post|reply|quote|quotepost|forward|edit
 1631      * @var    string    subject    Subject of the private message
 1632      * @var    array    data    The whole row data of the PM.
 1633      * @since 3.1.0-b3
 1634      */
 1635      $vars = array('mode', 'subject', 'data');
 1636      extract($phpbb_dispatcher->trigger_event('core.submit_pm_before', compact($vars)));
 1637      $data_ary = $data;
 1638      unset($data);
 1639   
 1640      // Collect some basic information about which tables and which rows to update/insert
 1641      $sql_data = array();
 1642      $root_level = 0;
 1643   
 1644      // Recipient Information
 1645      $recipients = $to = $bcc = array();
 1646   
 1647      if ($mode != 'edit')
 1648      {
 1649          // Build Recipient List
 1650          // u|g => array($user_id => 'to'|'bcc')
 1651          $_types = array('u', 'g');
 1652          foreach ($_types as $ug_type)
 1653          {
 1654              if (isset($data_ary['address_list'][$ug_type]) && sizeof($data_ary['address_list'][$ug_type]))
 1655              {
 1656                  foreach ($data_ary['address_list'][$ug_type] as $id => $field)
 1657                  {
 1658                      $id = (int) $id;
 1659   
 1660                      // Do not rely on the address list being "valid"
 1661                      if (!$id || ($ug_type == 'u' && $id == ANONYMOUS))
 1662                      {
 1663                          continue;
 1664                      }
 1665   
 1666                      $field = ($field == 'to') ? 'to' : 'bcc';
 1667                      if ($ug_type == 'u')
 1668                      {
 1669                          $recipients[$id] = $field;
 1670                      }
 1671                      ${$field}[] = $ug_type . '_' . $id;
 1672                  }
 1673              }
 1674          }
 1675   
 1676          if (isset($data_ary['address_list']['g']) && sizeof($data_ary['address_list']['g']))
 1677          {
 1678              // We need to check the PM status of group members (do they want to receive PM's?)
 1679              // Only check if not a moderator or admin, since they are allowed to override this user setting
 1680              $sql_allow_pm = (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) ? ' AND u.user_allow_pm = 1' : '';
 1681   
 1682              $sql = 'SELECT u.user_type, ug.group_id, ug.user_id
 1683                  FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
 1684                  WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data_ary['address_list']['g'])) . '
 1685                      AND ug.user_pending = 0
 1686                      AND u.user_id = ug.user_id
 1687                      AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' .
 1688                      $sql_allow_pm;
 1689              $result = $db->sql_query($sql);
 1690   
 1691              while ($row = $db->sql_fetchrow($result))
 1692              {
 1693                  $field = ($data_ary['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
 1694                  $recipients[$row['user_id']] = $field;
 1695              }
 1696              $db->sql_freeresult($result);
 1697          }
 1698   
 1699          if (!sizeof($recipients))
 1700          {
 1701              trigger_error('NO_RECIPIENT');
 1702          }
 1703      }
 1704   
 1705      // First of all make sure the subject are having the correct length.
 1706      $subject = truncate_string($subject);
 1707   
 1708      $db->sql_transaction('begin');
 1709   
 1710      $sql = '';
 1711   
 1712      switch ($mode)
 1713      {
 1714          case 'reply':
 1715          case 'quote':
 1716              $root_level = ($data_ary['reply_from_root_level']) ? $data_ary['reply_from_root_level'] : $data_ary['reply_from_msg_id'];
 1717   
 1718              // Set message_replied switch for this user
 1719              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 1720                  SET pm_replied = 1
 1721                  WHERE user_id = ' . $data_ary['from_user_id'] . '
 1722                      AND msg_id = ' . $data_ary['reply_from_msg_id'];
 1723   
 1724          // no break
 1725   
 1726          case 'forward':
 1727          case 'post':
 1728          case 'quotepost':
 1729              $sql_data = array(
 1730                  'root_level'        => $root_level,
 1731                  'author_id'            => $data_ary['from_user_id'],
 1732                  'icon_id'            => $data_ary['icon_id'],
 1733                  'author_ip'            => $data_ary['from_user_ip'],
 1734                  'message_time'        => $current_time,
 1735                  'enable_bbcode'        => $data_ary['enable_bbcode'],
 1736                  'enable_smilies'    => $data_ary['enable_smilies'],
 1737                  'enable_magic_url'    => $data_ary['enable_urls'],
 1738                  'enable_sig'        => $data_ary['enable_sig'],
 1739                  'message_subject'    => $subject,
 1740                  'message_text'        => $data_ary['message'],
 1741                  'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0,
 1742                  'bbcode_bitfield'    => $data_ary['bbcode_bitfield'],
 1743                  'bbcode_uid'        => $data_ary['bbcode_uid'],
 1744                  'to_address'        => implode(':', $to),
 1745                  'bcc_address'        => implode(':', $bcc),
 1746                  'message_reported'    => 0,
 1747              );
 1748          break;
 1749   
 1750          case 'edit':
 1751              $sql_data = array(
 1752                  'icon_id'            => $data_ary['icon_id'],
 1753                  'message_edit_time'    => $current_time,
 1754                  'enable_bbcode'        => $data_ary['enable_bbcode'],
 1755                  'enable_smilies'    => $data_ary['enable_smilies'],
 1756                  'enable_magic_url'    => $data_ary['enable_urls'],
 1757                  'enable_sig'        => $data_ary['enable_sig'],
 1758                  'message_subject'    => $subject,
 1759                  'message_text'        => $data_ary['message'],
 1760                  'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0,
 1761                  'bbcode_bitfield'    => $data_ary['bbcode_bitfield'],
 1762                  'bbcode_uid'        => $data_ary['bbcode_uid']
 1763              );
 1764          break;
 1765      }
 1766   
 1767      if (sizeof($sql_data))
 1768      {
 1769          if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
 1770          {
 1771              $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
 1772              $data_ary['msg_id'] = $db->sql_nextid();
 1773          }
 1774          else if ($mode == 'edit')
 1775          {
 1776              $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
 1777                  SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
 1778                  WHERE msg_id = ' . $data_ary['msg_id'];
 1779              $db->sql_query($sql);
 1780          }
 1781      }
 1782   
 1783      if ($mode != 'edit')
 1784      {
 1785          if ($sql)
 1786          {
 1787              $db->sql_query($sql);
 1788          }
 1789          unset($sql);
 1790   
 1791          $sql_ary = array();
 1792          foreach ($recipients as $user_id => $type)
 1793          {
 1794              $sql_ary[] = array(
 1795                  'msg_id'        => (int) $data_ary['msg_id'],
 1796                  'user_id'        => (int) $user_id,
 1797                  'author_id'        => (int) $data_ary['from_user_id'],
 1798                  'folder_id'        => PRIVMSGS_NO_BOX,
 1799                  'pm_new'        => 1,
 1800                  'pm_unread'        => 1,
 1801                  'pm_forwarded'    => ($mode == 'forward') ? 1 : 0
 1802              );
 1803          }
 1804   
 1805          $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
 1806   
 1807          $sql = 'UPDATE ' . USERS_TABLE . '
 1808              SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
 1809              WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
 1810          $db->sql_query($sql);
 1811   
 1812          // Put PM into outbox
 1813          if ($put_in_outbox)
 1814          {
 1815              $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
 1816                  'msg_id'        => (int) $data_ary['msg_id'],
 1817                  'user_id'        => (int) $data_ary['from_user_id'],
 1818                  'author_id'        => (int) $data_ary['from_user_id'],
 1819                  'folder_id'        => PRIVMSGS_OUTBOX,
 1820                  'pm_new'        => 0,
 1821                  'pm_unread'        => 0,
 1822                  'pm_forwarded'    => ($mode == 'forward') ? 1 : 0))
 1823              );
 1824          }
 1825      }
 1826   
 1827      // Set user last post time
 1828      if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post')
 1829      {
 1830          $sql = 'UPDATE ' . USERS_TABLE . "
 1831              SET user_lastpost_time = $current_time
 1832              WHERE user_id = " . $data_ary['from_user_id'];
 1833          $db->sql_query($sql);
 1834      }
 1835   
 1836      // Submit Attachments
 1837      if (!empty($data_ary['attachment_data']) && $data_ary['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
 1838      {
 1839          $space_taken = $files_added = 0;
 1840          $orphan_rows = array();
 1841   
 1842          foreach ($data_ary['attachment_data'] as $pos => $attach_row)
 1843          {
 1844              $orphan_rows[(int) $attach_row['attach_id']] = array();
 1845          }
 1846   
 1847          if (sizeof($orphan_rows))
 1848          {
 1849              $sql = 'SELECT attach_id, filesize, physical_filename
 1850                  FROM ' . ATTACHMENTS_TABLE . '
 1851                  WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
 1852                      AND in_message = 1
 1853                      AND is_orphan = 1
 1854                      AND poster_id = ' . $user->data['user_id'];
 1855              $result = $db->sql_query($sql);
 1856   
 1857              $orphan_rows = array();
 1858              while ($row = $db->sql_fetchrow($result))
 1859              {
 1860                  $orphan_rows[$row['attach_id']] = $row;
 1861              }
 1862              $db->sql_freeresult($result);
 1863          }
 1864   
 1865          foreach ($data_ary['attachment_data'] as $pos => $attach_row)
 1866          {
 1867              if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
 1868              {
 1869                  continue;
 1870              }
 1871   
 1872              if (!$attach_row['is_orphan'])
 1873              {
 1874                  // update entry in db if attachment already stored in db and filespace
 1875                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
 1876                      SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
 1877                      WHERE attach_id = " . (int) $attach_row['attach_id'] . '
 1878                          AND is_orphan = 0';
 1879                  $db->sql_query($sql);
 1880              }
 1881              else
 1882              {
 1883                  // insert attachment into db
 1884                  if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
 1885                  {
 1886                      continue;
 1887                  }
 1888   
 1889                  $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
 1890                  $files_added++;
 1891   
 1892                  $attach_sql = array(
 1893                      'post_msg_id'        => $data_ary['msg_id'],
 1894                      'topic_id'            => 0,
 1895                      'is_orphan'            => 0,
 1896                      'poster_id'            => $data_ary['from_user_id'],
 1897                      'attach_comment'    => $attach_row['attach_comment'],
 1898                  );
 1899   
 1900                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
 1901                      WHERE attach_id = ' . $attach_row['attach_id'] . '
 1902                          AND is_orphan = 1
 1903                          AND poster_id = ' . $user->data['user_id'];
 1904                  $db->sql_query($sql);
 1905              }
 1906          }
 1907   
 1908          if ($space_taken && $files_added)
 1909          {
 1910              $config->increment('upload_dir_size', $space_taken, false);
 1911              $config->increment('num_files', $files_added, false);
 1912          }
 1913      }
 1914   
 1915      // Delete draft if post was loaded...
 1916      $draft_id = $request->variable('draft_loaded', 0);
 1917      if ($draft_id)
 1918      {
 1919          $sql = 'DELETE FROM ' . DRAFTS_TABLE . "
 1920              WHERE draft_id = $draft_id
 1921                  AND user_id = " . $data_ary['from_user_id'];
 1922          $db->sql_query($sql);
 1923      }
 1924   
 1925      $db->sql_transaction('commit');
 1926   
 1927      // Send Notifications
 1928      $pm_data = array_merge($data_ary, array(
 1929          'message_subject'        => $subject,
 1930          'recipients'            => $recipients,
 1931      ));
 1932   
 1933      /* @var $phpbb_notifications \phpbb\notification\manager */
 1934      $phpbb_notifications = $phpbb_container->get('notification_manager');
 1935   
 1936      if ($mode == 'edit')
 1937      {
 1938          $phpbb_notifications->update_notifications('notification.type.pm', $pm_data);
 1939      }
 1940      else
 1941      {
 1942          $phpbb_notifications->add_notifications('notification.type.pm', $pm_data);
 1943      }
 1944   
 1945      $data = $data_ary;
 1946      /**
 1947      * Get PM message ID after submission to DB
 1948      *
 1949      * @event core.submit_pm_after
 1950      * @var    string    mode    PM Post mode - post|reply|quote|quotepost|forward|edit
 1951      * @var    string    subject    Subject of the private message
 1952      * @var    array    data    The whole row data of the PM.
 1953      * @var    array    pm_data    The data sent to notification class
 1954      * @since 3.1.0-b5
 1955      */
 1956      $vars = array('mode', 'subject', 'data', 'pm_data');
 1957      extract($phpbb_dispatcher->trigger_event('core.submit_pm_after', compact($vars)));
 1958      $data_ary = $data;
 1959      unset($data);
 1960   
 1961      return $data_ary['msg_id'];
 1962  }
 1963   
 1964  /**
 1965  * Display Message History
 1966  */
 1967  function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)
 1968  {
 1969      global $db, $user, $template, $phpbb_root_path, $phpEx, $auth;
 1970   
 1971      // Select all receipts and the author from the pm we currently view, to only display their pm-history
 1972      $sql = 'SELECT author_id, user_id
 1973          FROM ' . PRIVMSGS_TO_TABLE . "
 1974          WHERE msg_id = $msg_id
 1975              AND folder_id <> " . PRIVMSGS_HOLD_BOX;
 1976      $result = $db->sql_query($sql);
 1977   
 1978      $recipients = array();
 1979      while ($row = $db->sql_fetchrow($result))
 1980      {
 1981          $recipients[] = (int) $row['user_id'];
 1982          $recipients[] = (int) $row['author_id'];
 1983      }
 1984      $db->sql_freeresult($result);
 1985      $recipients = array_unique($recipients);
 1986   
 1987      // Get History Messages (could be newer)
 1988      $sql = 'SELECT t.*, p.*, u.*
 1989          FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u
 1990          WHERE t.msg_id = p.msg_id
 1991              AND p.author_id = u.user_id
 1992              AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
 1993              AND ' . $db->sql_in_set('t.author_id', $recipients, false, true) . "
 1994              AND t.user_id = $user_id";
 1995   
 1996      // We no longer need those.
 1997      unset($recipients);
 1998   
 1999      if (!$message_row['root_level'])
 2000      {
 2001          $sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";
 2002      }
 2003      else
 2004      {
 2005          $sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')';
 2006      }
 2007      $sql .= ' ORDER BY p.message_time DESC';
 2008   
 2009      $result = $db->sql_query($sql);
 2010      $row = $db->sql_fetchrow($result);
 2011   
 2012      if (!$row)
 2013      {
 2014          $db->sql_freeresult($result);
 2015          return false;
 2016      }
 2017   
 2018      $title = $row['message_subject'];
 2019   
 2020      $rowset = array();
 2021      $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&amp;folder=';
 2022   
 2023      do
 2024      {
 2025          $folder_id = (int) $row['folder_id'];
 2026   
 2027          $row['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang['UNKNOWN_FOLDER'];
 2028   
 2029          if (isset($rowset[$row['msg_id']]))
 2030          {
 2031              $rowset[$row['msg_id']]['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang['UNKNOWN_FOLDER'];
 2032          }
 2033          else
 2034          {
 2035              $rowset[$row['msg_id']] = $row;
 2036          }
 2037      }
 2038      while ($row = $db->sql_fetchrow($result));
 2039      $db->sql_freeresult($result);
 2040   
 2041      if (sizeof($rowset) == 1 && !$in_post_mode)
 2042      {
 2043          return false;
 2044      }
 2045   
 2046      $title = censor_text($title);
 2047   
 2048      $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm');
 2049      $next_history_pm = $previous_history_pm = $prev_id = 0;
 2050   
 2051      // Re-order rowset to be able to get the next/prev message rows...
 2052      $rowset = array_values($rowset);
 2053   
 2054      for ($i = 0, $size = sizeof($rowset); $i < $size; $i++)
 2055      {
 2056          $row = &$rowset[$i];
 2057          $id = (int) $row['msg_id'];
 2058   
 2059          $author_id    = $row['author_id'];
 2060          $folder_id    = (int) $row['folder_id'];
 2061   
 2062          $subject    = $row['message_subject'];
 2063          $message    = $row['message_text'];
 2064   
 2065          $message = censor_text($message);
 2066   
 2067          $decoded_message = false;
 2068   
 2069          if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS)
 2070          {
 2071              $decoded_message = $message;
 2072              decode_message($decoded_message, $row['bbcode_uid']);
 2073   
 2074              $decoded_message = bbcode_nl2br($decoded_message);
 2075          }
 2076   
 2077          $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0);
 2078          $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0);
 2079   
 2080          $message = generate_text_for_display($message, $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, false);
 2081   
 2082          $subject = censor_text($subject);
 2083   
 2084          if ($id == $msg_id)
 2085          {
 2086              $next_history_pm = (isset($rowset[$i + 1])) ? (int) $rowset[$i + 1]['msg_id'] : 0;
 2087              $previous_history_pm = $prev_id;
 2088          }
 2089   
 2090          $template->assign_block_vars('history_row', array(
 2091              'MESSAGE_AUTHOR_QUOTE'        => (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''),
 2092              'MESSAGE_AUTHOR_FULL'        => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']),
 2093              'MESSAGE_AUTHOR_COLOUR'        => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']),
 2094              'MESSAGE_AUTHOR'            => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']),
 2095              'U_MESSAGE_AUTHOR'            => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']),
 2096   
 2097              'SUBJECT'            => $subject,
 2098              'SENT_DATE'            => $user->format_date($row['message_time']),
 2099              'MESSAGE'            => $message,
 2100              'FOLDER'            => implode($user->lang['COMMA_SEPARATOR'], $row['folder']),
 2101              'DECODED_MESSAGE'    => $decoded_message,
 2102   
 2103              'S_CURRENT_MSG'        => ($row['msg_id'] == $msg_id),
 2104              'S_AUTHOR_DELETED'    => ($author_id == ANONYMOUS) ? true : false,
 2105              'S_IN_POST_MODE'    => $in_post_mode,
 2106   
 2107              'MSG_ID'            => $row['msg_id'],
 2108              'MESSAGE_TIME'        => $row['message_time'],
 2109              'USER_ID'            => $row['user_id'],
 2110              'U_VIEW_MESSAGE'    => "$url&amp;f=$folder_id&amp;p=" . $row['msg_id'],
 2111              'U_QUOTE'            => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
 2112              'U_POST_REPLY_PM'    => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $row['msg_id'] : '')
 2113          );
 2114          unset($rowset[$i]);
 2115          $prev_id = $id;
 2116      }
 2117   
 2118      $template->assign_vars(array(
 2119          'QUOTE_IMG'            => $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']),
 2120          'HISTORY_TITLE'        => $title,
 2121   
 2122          'U_VIEW_NEXT_HISTORY'        => ($next_history_pm) ? "$url&amp;p=" . $next_history_pm : '',
 2123          'U_VIEW_PREVIOUS_HISTORY'    => ($previous_history_pm) ? "$url&amp;p=" . $previous_history_pm : '',
 2124      ));
 2125   
 2126      return true;
 2127  }
 2128   
 2129  /**
 2130  * Set correct users max messages in PM folder.
 2131  * If several group memberships define different amount of messages, the highest will be chosen.
 2132  */
 2133  function set_user_message_limit()
 2134  {
 2135      global $user, $db, $config;
 2136   
 2137      // Get maximum about from user memberships
 2138      $message_limit = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'message_limit');
 2139   
 2140      // If it is 0, there is no limit set and we use the maximum value within the config.
 2141      $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit;
 2142  }
 2143   
 2144  /**
 2145   * Get the maximum PM setting for the groups of the user
 2146   *
 2147   * @param \phpbb\db\driver\driver_interface $db
 2148   * @param int $user_id
 2149   * @param string $setting Only 'max_recipients' and 'message_limit' are supported
 2150   * @return int The maximum setting for all groups of the user, unless one group has '0'
 2151   * @throws \InvalidArgumentException If selected group setting is not supported
 2152   */
 2153  function phpbb_get_max_setting_from_group(\phpbb\db\driver\driver_interface $db, $user_id, $setting)
 2154  {
 2155      if ($setting !== 'max_recipients' && $setting !== 'message_limit')
 2156      {
 2157          throw new InvalidArgumentException('Setting "' . $setting . '" is not supported');
 2158      }
 2159   
 2160      // Get maximum number of allowed recipients
 2161      $sql = 'SELECT MAX(g.group_' . $setting . ') as max_setting
 2162          FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
 2163          WHERE ug.user_id = ' . (int) $user_id . '
 2164              AND ug.user_pending = 0
 2165              AND ug.group_id = g.group_id';
 2166      $result = $db->sql_query($sql);
 2167      $row = $db->sql_fetchrow($result);
 2168      $db->sql_freeresult($result);
 2169      $max_setting = (int) $row['max_setting'];
 2170   
 2171      return $max_setting;
 2172  }
 2173   
 2174  /**
 2175  * Generates an array of coloured recipient names from a list of PMs - (groups & users)
 2176  *
 2177  * @param    array    $pm_by_id    An array of rows from PRIVMSGS_TABLE, keys are the msg_ids.
 2178  *
 2179  * @return    array                2D Array: array(msg_id => array('username or group string', ...), ...)
 2180  *                                Usernames are generated with {@link get_username_string get_username_string}
 2181  *                                Groups are coloured and have a link to the membership page
 2182  */
 2183  function get_recipient_strings($pm_by_id)
 2184  {
 2185      global $db, $phpbb_root_path, $phpEx, $user, $phpbb_container;
 2186   
 2187      /** @var \phpbb\group\helper $group_helper */
 2188      $group_helper = $phpbb_container->get('group_helper');
 2189   
 2190      $address_list = $recipient_list = $address = array();
 2191   
 2192      $_types = array('u', 'g');
 2193   
 2194      foreach ($pm_by_id as $message_id => $row)
 2195      {
 2196          $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address']));
 2197   
 2198          foreach ($_types as $ug_type)
 2199          {
 2200              if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type]))
 2201              {
 2202                  foreach ($address[$message_id][$ug_type] as $ug_id => $in_to)
 2203                  {
 2204                      $recipient_list[$ug_type][$ug_id] = array('name' => $user->lang['NA'], 'colour' => '');
 2205                  }
 2206              }
 2207          }
 2208      }
 2209   
 2210      foreach ($_types as $ug_type)
 2211      {
 2212          if (!empty($recipient_list[$ug_type]))
 2213          {
 2214              if ($ug_type == 'u')
 2215              {
 2216                  $sql = 'SELECT user_id as id, username as name, user_colour as colour
 2217                      FROM ' . USERS_TABLE . '
 2218                      WHERE ';
 2219              }
 2220              else
 2221              {
 2222                  $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type
 2223                      FROM ' . GROUPS_TABLE . '
 2224                      WHERE ';
 2225              }
 2226              $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type])));
 2227   
 2228              $result = $db->sql_query($sql);
 2229   
 2230              while ($row = $db->sql_fetchrow($result))
 2231              {
 2232                  if ($ug_type == 'g')
 2233                  {
 2234                      $row['name'] = $group_helper->get_name($row['name']);
 2235                  }
 2236   
 2237                  $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
 2238              }
 2239              $db->sql_freeresult($result);
 2240          }
 2241      }
 2242   
 2243      foreach ($address as $message_id => $adr_ary)
 2244      {
 2245          foreach ($adr_ary as $type => $id_ary)
 2246          {
 2247              foreach ($id_ary as $ug_id => $_id)
 2248              {
 2249                  if ($type == 'u')
 2250                  {
 2251                      $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']);
 2252                  }
 2253                  else
 2254                  {
 2255                      $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : '';
 2256                      $link = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $ug_id) . '"' . $user_colour . '>';
 2257                      $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '</a>' : '');
 2258                  }
 2259              }
 2260          }
 2261      }
 2262   
 2263      return $address_list;
 2264  }
 2265