[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> functions_privmsgs.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package phpBB3
   5  * @version $Id: functions_privmsgs.php,v 1.57 2006/11/03 21:04:09 acydburn Exp $
   6  * @copyright (c) 2005 phpBB Group 
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License 
   8  *
   9  */
  10  
  11  /**
  12  */
  13  if (!defined('IN_PHPBB'))
  14  {
  15      exit;
  16  }
  17  
  18  /*
  19      Ability to simply add own rules by doing three things:
  20          1) Add an appropiate constant
  21          2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required)
  22          3) Add a new language variable to ucp.php
  23  
  24          The user is then able to select the new rule. It will be checked against and handled as specified.
  25          To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified.
  26  */
  27  
  28  define('RULE_IS_LIKE', 1);        // Is Like
  29  define('RULE_IS_NOT_LIKE', 2);    // Is Not Like
  30  define('RULE_IS', 3);            // Is
  31  define('RULE_IS_NOT', 4);        // Is Not
  32  define('RULE_BEGINS_WITH', 5);    // Begins with
  33  define('RULE_ENDS_WITH', 6);    // Ends with
  34  define('RULE_IS_FRIEND', 7);    // Is Friend
  35  define('RULE_IS_FOE', 8);        // Is Foe
  36  define('RULE_IS_USER', 9);        // Is User
  37  define('RULE_IS_GROUP', 10);    // Is In Usergroup
  38  define('RULE_ANSWERED', 11);    // Answered
  39  define('RULE_FORWARDED', 12);    // Forwarded
  40  define('RULE_TO_GROUP', 14);    // Usergroup
  41  define('RULE_TO_ME', 15);        // Me
  42  
  43  define('ACTION_PLACE_INTO_FOLDER', 1);
  44  define('ACTION_MARK_AS_READ', 2);
  45  define('ACTION_MARK_AS_IMPORTANT', 3);
  46  define('ACTION_DELETE_MESSAGE', 4);
  47  
  48  define('CHECK_SUBJECT', 1);
  49  define('CHECK_SENDER', 2);
  50  define('CHECK_MESSAGE', 3);
  51  define('CHECK_STATUS', 4);
  52  define('CHECK_TO', 5);
  53  
  54  /**
  55  * Global private message rules
  56  * These rules define what to do if a rule is hit
  57  */
  58  $global_privmsgs_rules = array(
  59      CHECK_SUBJECT    => array(
  60          RULE_IS_LIKE        => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
  61          RULE_IS_NOT_LIKE    => array('check0' => 'message_subject', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
  62          RULE_IS                => array('check0' => 'message_subject', 'function' => '{CHECK0} == {STRING}'),
  63          RULE_IS_NOT            => array('check0' => 'message_subject', 'function' => '{CHECK0} != {STRING}'),
  64          RULE_BEGINS_WITH    => array('check0' => 'message_subject', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
  65          RULE_ENDS_WITH        => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'),
  66      ),
  67  
  68      CHECK_SENDER    => array(
  69          RULE_IS_LIKE        => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
  70          RULE_IS_NOT_LIKE    => array('check0' => 'username', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
  71          RULE_IS                => array('check0' => 'username', 'function' => '{CHECK0} == {STRING}'),
  72          RULE_IS_NOT            => array('check0' => 'username', 'function' => '{CHECK0} != {STRING}'),
  73          RULE_BEGINS_WITH    => array('check0' => 'username', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
  74          RULE_ENDS_WITH        => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'),
  75          RULE_IS_FRIEND        => array('check0' => 'friend', 'function' => '{CHECK0} == 1'),
  76          RULE_IS_FOE            => array('check0' => 'foe', 'function' => '{CHECK0} == 1'),
  77          RULE_IS_USER        => array('check0' => 'author_id', 'function' => '{CHECK0} == {USER_ID}'),
  78          RULE_IS_GROUP        => array('check0' => 'author_in_group', 'function' => 'in_array({GROUP_ID}, {CHECK0})'),
  79      ),
  80  
  81      CHECK_MESSAGE    => array(
  82          RULE_IS_LIKE        => array('check0' => 'message_text', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
  83          RULE_IS_NOT_LIKE    => array('check0' => 'message_text', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
  84          RULE_IS                => array('check0' => 'message_text', 'function' => '{CHECK0} == {STRING}'),
  85          RULE_IS_NOT            => array('check0' => 'message_text', 'function' => '{CHECK0} != {STRING}'),
  86      ),
  87  
  88      CHECK_STATUS    => array(
  89          RULE_ANSWERED        => array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'),
  90          RULE_FORWARDED        => array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'),
  91      ),
  92  
  93      CHECK_TO        => array(
  94          RULE_TO_GROUP        => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group', 'function' => 'in_array("g_" . {CHECK2}, {CHECK0}) || in_array("g_" . {CHECK2}, {CHECK1})'),
  95          RULE_TO_ME            => array('check0' => 'to', 'check1' => 'bcc', 'function' => 'in_array("u_" . $user_id, {CHECK0}) || in_array("u_" . $user_id, {CHECK1})'),
  96      )
  97  );
  98  
  99  /**
 100  * This is for defining which condition fields to show for which Rule
 101  */
 102  $global_rule_conditions = array(
 103      RULE_IS_LIKE        => 'text',
 104      RULE_IS_NOT_LIKE    => 'text',
 105      RULE_IS                => 'text',
 106      RULE_IS_NOT            => 'text',
 107      RULE_BEGINS_WITH    => 'text',
 108      RULE_ENDS_WITH        => 'text',
 109      RULE_IS_USER        => 'user',
 110      RULE_IS_GROUP        => 'group'
 111  );
 112  
 113  /**
 114  * Get all folder
 115  */
 116  function get_folder($user_id, $folder_id = false)
 117  {
 118      global $db, $user, $template;
 119      global $phpbb_root_path, $phpEx;
 120  
 121      $folder = array();
 122  
 123      // Get folder informations
 124      $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread
 125          FROM ' . PRIVMSGS_TO_TABLE . "
 126          WHERE user_id = $user_id
 127              AND folder_id <> " . PRIVMSGS_NO_BOX . '
 128          GROUP BY folder_id';
 129      $result = $db->sql_query($sql);
 130  
 131      $num_messages = $num_unread = array();
 132      while ($row = $db->sql_fetchrow($result))
 133      {
 134          $num_messages[(int) $row['folder_id']] = $row['num_messages'];
 135          $num_unread[(int) $row['folder_id']] = $row['num_unread'];
 136      }
 137      $db->sql_freeresult($result);
 138  
 139      // Make sure the default boxes are defined
 140      $available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX);
 141  
 142      foreach ($available_folder as $default_folder)
 143      {
 144          if (!isset($num_messages[$default_folder]))
 145          {
 146              $num_messages[$default_folder] = 0;
 147          }
 148  
 149          if (!isset($num_unread[$default_folder]))
 150          {
 151              $num_unread[$default_folder] = 0;
 152          }
 153      }
 154  
 155      // Adjust unread status for outbox
 156      $num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX];
 157  
 158      $folder[PRIVMSGS_INBOX] = array(
 159          'folder_name'        => $user->lang['PM_INBOX'],
 160          'num_messages'        => $num_messages[PRIVMSGS_INBOX],
 161          'unread_messages'    => $num_unread[PRIVMSGS_INBOX]
 162      );
 163  
 164      // Custom Folder
 165      $sql = 'SELECT folder_id, folder_name, pm_count
 166          FROM ' . PRIVMSGS_FOLDER_TABLE . "
 167              WHERE user_id = $user_id";
 168      $result = $db->sql_query($sql);
 169  
 170      while ($row = $db->sql_fetchrow($result))
 171      {
 172          $folder[$row['folder_id']] = array(
 173              'folder_name'        => $row['folder_name'],
 174              'num_messages'        => $row['pm_count'],
 175              'unread_messages'    => ((isset($num_unread[$row['folder_id']])) ? $num_unread[$row['folder_id']] : 0)
 176          );
 177      }
 178      $db->sql_freeresult($result);
 179  
 180      $folder[PRIVMSGS_OUTBOX] = array(
 181          'folder_name'        => $user->lang['PM_OUTBOX'],
 182          'num_messages'        => $num_messages[PRIVMSGS_OUTBOX],
 183          'unread_messages'    => $num_unread[PRIVMSGS_OUTBOX]
 184      );
 185  
 186      $folder[PRIVMSGS_SENTBOX] = array(
 187          'folder_name'        => $user->lang['PM_SENTBOX'],
 188          'num_messages'        => $num_messages[PRIVMSGS_SENTBOX],
 189          'unread_messages'    => $num_unread[PRIVMSGS_SENTBOX]
 190      );
 191  
 192      // Define Folder Array for template designers (and for making custom folders usable by the template too)
 193      foreach ($folder as $f_id => $folder_ary)
 194      {
 195          $folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox');
 196  
 197          $template->assign_block_vars('folder', array(
 198              'FOLDER_ID'            => $f_id,
 199              'FOLDER_NAME'        => $folder_ary['folder_name'],
 200              'NUM_MESSAGES'        => $folder_ary['num_messages'],
 201              'UNREAD_MESSAGES'    => $folder_ary['unread_messages'],
 202  
 203              '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),
 204  
 205              'S_CUR_FOLDER'        => ($f_id === $folder_id) ? true : false,
 206              'S_UNREAD_MESSAGES'    => ($folder_ary['unread_messages']) ? true : false,
 207              'S_CUSTOM_FOLDER'    => ($f_id > 0) ? true : false)
 208          );
 209      }
 210  
 211      return $folder;
 212  }
 213  
 214  /**
 215  * Delete Messages From Sentbox
 216  * we are doing this here because this saves us a bunch of checks and queries
 217  */
 218  function clean_sentbox($num_sentbox_messages)
 219  {
 220      global $db, $user, $config;
 221  
 222      // Check Message Limit
 223      if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit'])
 224      {
 225          // Delete old messages
 226          $sql = 'SELECT t.msg_id
 227              FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
 228              WHERE t.msg_id = p.msg_id
 229                  AND t.user_id = ' . $user->data['user_id'] . '
 230                  AND t.folder_id = ' . PRIVMSGS_SENTBOX . '
 231              ORDER BY p.message_time ASC';
 232          $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit']));
 233  
 234          $delete_ids = array();
 235          while ($row = $db->sql_fetchrow($result))
 236          {
 237              $delete_ids[] = $row['msg_id'];
 238          }
 239          $db->sql_freeresult($result);
 240          delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX);
 241      }
 242  }
 243  
 244  /**
 245  * Check Rule against Message Informations
 246  */
 247  function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
 248  {
 249      global $user, $config;
 250  
 251      if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
 252      {
 253          return false;
 254      }
 255  
 256      $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']];
 257  
 258      // Replace Check Literals
 259      $evaluate = $check_ary['function'];
 260      $evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate);
 261  
 262      // Replace Rule Literals
 263      $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate);
 264  
 265      // Evil Statement
 266      $result = false;
 267      eval('$result = (' . $evaluate . ') ? true : false;');
 268  
 269      if (!$result)
 270      {
 271          return false;
 272      }
 273  
 274      switch ($rule_row['rule_action'])
 275      {
 276          case ACTION_PLACE_INTO_FOLDER:
 277              return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']);
 278          break;
 279          
 280          case ACTION_MARK_AS_READ:
 281          case ACTION_MARK_AS_IMPORTANT:
 282              return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
 283          break;
 284  
 285          case ACTION_DELETE_MESSAGE:
 286              global $db, $auth;
 287  
 288              // Check for admins/mods - users are not allowed to remove those messages...
 289              // We do the check here to make sure the data we use is consistent
 290              $sql = 'SELECT user_id, user_type, user_permissions
 291                  FROM ' . USERS_TABLE . '
 292                  WHERE user_id = ' . (int) $message_row['author_id'];
 293              $result = $db->sql_query($sql);
 294              $userdata = $db->sql_fetchrow($result);
 295              $db->sql_freeresult($result);
 296  
 297              $auth2 = new auth();
 298              $auth2->acl($userdata);
 299  
 300              if (!$auth2->acl_get('a_') && !$auth->acl_get('m_') && !$auth2->acl_getf_global('m_'))
 301              {
 302                  return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
 303              }
 304  
 305              return false;
 306          break;
 307          
 308          default:
 309              return false;
 310      }
 311  
 312      return false;
 313  }
 314  
 315  /**
 316  * Place new messages into appropiate folder
 317  */
 318  function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
 319  {
 320      global $db, $user, $config;
 321  
 322      if (!$user->data['user_new_privmsg'])
 323      {
 324          return 0;
 325      }
 326  
 327      $user_new_privmsg = (int) $user->data['user_new_privmsg'];
 328      $user_message_rules = (int) $user->data['user_message_rules'];
 329      $user_id = (int) $user->data['user_id'];
 330  
 331      $action_ary = $move_into_folder = array();
 332  
 333      if ($release)
 334      {
 335          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 
 336              SET folder_id = ' . PRIVMSGS_NO_BOX . '
 337              WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . "
 338                  AND user_id = $user_id";
 339          $db->sql_query($sql);
 340      }
 341  
 342      // Get those messages not yet placed into any box
 343      $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
 344          FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u
 345          WHERE t.user_id = $user_id
 346              AND p.author_id = u.user_id
 347              AND t.folder_id = " . PRIVMSGS_NO_BOX . '
 348              AND t.msg_id = p.msg_id';
 349  
 350      // Just place into the appropiate arrays if no rules need to be checked
 351      if (!$user_message_rules)
 352      {
 353          $result = $db->sql_query($retrieve_sql);
 354  
 355          while ($row = $db->sql_fetchrow($result))
 356          {
 357              $action_ary[$row['msg_id']][] = array('action' => false);
 358              $move_into_folder[PRIVMSGS_INBOX][] = $row['msg_id'];
 359          }
 360          $db->sql_freeresult($result);
 361      }
 362      else
 363      {
 364          $user_rules = $zebra = $check_rows = array();
 365          $user_ids = $memberships = array();
 366  
 367          // First of all, grab all rules and retrieve friends/foes
 368          $sql = 'SELECT * 
 369              FROM ' . PRIVMSGS_RULES_TABLE . "
 370              WHERE user_id = $user_id";
 371          $result = $db->sql_query($sql);
 372          $user_rules = $db->sql_fetchrowset($result);
 373          $db->sql_freeresult($result);
 374  
 375          if (sizeof($user_rules))
 376          {
 377              $sql = 'SELECT zebra_id, friend, foe
 378                  FROM ' . ZEBRA_TABLE . "
 379                  WHERE user_id = $user_id";
 380              $result = $db->sql_query($sql);
 381  
 382              while ($row = $db->sql_fetchrow($result))
 383              {
 384                  $zebra[$row['zebra_id']] = $row;
 385              }
 386              $db->sql_freeresult($result);
 387          }
 388  
 389          // Now build a bare-bone check_row array
 390          $result = $db->sql_query($retrieve_sql);
 391  
 392          while ($row = $db->sql_fetchrow($result))
 393          {
 394              $check_rows[] = array_merge($row, array(
 395                  'to'                => explode(':', $row['to_address']),
 396                  'bcc'                => explode(':', $row['bcc_address']),
 397                  'friend'            => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0,
 398                  'foe'                => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0,
 399                  'user_in_group'        => array($user->data['group_id']),
 400                  'author_in_group'    => array())
 401              );
 402  
 403              $user_ids[] = $row['user_id'];
 404          }
 405          $db->sql_freeresult($result);
 406  
 407          // Retrieve user memberships
 408          if (sizeof($user_ids))
 409          {
 410              $sql = 'SELECT *
 411                  FROM ' . USER_GROUP_TABLE . ' 
 412                  WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
 413                      AND user_pending = 0';
 414              $result = $db->sql_query($sql);
 415  
 416              while ($row = $db->sql_fetchrow($result))
 417              {
 418                  $memberships[$row['user_id']][] = $row['group_id'];
 419              }
 420              $db->sql_freeresult($result);
 421          }
 422  
 423          // Now place into the appropiate folder
 424          foreach ($check_rows as $row)
 425          {
 426              // Add membership if set
 427              if (isset($memberships[$row['author_id']]))
 428              {
 429                  $row['author_in_group'] = $memberships[$row['user_id']];
 430              }
 431  
 432              // Check Rule - this should be very quick since we have all informations we need
 433              $is_match = false;
 434              foreach ($user_rules as $rule_row)
 435              {
 436                  if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false)
 437                  {
 438                      $is_match = true;
 439                      $action_ary[$row['msg_id']][] = $action;
 440                  }
 441              }
 442  
 443              if (!$is_match)
 444              {
 445                  $action_ary[$row['msg_id']][] = array('action' => false);
 446                  $move_into_folder[PRIVMSGS_INBOX][] = $row['msg_id'];
 447              }
 448          }
 449  
 450          unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
 451      }
 452  
 453      // We place actions into arrays, to save queries.
 454      $num_new = $num_unread = 0;
 455      $sql = $unread_ids = $delete_ids = $important_ids = array();
 456  
 457      foreach ($action_ary as $msg_id => $msg_ary)
 458      {
 459          // It is allowed to execute actions more than once, except placing messages into folder
 460          $folder_action = false;
 461  
 462          foreach ($msg_ary as $pos => $rule_ary)
 463          {
 464              if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER)
 465              {
 466                  continue;
 467              }
 468  
 469              switch ($rule_ary['action'])
 470              {
 471                  case ACTION_PLACE_INTO_FOLDER:
 472                      // Folder actions have precedence, so we will remove any other ones
 473                      $folder_action = true;
 474                      $_folder_id = (int) $rule_ary['folder_id'];
 475                      $move_into_folder = array();
 476                      $move_into_folder[$_folder_id][] = $msg_id;
 477                      $num_new++;
 478                  break;
 479  
 480                  case ACTION_MARK_AS_READ:
 481                      if ($rule_ary['pm_unread'])
 482                      {
 483                          $unread_ids[] = $msg_id;
 484                      }
 485  
 486                      if (!$folder_action)
 487                      {
 488                          $move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
 489                      }
 490                  break;
 491  
 492                  case ACTION_DELETE_MESSAGE:
 493                      $delete_ids[] = $msg_id;
 494                  break;
 495  
 496                  case ACTION_MARK_AS_IMPORTANT:
 497                      if (!$rule_ary['pm_marked'])
 498                      {
 499                          $important_ids[] = $msg_id;
 500                      }
 501  
 502                      if (!$folder_action)
 503                      {
 504                          $move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
 505                      }
 506                  break;
 507              }
 508          }
 509      }
 510  
 511  //    $num_new += sizeof(array_unique($delete_ids));
 512  //    $num_unread += sizeof(array_unique($delete_ids));
 513      $num_unread += sizeof(array_unique($unread_ids));
 514  
 515      // Do not change the order of processing
 516      // The number of queries needed to be executed here highly depends on the defined rules and are
 517      // only gone through if new messages arrive.
 518      $num_not_moved = 0;
 519  
 520      // Delete messages
 521      if (sizeof($delete_ids))
 522      {
 523          delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX);
 524      }
 525  
 526      // Set messages to Unread
 527      if (sizeof($unread_ids))
 528      {
 529          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 
 530              SET pm_unread = 0
 531              WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "
 532                  AND user_id = $user_id
 533                  AND folder_id = " . PRIVMSGS_NO_BOX;
 534          $db->sql_query($sql);
 535      }
 536  
 537      // mark messages as important
 538      if (sizeof($important_ids))
 539      {
 540          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 541              SET pm_marked = !pm_marked
 542              WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
 543                  AND user_id = $user_id
 544                  AND " . $db->sql_in_set('msg_id', $important_ids);
 545          $db->sql_query($sql);
 546      }
 547  
 548      // Move into folder
 549      $folder = array();
 550  
 551      if (sizeof($move_into_folder))
 552      {
 553          // Determine Full Folder Action - we need the move to folder id later eventually
 554          $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
 555  
 556          $sql_folder = array_keys($move_into_folder);
 557          if ($full_folder_action >= 0)
 558          {
 559              $sql_folder[] = $full_folder_action;
 560          }
 561  
 562          $sql = 'SELECT folder_id, pm_count 
 563              FROM ' . PRIVMSGS_FOLDER_TABLE . '
 564              WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "
 565                  AND user_id = $user_id";
 566          $result = $db->sql_query($sql);
 567  
 568          while ($row = $db->sql_fetchrow($result))
 569          {
 570              $folder[(int) $row['folder_id']] = (int) $row['pm_count'];
 571          }
 572          $db->sql_freeresult($result);
 573  
 574          unset($sql_folder);
 575  
 576          if (in_array(PRIVMSGS_INBOX, array_keys($move_into_folder)))
 577          {
 578              $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages
 579                  FROM ' . PRIVMSGS_TO_TABLE . "
 580                  WHERE user_id = $user_id
 581                      AND folder_id = " . PRIVMSGS_INBOX . "
 582                  GROUP BY folder_id";
 583              $result = $db->sql_query_limit($sql, 1);
 584              $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages');
 585              $db->sql_freeresult($result);
 586          }
 587      }
 588  
 589      // Here we have ideally only one folder to move into
 590      foreach ($move_into_folder as $folder_id => $msg_ary)
 591      {
 592          $dest_folder = $folder_id;
 593          $full_folder_action = FULL_FOLDER_NONE;
 594  
 595          // Check Message Limit - we calculate with the complete array, most of the time it is one message
 596          // But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
 597          if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit'])
 598          {
 599              $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
 600  
 601              // If destination folder itself is full...
 602              if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit'])
 603              {
 604                  $full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1));
 605              }
 606  
 607              // If Full Folder Action is to move to another folder, we simply adjust the destination folder
 608              if ($full_folder_action >= 0)
 609              {
 610                  $dest_folder = $full_folder_action;
 611              }
 612              else if ($full_folder_action == FULL_FOLDER_DELETE)
 613              {
 614                  // Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
 615                  $sql = 'SELECT msg_id
 616                      FROM ' . PRIVMSGS_TO_TABLE . "
 617                      WHERE user_id = $user_id
 618                          AND folder_id = $dest_folder
 619                      ORDER BY msg_id ASC";
 620                  $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit']));
 621  
 622                  $delete_ids = array();
 623                  while ($row = $db->sql_fetchrow($result))
 624                  {
 625                      $delete_ids[] = $row['msg_id'];
 626                  }
 627                  $db->sql_freeresult($result);
 628  
 629                  delete_pm($user_id, $delete_ids, $dest_folder);
 630              }
 631          }
 632          
 633          // 
 634          if ($full_folder_action == FULL_FOLDER_HOLD)
 635          {
 636              $num_not_moved += sizeof($msg_ary);
 637  
 638              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 
 639                  SET folder_id = ' . PRIVMSGS_HOLD_BOX . '
 640                  WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
 641                      AND user_id = $user_id
 642                      AND " . $db->sql_in_set('msg_id', $msg_ary);
 643              $db->sql_query($sql);
 644          }
 645          else
 646          {
 647              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 
 648                  SET folder_id = $dest_folder, pm_new = 0
 649                  WHERE folder_id = " . PRIVMSGS_NO_BOX . "
 650                      AND user_id = $user_id
 651                      AND pm_new = 1
 652                      AND " . $db->sql_in_set('msg_id', $msg_ary);
 653              $db->sql_query($sql);
 654  
 655              if ($dest_folder != PRIVMSGS_INBOX)
 656              {
 657                  $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . '
 658                      SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "
 659                      WHERE folder_id = $dest_folder
 660                          AND user_id = $user_id";
 661                  $db->sql_query($sql);
 662              }
 663              else
 664              {
 665                  $num_new += $db->sql_affectedrows();
 666              }
 667          }
 668      }
 669  
 670      if (sizeof($action_ary))
 671      {
 672          // Move from OUTBOX to SENTBOX
 673          // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
 674          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 
 675              SET folder_id = ' . PRIVMSGS_SENTBOX . '
 676              WHERE folder_id = ' . PRIVMSGS_OUTBOX . '
 677                  AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
 678          $db->sql_query($sql);
 679      }
 680  
 681      // Update unread and new status field
 682      if ($num_unread || $num_new)
 683      {
 684          $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
 685          if ($num_new)
 686          {
 687              $set_sql .= ($set_sql != '') ? ', ' : '';
 688              $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
 689          }
 690          
 691          $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
 692  
 693          $user->data['user_new_privmsg'] -= $num_new;
 694          $user->data['user_unread_privmsg'] -= $num_unread;
 695      }
 696  
 697      return $num_not_moved;
 698  }
 699  
 700  /**
 701  * Move PM from one to another folder
 702  */
 703  function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id)
 704  {
 705      global $db, $user;
 706      global $phpbb_root_path, $phpEx;
 707  
 708      $num_moved = 0;
 709  
 710      if (!is_array($move_msg_ids))
 711      {
 712          $move_msg_ids = array($move_msg_ids);
 713      }
 714  
 715      if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && 
 716          !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && $cur_folder_id != $dest_folder)
 717      {
 718          // We have to check the destination folder ;)
 719          if ($dest_folder != PRIVMSGS_INBOX)
 720          {
 721              $sql = 'SELECT folder_id, folder_name, pm_count
 722                  FROM ' . PRIVMSGS_FOLDER_TABLE . "
 723                  WHERE folder_id = $dest_folder
 724                      AND user_id = $user_id";
 725              $result = $db->sql_query($sql);
 726              $row = $db->sql_fetchrow($result);
 727              $db->sql_freeresult($result);
 728  
 729              if (!$row)
 730              {
 731                  trigger_error('NOT_AUTHORIZED');
 732              }
 733  
 734              if ($row['pm_count'] + sizeof($move_msg_ids) > $message_limit)
 735              {
 736                  $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />';
 737                  $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']);
 738                  trigger_error($message);
 739              }
 740          }
 741          else
 742          {
 743              $sql = 'SELECT COUNT(msg_id) as num_messages
 744                  FROM ' . PRIVMSGS_TO_TABLE . '
 745                  WHERE folder_id = ' . PRIVMSGS_INBOX . "
 746                      AND user_id = $user_id";
 747              $result = $db->sql_query($sql);
 748              $num_messages = (int) $db->sql_fetchfield('num_messages');
 749              $db->sql_freeresult($result);
 750  
 751              if ($num_messages + sizeof($move_msg_ids) > $message_limit)
 752              {
 753                  $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />';
 754                  $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']);
 755                  trigger_error($message);
 756              }
 757          }
 758  
 759          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
 760              SET folder_id = $dest_folder
 761              WHERE folder_id = $cur_folder_id
 762                  AND user_id = $user_id
 763                  AND " . $db->sql_in_set('msg_id', $move_msg_ids);
 764          $db->sql_query($sql);
 765          $num_moved = $db->sql_affectedrows();
 766  
 767          // Update pm counts
 768          if ($num_moved)
 769          {
 770              if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)))
 771              {
 772                  $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
 773                      SET pm_count = pm_count - $num_moved
 774                      WHERE folder_id = $cur_folder_id
 775                          AND user_id = $user_id";
 776                  $db->sql_query($sql);
 777              }
 778  
 779              if ($dest_folder != PRIVMSGS_INBOX)
 780              {
 781                  $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
 782                      SET pm_count = pm_count + $num_moved
 783                      WHERE folder_id = $dest_folder
 784                          AND user_id = $user_id";
 785                  $db->sql_query($sql);
 786              }
 787          }
 788      }
 789  
 790      return $num_moved;
 791  }
 792  
 793  /**
 794  * Update unread message status
 795  */
 796  function update_unread_status($unread, $msg_id, $user_id, $folder_id)
 797  {
 798      if (!$unread)
 799      {
 800          return;
 801      }
 802  
 803      global $db, $user;
 804  
 805      $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 
 806          SET pm_unread = 0
 807          WHERE msg_id = $msg_id
 808              AND user_id = $user_id
 809              AND folder_id = $folder_id";
 810      $db->sql_query($sql);
 811  
 812      $sql = 'UPDATE ' . USERS_TABLE . " 
 813          SET user_unread_privmsg = user_unread_privmsg - 1
 814          WHERE user_id = $user_id";
 815      $db->sql_query($sql);
 816  
 817      if ($user->data['user_id'] == $user_id)
 818      {
 819          $user->data['user_unread_privmsg']--;
 820      }
 821  }
 822  
 823  /**
 824  * Handle all actions possible with marked messages
 825  */
 826  function handle_mark_actions($user_id, $mark_action)
 827  {
 828      global $db, $user, $_POST, $phpbb_root_path, $phpEx;
 829  
 830      $msg_ids        = (isset($_POST['marked_msg_id'])) ? array_map('intval', $_POST['marked_msg_id']) : array();
 831      $cur_folder_id    = request_var('cur_folder_id', PRIVMSGS_NO_BOX);
 832      $confirm        = (isset($_POST['confirm'])) ? true : false;
 833  
 834      if (!sizeof($msg_ids))
 835      {
 836          return false;
 837      }
 838  
 839      switch ($mark_action)
 840      {
 841          case 'mark_important':
 842  
 843              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
 844                  SET pm_marked = !pm_marked
 845                  WHERE folder_id = $cur_folder_id
 846                      AND user_id = $user_id
 847                      AND " . $db->sql_in_set('msg_id', $msg_ids);
 848              $db->sql_query($sql);
 849  
 850          break;
 851  
 852          case 'delete_marked':
 853  
 854              if (confirm_box(true))
 855              {
 856                  delete_pm($user_id, $msg_ids, $cur_folder_id);
 857                  
 858                  $success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED';
 859                  $redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $cur_folder_id);
 860  
 861                  meta_refresh(3, $redirect);
 862                  trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>'));
 863              }
 864              else
 865              {
 866                  $s_hidden_fields = array(
 867                      'cur_folder_id'    => $cur_folder_id, 
 868                      'mark_option'    => 'delete_marked',
 869                      'submit_mark'    => true,
 870                      'marked_msg_id'    => $msg_ids
 871                  );
 872  
 873                  confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields));
 874              }
 875  
 876          break;
 877  
 878          default:
 879              return false;
 880      }
 881  
 882      return true;
 883  }
 884  
 885  /**
 886  * Delete PM(s)
 887  */
 888  function delete_pm($user_id, $msg_ids, $folder_id)
 889  {
 890      global $db, $user;
 891  
 892      $user_id    = (int) $user_id;
 893      $folder_id    = (int) $folder_id;
 894  
 895      if (!$user_id)
 896      {
 897          return false;
 898      }
 899  
 900      if (!is_array($msg_ids))
 901      {
 902          if (!$msg_ids)
 903          {
 904              return false;
 905          }
 906          $msg_ids = array($msg_ids);
 907      }
 908  
 909      if (!sizeof($msg_ids))
 910      {
 911          return false;
 912      }
 913  
 914      // Get PM Informations for later deleting
 915      $sql = 'SELECT msg_id, pm_unread, pm_new
 916          FROM ' . PRIVMSGS_TO_TABLE . '
 917          WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . "
 918              AND folder_id = $folder_id
 919              AND user_id = $user_id";
 920      $result = $db->sql_query($sql);
 921  
 922      $delete_rows = array();
 923      $num_unread = $num_new = $num_deleted = 0;
 924      while ($row = $db->sql_fetchrow($result))
 925      {
 926          $num_unread += (int) $row['pm_unread'];
 927          $num_new += (int) $row['pm_new'];
 928  
 929          $delete_rows[$row['msg_id']] = 1;
 930      }
 931      $db->sql_freeresult($result);
 932      unset($msg_ids);
 933  
 934      if (!sizeof($delete_rows))
 935      {
 936          return false;
 937      }
 938  
 939      // if no one has read the message yet (meaning it is in users outbox)
 940      // then mark the message as deleted...
 941      if ($folder_id == PRIVMSGS_OUTBOX)
 942      {
 943          // Remove PM from Outbox
 944          $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
 945              WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . '
 946                  AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
 947          $db->sql_query($sql);
 948  
 949          // Update PM Information for safety
 950          $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = ''
 951              WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows));
 952          $db->sql_query($sql);
 953  
 954          // Set delete flag for those intended to receive the PM
 955          // We do not remove the message actually, to retain some basic informations (sent time for example)
 956          $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
 957              SET pm_deleted = 1
 958              WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
 959          $db->sql_query($sql);
 960  
 961          $num_deleted = $db->sql_affectedrows();
 962      }
 963      else
 964      {
 965          // Delete Private Message Informations
 966          $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
 967              WHERE user_id = $user_id
 968                  AND folder_id = $folder_id
 969                  AND " . $db->sql_in_set('msg_id', array_keys($delete_rows));
 970          $db->sql_query($sql);
 971          $num_deleted = $db->sql_affectedrows();
 972      }
 973  
 974      // if folder id is user defined folder then decrease pm_count
 975      if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX)))
 976      {
 977          $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 
 978              SET pm_count = pm_count - $num_deleted 
 979              WHERE folder_id = $folder_id";
 980          $db->sql_query($sql);
 981      }
 982  
 983      // Update unread and new status field
 984      if ($num_unread || $num_new)
 985      {
 986          $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
 987  
 988          if ($num_new)
 989          {
 990              $set_sql .= ($set_sql != '') ? ', ' : '';
 991              $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
 992          }
 993  
 994          $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
 995  
 996          $user->data['user_new_privmsg'] -= $num_new;
 997          $user->data['user_unread_privmsg'] -= $num_unread;
 998      }
 999      
1000      // Now we have to check which messages we can delete completely    
1001      $sql = 'SELECT msg_id 
1002          FROM ' . PRIVMSGS_TO_TABLE . '
1003          WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1004      $result = $db->sql_query($sql);
1005  
1006      while ($row = $db->sql_fetchrow($result))
1007      {
1008          unset($delete_rows[$row['msg_id']]);
1009      }
1010      $db->sql_freeresult($result);
1011  
1012      $delete_ids = array_keys($delete_rows);
1013  
1014      if (sizeof($delete_ids))
1015      {
1016          $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
1017              WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
1018          $db->sql_query($sql);
1019      }
1020  
1021      return true;
1022  }
1023  
1024  /**
1025  * Rebuild message header
1026  */
1027  function rebuild_header($check_ary)
1028  {
1029      global $db;
1030  
1031      $address = array();
1032  
1033      foreach ($check_ary as $check_type => $address_field)
1034      {
1035          // Split Addresses into users and groups
1036          preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1037  
1038          $u = $g = array();
1039          foreach ($match[1] as $id => $type)
1040          {
1041              ${$type}[] = (int) $match[2][$id];
1042          }
1043  
1044          $_types = array('u', 'g');
1045          foreach ($_types as $type)
1046          {
1047              if (sizeof($$type))
1048              {
1049                  foreach ($$type as $id)
1050                  {
1051                      $address[$type][$id] = $check_type;
1052                  }
1053              }
1054          }
1055      }
1056  
1057      return $address;
1058  }
1059  
1060  /**
1061  * Print out/assign recipient informations
1062  */
1063  function write_pm_addresses($check_ary, $author_id, $plaintext = false)
1064  {
1065      global $db, $user, $template, $phpbb_root_path, $phpEx;
1066  
1067      $addresses = array();
1068  
1069      foreach ($check_ary as $check_type => $address_field)
1070      {
1071          if (!is_array($address_field))
1072          {
1073              // Split Addresses into users and groups
1074              preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1075  
1076              $u = $g = array();
1077              foreach ($match[1] as $id => $type)
1078              {
1079                  ${$type}[] = (int) $match[2][$id];
1080              }
1081          }
1082          else
1083          {
1084              $u = $address_field['u'];
1085              $g = $address_field['g'];
1086          }
1087  
1088          $address = array();
1089          if (sizeof($u))
1090          {
1091              $sql = 'SELECT user_id, username, user_colour 
1092                  FROM ' . USERS_TABLE . '
1093                  WHERE ' . $db->sql_in_set('user_id', $u) . '
1094                      AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1095              $result = $db->sql_query($sql);
1096  
1097              while ($row = $db->sql_fetchrow($result))
1098              {
1099                  if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1100                  {
1101                      if ($plaintext)
1102                      {
1103                          $address[] = $row['username'];
1104                      }
1105                      else
1106                      {
1107                          $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']);
1108                      }
1109                  }
1110              }
1111              $db->sql_freeresult($result);
1112          }
1113  
1114          if (sizeof($g))
1115          {
1116              if ($plaintext)
1117              {
1118                  $sql = 'SELECT group_name, group_type
1119                      FROM ' . GROUPS_TABLE . ' 
1120                          WHERE ' . $db->sql_in_set('group_id', $g);
1121                  $result = $db->sql_query($sql);
1122          
1123                  while ($row = $db->sql_fetchrow($result))
1124                  {
1125                      if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1126                      {
1127                          $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
1128                      }
1129                  }
1130                  $db->sql_freeresult($result);
1131              }
1132              else
1133              {
1134                  $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id
1135                      FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
1136                          WHERE ' . $db->sql_in_set('g.group_id', $g) . '
1137                          AND g.group_id = ug.group_id
1138                          AND ug.user_pending = 0';
1139                  $result = $db->sql_query($sql);
1140          
1141                  while ($row = $db->sql_fetchrow($result))
1142                  {
1143                      if (!isset($address['group'][$row['group_id']]))
1144                      {
1145                          if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1146                          {
1147                              $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
1148                              $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
1149                          }
1150                      }
1151  
1152                      if (isset($address['user'][$row['user_id']]))
1153                      {
1154                          $address['user'][$row['user_id']]['in_group'] = $row['group_id'];
1155                      }
1156                  }
1157                  $db->sql_freeresult($result);
1158              }
1159          }
1160  
1161          if (sizeof($address) && !$plaintext)
1162          {
1163              $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true);
1164  
1165              foreach ($address as $type => $adr_ary)
1166              {
1167                  foreach ($adr_ary as $id => $row)
1168                  {
1169                      $template->assign_block_vars($check_type . '_recipient', array(
1170                          'NAME'        => $row['name'],
1171                          'IS_GROUP'    => ($type == 'group'),
1172                          'IS_USER'    => ($type == 'user'),
1173                          'COLOUR'    => ($row['colour']) ? $row['colour'] : '',
1174                          'UG_ID'        => $id,
1175                          'U_VIEW'    => ($type == 'user') ? (($id != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $id) : '') : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $id),
1176                          'TYPE'        => $type)
1177                      );
1178                  }
1179              }
1180          }
1181  
1182          $addresses[$check_type] = $address;
1183      }
1184  
1185      return $addresses;
1186  }
1187  
1188  /**
1189  * Get folder status
1190  */
1191  function get_folder_status($folder_id, $folder)
1192  {
1193      global $db, $user, $config;
1194  
1195      if (isset($folder[$folder_id]))
1196      {
1197          $folder = $folder[$folder_id];
1198      }
1199      else
1200      {
1201          return false;
1202      }
1203  
1204      $return = array(
1205          'folder_name'    => $folder['folder_name'], 
1206          'cur'            => $folder['num_messages'],
1207          'remaining'        => $user->data['message_limit'] - $folder['num_messages'],
1208          'max'            => $user->data['message_limit'],
1209          'percent'        => ($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100,
1210      );
1211  
1212      $return['message']    = sprintf($user->lang['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']);
1213  
1214      return $return;
1215  }
1216  
1217  //
1218  // COMPOSE MESSAGES
1219  //
1220  
1221  /**
1222  * Submit PM
1223  */
1224  function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = true)
1225  {
1226      global $db, $auth, $config, $phpEx, $template, $user;
1227  
1228      // We do not handle erasing pms here
1229      if ($mode == 'delete')
1230      {
1231          return false;
1232      }
1233  
1234      $current_time = time();
1235  
1236      // Collect some basic informations about which tables and which rows to update/insert
1237      $sql_data = array();
1238      $root_level = 0;
1239  
1240      // Recipient Informations
1241      $recipients = $to = $bcc = array();
1242  
1243      if ($mode != 'edit')
1244      {
1245          // Build Recipient List
1246          // u|g => array($user_id => 'to'|'bcc')
1247          $_types = array('u', 'g');
1248          foreach ($_types as $ug_type)
1249          {
1250              if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
1251              {
1252                  foreach ($data['address_list'][$ug_type] as $id => $field)
1253                  {
1254                      $id = (int) $id;
1255  
1256                      // Do not rely on the address list being "valid"
1257                      if (!$id || ($ug_type == 'u' && $id == ANONYMOUS))
1258                      {
1259                          continue;
1260                      }
1261  
1262                      $field = ($field == 'to') ? 'to' : 'bcc';
1263                      if ($ug_type == 'u')
1264                      {
1265                          $recipients[$id] = $field;
1266                      }
1267                      ${$field}[] = $ug_type . '_' . $id;
1268                  }
1269              }
1270          }
1271  
1272          if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
1273          {
1274              $sql = 'SELECT group_id, user_id
1275                  FROM ' . USER_GROUP_TABLE . '
1276                  WHERE ' . $db->sql_in_set('group_id', array_keys($data['address_list']['g'])) . '
1277                      AND user_pending = 0';
1278              $result = $db->sql_query($sql);
1279      
1280              while ($row = $db->sql_fetchrow($result))
1281              {
1282                  $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
1283                  $recipients[$row['user_id']] = $field;
1284              }
1285              $db->sql_freeresult($result);
1286          }
1287  
1288          if (!sizeof($recipients))
1289          {
1290              trigger_error('NO_RECIPIENT');
1291          }
1292      }
1293  
1294      $sql = '';
1295  
1296      switch ($mode)
1297      {
1298          case 'reply':
1299          case 'quote':
1300              $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id']; 
1301  
1302              // Set message_replied switch for this user
1303              $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
1304                  SET pm_replied = 1
1305                  WHERE user_id = ' . $data['from_user_id'] . '
1306                      AND msg_id = ' . $data['reply_from_msg_id'];
1307  
1308          // no break
1309  
1310          case 'forward':
1311          case 'post':
1312          case 'quotepost':
1313              $sql_data = array(
1314                  'root_level'        => $root_level,
1315                  'author_id'            => $data['from_user_id'],
1316                  'icon_id'            => $data['icon_id'], 
1317                  'author_ip'            => $data['from_user_ip'],
1318                  'message_time'        => $current_time,
1319                  'enable_bbcode'        => $data['enable_bbcode'],
1320                  'enable_smilies'    => $data['enable_smilies'],
1321                  'enable_magic_url'    => $data['enable_urls'],
1322                  'enable_sig'        => $data['enable_sig'],
1323                  'message_subject'    => $subject,
1324                  'message_text'        => $data['message'],
1325                  'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
1326                  'bbcode_bitfield'    => $data['bbcode_bitfield'],
1327                  'bbcode_uid'        => $data['bbcode_uid'],
1328                  'to_address'        => implode(':', $to),
1329                  'bcc_address'        => implode(':', $bcc)
1330              );
1331          break;
1332  
1333          case 'edit':
1334              $sql_data = array(
1335                  'icon_id'            => $data['icon_id'],
1336                  'message_edit_time'    => $current_time,
1337                  'enable_bbcode'        => $data['enable_bbcode'],
1338                  'enable_smilies'    => $data['enable_smilies'],
1339                  'enable_magic_url'    => $data['enable_urls'],
1340                  'enable_sig'        => $data['enable_sig'],
1341                  'message_subject'    => $subject,
1342                  'message_text'        => $data['message'],
1343                  'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
1344                  'bbcode_bitfield'    => $data['bbcode_bitfield'],
1345                  'bbcode_uid'        => $data['bbcode_uid']
1346              );
1347          break;
1348      }
1349  
1350      if (sizeof($sql_data))
1351      {
1352          $query = '';
1353  
1354          if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
1355          {
1356              $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
1357              $data['msg_id'] = $db->sql_nextid();
1358          }
1359          else if ($mode == 'edit')
1360          {
1361              $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' 
1362                  SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . ' 
1363                  WHERE msg_id = ' . $data['msg_id'];
1364              $db->sql_query($sql);
1365          }
1366      }
1367  
1368      if ($mode != 'edit')
1369      {
1370          $db->sql_transaction('begin');
1371  
1372          if ($sql)
1373          {
1374              $db->sql_query($sql);
1375          }
1376          unset($sql);
1377  
1378          $sql_ary = array();
1379          foreach ($recipients as $user_id => $type)
1380          {
1381              $sql_ary[] = array(
1382                  'msg_id'        => (int) $data['msg_id'],
1383                  'user_id'        => (int) $user_id,
1384                  'author_id'        => (int) $data['from_user_id'],
1385                  'folder_id'        => PRIVMSGS_NO_BOX,
1386                  'pm_new'        => 1,
1387                  'pm_unread'        => 1,
1388                  'pm_forwarded'    => ($mode == 'forward') ? 1 : 0
1389              );
1390          }
1391  
1392          $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
1393  
1394          $sql = 'UPDATE ' . USERS_TABLE . ' 
1395              SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
1396              WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
1397          $db->sql_query($sql);
1398  
1399          // Put PM into outbox
1400          if ($put_in_outbox)
1401          {
1402              $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1403                  'msg_id'        => (int) $data['msg_id'],
1404                  'user_id'        => (int) $data['from_user_id'],
1405                  'author_id'        => (int) $data['from_user_id'],
1406                  'folder_id'        => PRIVMSGS_OUTBOX,
1407                  'pm_new'        => 0,
1408                  'pm_unread'        => 0,
1409                  'pm_forwarded'    => ($mode == 'forward') ? 1 : 0))
1410              );
1411          }
1412  
1413          $db->sql_transaction('commit');
1414      }
1415  
1416      // Set user last post time
1417      if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post')
1418      {
1419          $sql = 'UPDATE ' . USERS_TABLE . "
1420              SET user_lastpost_time = $current_time
1421              WHERE user_id = " . $data['from_user_id'];
1422          $db->sql_query($sql);
1423      }
1424  
1425      $db->sql_transaction('begin');
1426  
1427      // Submit Attachments
1428      if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
1429      {
1430          $space_taken = $files_added = 0;
1431          $orphan_rows = array();
1432  
1433          foreach ($data['attachment_data'] as $pos => $attach_row)
1434          {
1435              $orphan_rows[(int) $attach_row['attach_id']] = array();
1436          }
1437  
1438          if (sizeof($orphan_rows))
1439          {
1440              $sql = 'SELECT attach_id, filesize, physical_filename
1441                  FROM ' . ATTACHMENTS_TABLE . '
1442                  WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
1443                      AND in_message = 1
1444                      AND is_orphan = 1
1445                      AND poster_id = ' . $user->data['user_id'];
1446              $result = $db->sql_query($sql);
1447  
1448              $orphan_rows = array();
1449              while ($row = $db->sql_fetchrow($result))
1450              {
1451                  $orphan_rows[$row['attach_id']] = $row;
1452              }
1453              $db->sql_freeresult($result);
1454          }
1455  
1456          foreach ($data['attachment_data'] as $pos => $attach_row)
1457          {
1458              if ($attach_row['is_orphan'] && !in_array($attach_row['attach_id'], array_keys($orphan_rows)))
1459              {
1460                  continue;
1461              }
1462  
1463              if (!$attach_row['is_orphan'])
1464              {
1465                  // update entry in db if attachment already stored in db and filespace
1466                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
1467                      SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
1468                      WHERE attach_id = " . (int) $attach_row['attach_id'] . '
1469                          AND is_orphan = 0';
1470                  $db->sql_query($sql);
1471              }
1472              else
1473              {
1474                  // insert attachment into db
1475                  if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
1476                  {
1477                      continue;
1478                  }
1479  
1480                  $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
1481                  $files_added++;
1482  
1483                  $attach_sql = array(
1484                      'post_msg_id'        => $data['msg_id'],
1485                      'topic_id'            => 0,
1486                      'is_orphan'            => 0,
1487                      'poster_id'            => $data['from_user_id'],
1488                      'attach_comment'    => $attach_row['attach_comment'],
1489                  );
1490  
1491                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
1492                      WHERE attach_id = ' . $attach_row['attach_id'] . '
1493                          AND is_orphan = 1
1494                          AND poster_id = ' . $user->data['user_id'];
1495                  $db->sql_query($sql);
1496              }
1497          }
1498  
1499          if ($space_taken && $files_added)
1500          {
1501              set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
1502              set_config('num_files', $config['num_files'] + $files_added, true);
1503          }
1504      }
1505  
1506      $db->sql_transaction('commit');
1507  
1508      // Delete draft if post was loaded...
1509      $draft_id = request_var('draft_loaded', 0);
1510      if ($draft_id)
1511      {
1512          $sql = 'DELETE FROM ' . DRAFTS_TABLE . " 
1513              WHERE draft_id = $draft_id 
1514                  AND user_id = " . $data['from_user_id'];
1515          $db->sql_query($sql);
1516      }
1517  
1518      // Send Notifications
1519      if ($mode != 'edit')
1520      {
1521          pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']);
1522      }
1523  
1524      return $data['msg_id'];
1525  }
1526  
1527  /**
1528  * PM Notification
1529  */
1530  function pm_notification($mode, $author, $recipients, $subject, $message)
1531  {
1532      global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
1533  
1534      $subject = censor_text($subject);
1535  
1536      unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]);
1537  
1538      if (!sizeof($recipients))
1539      {
1540          return;
1541      }
1542  
1543      // Get banned User ID's
1544      $sql = 'SELECT ban_userid 
1545          FROM ' . BANLIST_TABLE . '
1546          WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . '
1547              AND ban_exclude = 0';
1548      $result = $db->sql_query($sql);
1549  
1550      while ($row = $db->sql_fetchrow($result))
1551      {
1552          unset($recipients[$row['ban_userid']]);
1553      }
1554      $db->sql_freeresult($result);
1555  
1556      if (!sizeof($recipients))
1557      {
1558          return;
1559      }
1560  
1561      $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber 
1562          FROM ' . USERS_TABLE . '
1563          WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients)));
1564      $result = $db->sql_query($sql);
1565  
1566      $msg_list_ary = array();
1567      while ($row = $db->sql_fetchrow($result))
1568      {
1569          if ($row['user_notify_pm'] == 1 && trim($row['user_email']))
1570          {
1571              $msg_list_ary[] = array(
1572                  'method'    => $row['user_notify_type'],
1573                  'email'        => $row['user_email'],
1574                  'jabber'    => $row['user_jabber'],
1575                  'name'        => $row['username'],
1576                  'lang'        => $row['user_lang']
1577              );
1578          }
1579      }
1580      $db->sql_freeresult($result);
1581  
1582      if (!sizeof($msg_list_ary))
1583      {
1584          return;
1585      }
1586  
1587      include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
1588      $messenger = new messenger();
1589  
1590      foreach ($msg_list_ary as $pos => $addr)
1591      {
1592          $messenger->template('privmsg_notify', $addr['lang']);
1593  
1594          $messenger->replyto($config['board_email']);
1595          $messenger->to($addr['email'], $addr['name']);
1596          $messenger->im($addr['jabber'], $addr['name']);
1597  
1598          $messenger->assign_vars(array(
1599              'SUBJECT'        => htmlspecialchars_decode($subject),
1600              'AUTHOR_NAME'    => htmlspecialchars_decode($author),
1601              'USERNAME'        => htmlspecialchars_decode($addr['name']),
1602  
1603              'U_INBOX'        => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox")
1604          );
1605  
1606          $messenger->send($addr['method']);
1607          $messenger->reset();
1608      }
1609      unset($msg_list_ary);
1610  
1611      $messenger->save_queue();
1612  
1613      unset($messenger);
1614  }
1615  
1616  ?>


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6