Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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

ucp_pm_compose.php

Zuletzt modifiziert: 01.05.2026, 11:25 - Dateigröße: 52.58 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  * @ignore
0016  */
0017  if (!defined('IN_PHPBB'))
0018  {
0019      exit;
0020  }
0021   
0022  /**
0023  * Compose private message
0024  * Called from ucp_pm with mode == 'compose'
0025  */
0026  function compose_pm($id, $mode, $action, $user_folders = array())
0027  {
0028      global $template, $db, $auth, $user, $cache;
0029      global $phpbb_root_path, $phpEx, $config, $language;
0030      global $request, $phpbb_dispatcher, $phpbb_container;
0031   
0032      // Damn php and globals - i know, this is horrible
0033      // Needed for handle_message_list_actions()
0034      global $refresh, $submit, $preview;
0035   
0036      if (!function_exists('generate_smilies'))
0037      {
0038          include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
0039      }
0040   
0041      if (!function_exists('display_custom_bbcodes'))
0042      {
0043          include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
0044      }
0045   
0046      if (!class_exists('parse_message'))
0047      {
0048          include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
0049      }
0050   
0051      if (!$action)
0052      {
0053          $action = 'post';
0054      }
0055      add_form_key('ucp_pm_compose');
0056   
0057      // Grab only parameters needed here
0058      $to_user_id        = $request->variable('u', 0);
0059      $to_group_id    = $request->variable('g', 0);
0060      $msg_id            = $request->variable('p', 0);
0061      $draft_id        = $request->variable('d', 0);
0062   
0063      // Reply to all triggered (quote/reply)
0064      $reply_to_all    = $request->variable('reply_to_all', 0);
0065   
0066      $address_list    = $request->variable('address_list', array('' => array(0 => '')));
0067   
0068      $preview    = (isset($_POST['preview'])) ? true : false;
0069      $save        = (isset($_POST['save'])) ? true : false;
0070      $load        = (isset($_POST['load'])) ? true : false;
0071      $cancel        = (isset($_POST['cancel']) && !isset($_POST['save'])) ? true : false;
0072      $delete        = (isset($_POST['delete'])) ? true : false;
0073   
0074      $remove_u    = (isset($_REQUEST['remove_u'])) ? true : false;
0075      $remove_g    = (isset($_REQUEST['remove_g'])) ? true : false;
0076      $add_to        = (isset($_REQUEST['add_to'])) ? true : false;
0077      $add_bcc    = (isset($_REQUEST['add_bcc'])) ? true : false;
0078   
0079      $refresh    = isset($_POST['add_file']) || isset($_POST['delete_file']) || $save || $load
0080          || $remove_u || $remove_g || $add_to || $add_bcc;
0081      $submit = $request->is_set_post('post') && !$refresh && !$preview;
0082   
0083      $action        = ($delete && !$preview && !$refresh && $submit) ? 'delete' : $action;
0084      $select_single = ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? false : true;
0085   
0086      $error = array();
0087      $current_time = time();
0088   
0089      /** @var \phpbb\group\helper $group_helper */
0090      $group_helper = $phpbb_container->get('group_helper');
0091   
0092      // Was cancel pressed? If so then redirect to the appropriate page
0093      if ($cancel)
0094      {
0095          if ($msg_id)
0096          {
0097              redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=view&amp;action=view_message&amp;p=' . $msg_id));
0098          }
0099          redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'));
0100      }
0101   
0102      // Since viewtopic.php language entries are used in several modes,
0103      // we include the language file here
0104      $user->add_lang('viewtopic');
0105   
0106      /**
0107      * Modify the default vars before composing a PM
0108      *
0109      * @event core.ucp_pm_compose_modify_data
0110      * @var    int        msg_id                    post_id in the page request
0111      * @var    int        to_user_id                The id of whom the message is to
0112      * @var    int        to_group_id                The id of the group the message is to
0113      * @var    bool    submit                    Whether the form has been submitted
0114      * @var    bool    preview                    Whether the user is previewing the PM or not
0115      * @var    string    action                    One of: post, reply, quote, forward, quotepost, edit, delete, smilies
0116      * @var    bool    delete                    Whether the user is deleting the PM
0117      * @var    int        reply_to_all            Value of reply_to_all request variable.
0118      * @since 3.1.4-RC1
0119      */
0120      $vars = array(
0121          'msg_id',
0122          'to_user_id',
0123          'to_group_id',
0124          'submit',
0125          'preview',
0126          'action',
0127          'delete',
0128          'reply_to_all',
0129      );
0130      extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_data', compact($vars)));
0131   
0132      // Output PM_TO box if message composing
0133      if ($action != 'edit')
0134      {
0135          // Add groups to PM box
0136          if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group'))
0137          {
0138              $sql = 'SELECT g.group_id, g.group_name, g.group_type, g.group_colour
0139                  FROM ' . GROUPS_TABLE . ' g';
0140   
0141              if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel'))
0142              {
0143                  $sql .= ' LEFT JOIN ' . USER_GROUP_TABLE . ' ug
0144                      ON (
0145                          g.group_id = ug.group_id
0146                          AND ug.user_id = ' . $user->data['user_id'] . '
0147                          AND ug.user_pending = 0
0148                      )
0149                      WHERE (g.group_type <> ' . GROUP_HIDDEN . ' OR ug.user_id = ' . $user->data['user_id'] . ')';
0150              }
0151   
0152              $sql .= ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? ' WHERE ' : ' AND ';
0153   
0154              $sql .= 'g.group_receive_pm = 1
0155                  ORDER BY g.group_type DESC, g.group_name ASC';
0156              $result = $db->sql_query($sql);
0157   
0158              $group_options = '';
0159              while ($row = $db->sql_fetchrow($result))
0160              {
0161                  $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . ($row['group_colour'] ? ' style="color: #' . $row['group_colour'] . '"' : '') . '>' . $group_helper->get_name($row['group_name']) . '</option>';
0162              }
0163              $db->sql_freeresult($result);
0164          }
0165   
0166          $template->assign_vars(array(
0167              'S_SHOW_PM_BOX'        => true,
0168              'S_ALLOW_MASS_PM'    => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? true : false,
0169              'S_GROUP_OPTIONS'    => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) ? $group_options : '',
0170              'U_FIND_USERNAME'    => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=searchuser&amp;form=postform&amp;field=username_list&amp;select_single=" . (int) $select_single),
0171          ));
0172      }
0173   
0174      $sql = '';
0175      $folder_id = 0;
0176   
0177      // What is all this following SQL for? Well, we need to know
0178      // some basic information in all cases before we do anything.
0179      switch ($action)
0180      {
0181          case 'post':
0182              if (!$auth->acl_get('u_sendpm'))
0183              {
0184                  send_status_line(403, 'Forbidden');
0185                  trigger_error('NO_AUTH_SEND_MESSAGE');
0186              }
0187          break;
0188   
0189          case 'reply':
0190          case 'quote':
0191          case 'forward':
0192          case 'quotepost':
0193              if (!$msg_id)
0194              {
0195                  trigger_error('NO_MESSAGE');
0196              }
0197   
0198              if (!$auth->acl_get('u_sendpm'))
0199              {
0200                  send_status_line(403, 'Forbidden');
0201                  trigger_error('NO_AUTH_SEND_MESSAGE');
0202              }
0203   
0204              if ($action == 'quotepost')
0205              {
0206                  $sql = 'SELECT p.post_id as msg_id, p.forum_id, p.post_text as message_text, p.poster_id as author_id, p.post_time as message_time, p.post_visibility as post_visibility, p.bbcode_bitfield, p.bbcode_uid, p.enable_sig, p.enable_smilies, p.enable_magic_url, t.topic_title as message_subject, u.username as quote_username
0207                      FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . " u
0208                      WHERE p.post_id = $msg_id
0209                          AND t.topic_id = p.topic_id
0210                          AND u.user_id = p.poster_id";
0211              }
0212              else
0213              {
0214                  $sql = 'SELECT t.folder_id, p.*, u.username as quote_username
0215                      FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u
0216                      WHERE t.user_id = ' . $user->data['user_id'] . "
0217                          AND p.author_id = u.user_id
0218                          AND t.msg_id = p.msg_id
0219                          AND p.msg_id = $msg_id";
0220              }
0221          break;
0222   
0223          case 'edit':
0224              if (!$msg_id)
0225              {
0226                  trigger_error('NO_MESSAGE');
0227              }
0228   
0229              // check for outbox (not read) status, we do not allow editing if one user already having the message
0230              $sql = 'SELECT p.*, t.folder_id
0231                  FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
0232                  WHERE t.user_id = ' . $user->data['user_id'] . '
0233                      AND t.folder_id = ' . PRIVMSGS_OUTBOX . "
0234                      AND t.msg_id = $msg_id
0235                      AND t.msg_id = p.msg_id";
0236          break;
0237   
0238          case 'delete':
0239              if (!$auth->acl_get('u_pm_delete'))
0240              {
0241                  send_status_line(403, 'Forbidden');
0242                  trigger_error('NO_AUTH_DELETE_MESSAGE');
0243              }
0244   
0245              if (!$msg_id)
0246              {
0247                  trigger_error('NO_MESSAGE');
0248              }
0249   
0250              $sql = 'SELECT msg_id, pm_unread, pm_new, author_id, folder_id
0251                  FROM ' . PRIVMSGS_TO_TABLE . '
0252                  WHERE user_id = ' . $user->data['user_id'] . "
0253                      AND msg_id = $msg_id";
0254          break;
0255   
0256          case 'smilies':
0257              generate_smilies('window', 0);
0258          break;
0259   
0260          default:
0261              trigger_error('NO_ACTION_MODE', E_USER_ERROR);
0262          break;
0263      }
0264   
0265      if ($action == 'forward' && (!$config['forward_pm'] || !$auth->acl_get('u_pm_forward')))
0266      {
0267          send_status_line(403, 'Forbidden');
0268          trigger_error('NO_AUTH_FORWARD_MESSAGE');
0269      }
0270   
0271      if ($action == 'edit' && !$auth->acl_get('u_pm_edit'))
0272      {
0273          send_status_line(403, 'Forbidden');
0274          trigger_error('NO_AUTH_EDIT_MESSAGE');
0275      }
0276   
0277      if ($sql)
0278      {
0279          /**
0280          * Alter sql query to get message for user to write the PM
0281          *
0282          * @event core.ucp_pm_compose_compose_pm_basic_info_query_before
0283          * @var    string    sql                        String with the query to be executed
0284          * @var    int        msg_id                    topic_id in the page request
0285          * @var    int        to_user_id                The id of whom the message is to
0286          * @var    int        to_group_id                The id of the group whom the message is to
0287          * @var    bool    submit                    Whether the user is sending the PM or not
0288          * @var    bool    preview                    Whether the user is previewing the PM or not
0289          * @var    string    action                    One of: post, reply, quote, forward, quotepost, edit, delete, smilies
0290          * @var    bool    delete                    Whether the user is deleting the PM
0291          * @var    int        reply_to_all            Value of reply_to_all request variable.
0292          * @since 3.1.0-RC5
0293          * @changed 3.2.0-a1 Removed undefined variables
0294          */
0295          $vars = array(
0296              'sql',
0297              'msg_id',
0298              'to_user_id',
0299              'to_group_id',
0300              'submit',
0301              'preview',
0302              'action',
0303              'delete',
0304              'reply_to_all',
0305          );
0306          extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_compose_pm_basic_info_query_before', compact($vars)));
0307   
0308          $result = $db->sql_query($sql);
0309          $post = $db->sql_fetchrow($result);
0310          $db->sql_freeresult($result);
0311   
0312          /**
0313          * Alter the row of the post being quoted when composing a private message
0314          *
0315          * @event core.ucp_pm_compose_compose_pm_basic_info_query_after
0316          * @var    array    post            Array with data of the post being quoted
0317          * @var    int        msg_id            topic_id in the page request
0318          * @var    int        to_user_id        The id of whom the message is to
0319          * @var    int        to_group_id        The id of the group whom the message is to
0320          * @var    bool    submit            Whether the user is sending the PM or not
0321          * @var    bool    preview            Whether the user is previewing the PM or not
0322          * @var    string    action            One of: post, reply, quote, forward, quotepost, edit, delete, smilies
0323          * @var    bool    delete            Whether the user is deleting the PM
0324          * @var    int        reply_to_all    Value of reply_to_all request variable.
0325          * @since 3.2.10-RC1
0326          * @since 3.3.1-RC1
0327          */
0328          $vars = [
0329              'post',
0330              'msg_id',
0331              'to_user_id',
0332              'to_group_id',
0333              'submit',
0334              'preview',
0335              'action',
0336              'delete',
0337              'reply_to_all',
0338          ];
0339          extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_compose_pm_basic_info_query_after', compact($vars)));
0340   
0341          if (!$post)
0342          {
0343              // If editing it could be the recipient already read the message...
0344              if ($action == 'edit')
0345              {
0346                  $sql = 'SELECT p.*, t.folder_id
0347                      FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
0348                      WHERE t.user_id = ' . $user->data['user_id'] . "
0349                          AND t.msg_id = $msg_id
0350                          AND t.msg_id = p.msg_id";
0351                  $result = $db->sql_query($sql);
0352                  $post = $db->sql_fetchrow($result);
0353                  $db->sql_freeresult($result);
0354   
0355                  if ($post)
0356                  {
0357                      trigger_error('NO_EDIT_READ_MESSAGE');
0358                  }
0359              }
0360   
0361              trigger_error('NO_MESSAGE');
0362          }
0363   
0364          if ($action == 'quotepost')
0365          {
0366              if (($post['forum_id'] && !$auth->acl_get('f_read', $post['forum_id'])) || (!$post['forum_id'] && !$auth->acl_getf_global('f_read')))
0367              {
0368                  send_status_line(403, 'Forbidden');
0369                  trigger_error('NOT_AUTHORISED');
0370              }
0371   
0372              /* @var $phpbb_content_visibility \phpbb\content_visibility */
0373              $phpbb_content_visibility = $phpbb_container->get('content.visibility');
0374   
0375              if (!$phpbb_content_visibility->is_visible('post', $post['forum_id'], $post))
0376              {
0377                  trigger_error('NO_MESSAGE');
0378              }
0379   
0380              /**
0381              * Get the result of querying for the post to be quoted in the pm message
0382              *
0383              * @event core.ucp_pm_compose_quotepost_query_after
0384              * @var    string    sql                    The original SQL used in the query
0385              * @var    array    post                Associative array with the data of the quoted post
0386              * @var    array    msg_id                The post_id that was searched to get the message for quoting
0387              * @var    int        to_user_id            Users the message is sent to
0388              * @var    int        to_group_id            Groups the message is sent to
0389              * @var    bool    submit                Whether the user is sending the PM or not
0390              * @var    bool    preview                Whether the user is previewing the PM or not
0391              * @var    string    action                One of: post, reply, quote, forward, quotepost, edit, delete, smilies
0392              * @var    bool    delete                If deleting message
0393              * @var    int        reply_to_all        Value of reply_to_all request variable.
0394              * @since 3.1.0-RC5
0395              * @changed 3.2.0-a1 Removed undefined variables
0396              */
0397              $vars = array(
0398                  'sql',
0399                  'post',
0400                  'msg_id',
0401                  'to_user_id',
0402                  'to_group_id',
0403                  'submit',
0404                  'preview',
0405                  'action',
0406                  'delete',
0407                  'reply_to_all',
0408              );
0409              extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_quotepost_query_after', compact($vars)));
0410   
0411              // Passworded forum?
0412              if ($post['forum_id'])
0413              {
0414                  $sql = 'SELECT forum_id, forum_name, forum_password
0415                      FROM ' . FORUMS_TABLE . '
0416                      WHERE forum_id = ' . (int) $post['forum_id'];
0417                  $result = $db->sql_query($sql);
0418                  $forum_data = $db->sql_fetchrow($result);
0419                  $db->sql_freeresult($result);
0420   
0421                  if (!empty($forum_data['forum_password']))
0422                  {
0423                      login_forum_box($forum_data);
0424                  }
0425              }
0426          }
0427   
0428          $msg_id            = (int) $post['msg_id'];
0429          $folder_id        = (isset($post['folder_id'])) ? $post['folder_id'] : 0;
0430          $message_text    = (isset($post['message_text'])) ? $post['message_text'] : '';
0431   
0432          if ((!$post['author_id'] || ($post['author_id'] == ANONYMOUS && $action != 'delete')) && $msg_id)
0433          {
0434              trigger_error('NO_AUTHOR');
0435          }
0436   
0437          if ($action == 'quotepost')
0438          {
0439              // Decode text for message display
0440              decode_message($message_text, $post['bbcode_uid']);
0441          }
0442   
0443          if ($action != 'delete')
0444          {
0445              $enable_urls = $post['enable_magic_url'];
0446              $enable_sig = (isset($post['enable_sig'])) ? $post['enable_sig'] : 0;
0447   
0448              $message_attachment = (isset($post['message_attachment'])) ? $post['message_attachment'] : 0;
0449              $message_subject = $post['message_subject'];
0450              $message_time = $post['message_time'];
0451              $bbcode_uid = $post['bbcode_uid'];
0452   
0453              $quote_username = (isset($post['quote_username'])) ? $post['quote_username'] : '';
0454              $icon_id = (isset($post['icon_id'])) ? $post['icon_id'] : 0;
0455   
0456              if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !count($address_list) && !$refresh && !$submit && !$preview)
0457              {
0458                  // Add the original author as the recipient if quoting a post or only replying and not having checked "reply to all"
0459                  if ($action == 'quotepost' || !$reply_to_all)
0460                  {
0461                      $address_list = array('u' => array($post['author_id'] => 'to'));
0462                  }
0463                  else
0464                  {
0465                      // We try to include every previously listed member from the TO Header - Reply to all
0466                      $address_list = rebuild_header(array('to' => $post['to_address']));
0467   
0468                      // Add the author (if he is already listed then this is no shame (it will be overwritten))
0469                      $address_list['u'][$post['author_id']] = 'to';
0470   
0471                      // Now, make sure the user itself is not listed. ;)
0472                      if (isset($address_list['u'][$user->data['user_id']]))
0473                      {
0474                          unset($address_list['u'][$user->data['user_id']]);
0475                      }
0476                  }
0477              }
0478              else if ($action == 'edit' && !count($address_list) && !$refresh && !$submit && !$preview)
0479              {
0480                  // Rebuild TO and BCC Header
0481                  $address_list = rebuild_header(array('to' => $post['to_address'], 'bcc' => $post['bcc_address']));
0482              }
0483   
0484              if ($action == 'quotepost')
0485              {
0486                  $check_value = 0;
0487              }
0488              else
0489              {
0490                  $check_value = (($post['enable_bbcode']+1) << 8) + (($post['enable_smilies']+1) << 4) + (($enable_urls+1) << 2) + (($post['enable_sig']+1) << 1);
0491              }
0492          }
0493      }
0494      else
0495      {
0496          $message_attachment = 0;
0497          $message_text = $message_subject = '';
0498   
0499          /**
0500          * Predefine message text and subject
0501          *
0502          * @event core.ucp_pm_compose_predefined_message
0503          * @var    string    message_text    Message text
0504          * @var    string    message_subject    Messate subject
0505          * @since 3.1.11-RC1
0506          */
0507          $vars = array('message_text', 'message_subject');
0508          extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_predefined_message', compact($vars)));
0509   
0510          if ($to_user_id && $to_user_id != ANONYMOUS && $action == 'post')
0511          {
0512              $address_list['u'][$to_user_id] = 'to';
0513          }
0514          else if ($to_group_id && $action == 'post')
0515          {
0516              $address_list['g'][$to_group_id] = 'to';
0517          }
0518          $check_value = 0;
0519      }
0520   
0521      if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group')))
0522      {
0523          send_status_line(403, 'Forbidden');
0524          trigger_error('NO_AUTH_GROUP_MESSAGE');
0525      }
0526   
0527      if ($action == 'edit' && !$refresh && !$preview && !$submit)
0528      {
0529          if (!($message_time > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']))
0530          {
0531              trigger_error('CANNOT_EDIT_MESSAGE_TIME');
0532          }
0533      }
0534   
0535      if ($action == 'post')
0536      {
0537          $template->assign_var('S_NEW_MESSAGE', true);
0538      }
0539   
0540      if (!isset($icon_id))
0541      {
0542          $icon_id = 0;
0543      }
0544   
0545      /* @var $plupload \phpbb\plupload\plupload */
0546      $plupload = $phpbb_container->get('plupload');
0547      $message_parser = new parse_message();
0548      $message_parser->set_plupload($plupload);
0549   
0550      $message_parser->message = ($action == 'reply') ? '' : $message_text;
0551      unset($message_text);
0552   
0553      $s_action = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=$mode&amp;action=$action", true, $user->session_id);
0554      $s_action .= (($folder_id) ? "&amp;f=$folder_id" : '') . (($msg_id) ? "&amp;p=$msg_id" : '');
0555   
0556      // Delete triggered ?
0557      if ($action == 'delete')
0558      {
0559          // Folder id has been determined by the SQL Statement
0560          // $folder_id = $request->variable('f', PRIVMSGS_NO_BOX);
0561   
0562          // Do we need to confirm ?
0563          if (confirm_box(true))
0564          {
0565              delete_pm($user->data['user_id'], $msg_id, $folder_id);
0566   
0567              // jump to next message in "history"? nope, not for the moment. But able to be included later.
0568              $meta_info = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&amp;folder=$folder_id");
0569              $message = $user->lang['MESSAGE_DELETED'];
0570   
0571              meta_refresh(3, $meta_info);
0572              $message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>');
0573              trigger_error($message);
0574          }
0575          else
0576          {
0577              $s_hidden_fields = array(
0578                  'p'            => $msg_id,
0579                  'f'            => $folder_id,
0580                  'action'    => 'delete'
0581              );
0582   
0583              // "{$phpbb_root_path}ucp.$phpEx?i=pm&amp;mode=compose"
0584              confirm_box(false, 'DELETE_MESSAGE', build_hidden_fields($s_hidden_fields));
0585          }
0586   
0587          redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=view&amp;action=view_message&amp;p=' . $msg_id));
0588      }
0589   
0590      // Get maximum number of allowed recipients
0591      $max_recipients = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'max_recipients');
0592   
0593      // If it is 0, there is no limit set and we use the maximum value within the config.
0594      $max_recipients = (!$max_recipients) ? $config['pm_max_recipients'] : $max_recipients;
0595   
0596      // If this is a quote/reply "to all"... we may increase the max_recpients to the number of original recipients
0597      if (($action == 'reply' || $action == 'quote') && $max_recipients && $reply_to_all)
0598      {
0599          // We try to include every previously listed member from the TO Header
0600          $list = rebuild_header(array('to' => $post['to_address']));
0601   
0602          // Can be an empty array too ;)
0603          $list = (!empty($list['u'])) ? $list['u'] : array();
0604          $list[$post['author_id']] = 'to';
0605   
0606          if (isset($list[$user->data['user_id']]))
0607          {
0608              unset($list[$user->data['user_id']]);
0609          }
0610   
0611          $max_recipients = ($max_recipients < count($list)) ? count($list) : $max_recipients;
0612   
0613          unset($list);
0614      }
0615   
0616      // Handle User/Group adding/removing
0617      handle_message_list_actions($address_list, $error, $remove_u, $remove_g, $add_to, $add_bcc);
0618   
0619      // Check mass pm to group permission
0620      if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group')) && !empty($address_list['g']))
0621      {
0622          $address_list = array();
0623          $error[] = $user->lang['NO_AUTH_GROUP_MESSAGE'];
0624      }
0625   
0626      // Check mass pm to users permission
0627      if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm')) && num_recipients($address_list) > 1)
0628      {
0629          $address_list = get_recipients($address_list, 1);
0630          $error[] = $user->lang('TOO_MANY_RECIPIENTS', 1);
0631      }
0632   
0633      // Check for too many recipients
0634      if (!empty($address_list['u']) && $max_recipients && count($address_list['u']) > $max_recipients)
0635      {
0636          $address_list = get_recipients($address_list, $max_recipients);
0637          $error[] = $user->lang('TOO_MANY_RECIPIENTS', $max_recipients);
0638      }
0639   
0640      // Always check if the submitted attachment data is valid and belongs to the user.
0641      // Further down (especially in submit_post()) we do not check this again.
0642      $message_parser->get_submitted_attachment_data();
0643   
0644      if ($message_attachment && !$submit && !$refresh && !$preview && $action == 'edit')
0645      {
0646          // Do not change to SELECT *
0647          $sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename, filesize
0648              FROM ' . ATTACHMENTS_TABLE . "
0649              WHERE post_msg_id = $msg_id
0650                  AND in_message = 1
0651                  AND is_orphan = 0
0652              ORDER BY filetime DESC";
0653          $result = $db->sql_query($sql);
0654          $message_parser->attachment_data = array_merge($message_parser->attachment_data, $db->sql_fetchrowset($result));
0655          $db->sql_freeresult($result);
0656      }
0657   
0658      if (!in_array($action, array('quote', 'edit', 'delete', 'forward')))
0659      {
0660          $enable_sig        = ($config['allow_sig'] && $config['allow_sig_pm'] && $auth->acl_get('u_sig') && $user->optionget('attachsig'));
0661          $enable_smilies    = ($config['allow_smilies'] && $auth->acl_get('u_pm_smilies') && $user->optionget('smilies'));
0662          $enable_bbcode    = ($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode') && $user->optionget('bbcode'));
0663          $enable_urls    = true;
0664      }
0665   
0666      $drafts = false;
0667   
0668      // User own some drafts?
0669      if ($auth->acl_get('u_savedrafts') && $action != 'delete')
0670      {
0671          $sql = 'SELECT draft_id
0672              FROM ' . DRAFTS_TABLE . '
0673              WHERE forum_id = 0
0674                  AND topic_id = 0
0675                  AND user_id = ' . $user->data['user_id'] .
0676                  (($draft_id) ? " AND draft_id <> $draft_id" : '');
0677          $result = $db->sql_query_limit($sql, 1);
0678          $row = $db->sql_fetchrow($result);
0679          $db->sql_freeresult($result);
0680   
0681          if ($row)
0682          {
0683              $drafts = true;
0684          }
0685      }
0686   
0687      if ($action == 'edit')
0688      {
0689          $message_parser->bbcode_uid = $bbcode_uid;
0690      }
0691   
0692      $bbcode_status    = ($config['allow_bbcode'] && $config['auth_bbcode_pm'] && $auth->acl_get('u_pm_bbcode')) ? true : false;
0693      $smilies_status    = ($config['allow_smilies'] && $config['auth_smilies_pm'] && $auth->acl_get('u_pm_smilies')) ? true : false;
0694      $img_status        = ($config['auth_img_pm'] && $auth->acl_get('u_pm_img')) ? true : false;
0695      $flash_status    = ($config['auth_flash_pm'] && $auth->acl_get('u_pm_flash')) ? true : false;
0696      $url_status        = ($config['allow_post_links']) ? true : false;
0697   
0698      /**
0699       * Event to override private message BBCode status indications
0700       *
0701       * @event core.ucp_pm_compose_modify_bbcode_status
0702       *
0703       * @var bool    bbcode_status    BBCode status
0704       * @var bool    smilies_status    Smilies status
0705       * @var bool    img_status        Image BBCode status
0706       * @var bool    flash_status    Flash BBCode status
0707       * @var bool    url_status        URL BBCode status
0708       * @since 3.3.3-RC1
0709       */
0710      $vars = [
0711          'bbcode_status',
0712          'smilies_status',
0713          'img_status',
0714          'flash_status',
0715          'url_status',
0716      ];
0717      extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_bbcode_status', compact($vars)));
0718   
0719      // Save Draft
0720      if ($save && $auth->acl_get('u_savedrafts'))
0721      {
0722          $subject = $request->variable('subject', '', true);
0723          $subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject;
0724          $message = $request->variable('message', '', true);
0725   
0726          /**
0727           * Replace Emojis and other 4bit UTF-8 chars not allowed by MySQL to UCR/NCR.
0728           * Using their Numeric Character Reference's Hexadecimal notation.
0729           */
0730          $subject = utf8_encode_ucr($subject);
0731   
0732          if ($subject && $message)
0733          {
0734              if (confirm_box(true))
0735              {
0736                  $message_parser->message = $message;
0737                  $message_parser->parse($bbcode_status, $url_status, $smilies_status, $img_status, $flash_status, true, $url_status);
0738   
0739                  $sql = 'INSERT INTO ' . DRAFTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
0740                      'user_id'        => $user->data['user_id'],
0741                      'topic_id'        => 0,
0742                      'forum_id'        => 0,
0743                      'save_time'        => $current_time,
0744                      'draft_subject'    => $subject,
0745                      'draft_message'    => $message_parser->message,
0746                      )
0747                  );
0748                  $db->sql_query($sql);
0749   
0750                  /** @var \phpbb\attachment\manager $attachment_manager */
0751                  $attachment_manager = $phpbb_container->get('attachment.manager');
0752                  $attachment_manager->delete('attach', array_column($message_parser->attachment_data, 'attach_id'));
0753   
0754                  $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&amp;mode=$mode");
0755   
0756                  meta_refresh(3, $redirect_url);
0757                  $message = $user->lang['DRAFT_SAVED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>');
0758   
0759                  trigger_error($message);
0760              }
0761              else
0762              {
0763                  $s_hidden_fields = build_hidden_fields(array(
0764                      'mode'        => $mode,
0765                      'action'    => $action,
0766                      'save'        => true,
0767                      'subject'    => $subject,
0768                      'message'    => $message,
0769                      'u'            => $to_user_id,
0770                      'g'            => $to_group_id,
0771                      'p'            => $msg_id,
0772                      'attachment_data' => $message_parser->attachment_data,
0773                  ));
0774                  $s_hidden_fields .= build_address_field($address_list);
0775   
0776                  confirm_box(false, 'SAVE_DRAFT', $s_hidden_fields);
0777              }
0778          }
0779          else
0780          {
0781              if (utf8_clean_string($subject) === '')
0782              {
0783                  $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT'];
0784              }
0785   
0786              if (utf8_clean_string($message) === '')
0787              {
0788                  $error[] = $user->lang['TOO_FEW_CHARS'];
0789              }
0790          }
0791   
0792          unset($subject, $message);
0793      }
0794   
0795      // Load Draft
0796      if ($draft_id && $auth->acl_get('u_savedrafts'))
0797      {
0798          $sql = 'SELECT draft_subject, draft_message
0799              FROM ' . DRAFTS_TABLE . "
0800              WHERE draft_id = $draft_id
0801                  AND topic_id = 0
0802                  AND forum_id = 0
0803                  AND user_id = " . $user->data['user_id'];
0804          $result = $db->sql_query_limit($sql, 1);
0805   
0806          if ($row = $db->sql_fetchrow($result))
0807          {
0808              $message_parser->message = $row['draft_message'];
0809              $message_subject = $row['draft_subject'];
0810   
0811              $template->assign_var('S_DRAFT_LOADED', true);
0812          }
0813          else
0814          {
0815              $draft_id = 0;
0816          }
0817          $db->sql_freeresult($result);
0818      }
0819   
0820      // Load Drafts
0821      if ($load && $drafts)
0822      {
0823          load_drafts(0, 0, $id, $action, $msg_id);
0824      }
0825   
0826      if ($submit || $preview || $refresh)
0827      {
0828          if (($submit || $preview) && !check_form_key('ucp_pm_compose'))
0829          {
0830              $error[] = $user->lang['FORM_INVALID'];
0831          }
0832          $subject = $request->variable('subject', '', true);
0833          $message_parser->message = $request->variable('message', '', true);
0834   
0835          $icon_id            = $request->variable('icon', 0);
0836   
0837          $enable_bbcode         = (!$bbcode_status || isset($_POST['disable_bbcode'])) ? false : true;
0838          $enable_smilies        = (!$smilies_status || isset($_POST['disable_smilies'])) ? false : true;
0839          $enable_urls         = (isset($_POST['disable_magic_url'])) ? 0 : 1;
0840          $enable_sig            = (!$config['allow_sig'] ||!$config['allow_sig_pm']) ? false : ((isset($_POST['attach_sig'])) ? true : false);
0841   
0842          /**
0843          * Modify private message
0844          *
0845          * @event core.ucp_pm_compose_modify_parse_before
0846          * @var    bool    enable_bbcode        Whether or not bbcode is enabled
0847          * @var    bool    enable_smilies        Whether or not smilies are enabled
0848          * @var    bool    enable_urls            Whether or not urls are enabled
0849          * @var    bool    enable_sig            Whether or not signature is enabled
0850          * @var    string    subject                PM subject text
0851          * @var    object    message_parser        The message parser object
0852          * @var    bool    submit                Whether or not the form has been sumitted
0853          * @var    bool    preview                Whether or not the signature is being previewed
0854          * @var    array    error                Any error strings
0855          * @since 3.1.10-RC1
0856          */
0857          $vars = array(
0858              'enable_bbcode',
0859              'enable_smilies',
0860              'enable_urls',
0861              'enable_sig',
0862              'subject',
0863              'message_parser',
0864              'submit',
0865              'preview',
0866              'error',
0867          );
0868          extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_parse_before', compact($vars)));
0869   
0870          // Parse Attachments - before checksum is calculated
0871          if ($message_parser->check_attachment_form_token($language, $request, 'ucp_pm_compose'))
0872          {
0873              $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true);
0874          }
0875   
0876          if (count($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc))
0877          {
0878              $error[] = implode('<br />', $message_parser->warn_msg);
0879              $message_parser->warn_msg = array();
0880          }
0881   
0882          // Parse message
0883          $message_parser->parse($enable_bbcode, ($config['allow_post_links']) ? $enable_urls : false, $enable_smilies, $img_status, $flash_status, true, $config['allow_post_links']);
0884   
0885          // On a refresh we do not care about message parsing errors
0886          if (count($message_parser->warn_msg) && !$refresh)
0887          {
0888              $error[] = implode('<br />', $message_parser->warn_msg);
0889          }
0890   
0891          if ($action != 'edit' && !$preview && !$refresh && $config['flood_interval'] && !$auth->acl_get('u_ignoreflood'))
0892          {
0893              // Flood check
0894              $last_post_time = $user->data['user_lastpost_time'];
0895   
0896              if ($last_post_time)
0897              {
0898                  if ($last_post_time && ($current_time - $last_post_time) < intval($config['flood_interval']))
0899                  {
0900                      $error[] = $user->lang['FLOOD_ERROR'];
0901                  }
0902              }
0903          }
0904   
0905          // Subject defined
0906          if ($submit)
0907          {
0908              if (utf8_clean_string($subject) === '')
0909              {
0910                  $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT'];
0911              }
0912   
0913              if (!count($address_list))
0914              {
0915                  $error[] = $user->lang['NO_RECIPIENT'];
0916              }
0917          }
0918   
0919          /**
0920          * Modify private message
0921          *
0922          * @event core.ucp_pm_compose_modify_parse_after
0923          * @var    bool    enable_bbcode        Whether or not bbcode is enabled
0924          * @var    bool    enable_smilies        Whether or not smilies are enabled
0925          * @var    bool    enable_urls            Whether or not urls are enabled
0926          * @var    bool    enable_sig            Whether or not signature is enabled
0927          * @var    string    subject                PM subject text
0928          * @var    object    message_parser        The message parser object
0929          * @var    bool    submit                Whether or not the form has been sumitted
0930          * @var    bool    preview                Whether or not the signature is being previewed
0931          * @var    array    error                Any error strings
0932          * @since 3.2.10-RC1
0933          * @since 3.3.1-RC1
0934          */
0935          $vars = [
0936              'enable_bbcode',
0937              'enable_smilies',
0938              'enable_urls',
0939              'enable_sig',
0940              'subject',
0941              'message_parser',
0942              'submit',
0943              'preview',
0944              'error',
0945          ];
0946          extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_parse_after', compact($vars)));
0947   
0948          // Store message, sync counters
0949          if (!count($error) && $submit)
0950          {
0951              $pm_data = array(
0952                  'msg_id'                => (int) $msg_id,
0953                  'from_user_id'            => $user->data['user_id'],
0954                  'from_user_ip'            => $user->ip,
0955                  'from_username'            => $user->data['username'],
0956                  'reply_from_root_level'    => (isset($post['root_level'])) ? (int) $post['root_level'] : 0,
0957                  'reply_from_msg_id'        => (int) $msg_id,
0958                  'icon_id'                => (int) $icon_id,
0959                  'enable_sig'            => (bool) $enable_sig,
0960                  'enable_bbcode'            => (bool) $enable_bbcode,
0961                  'enable_smilies'        => (bool) $enable_smilies,
0962                  'enable_urls'            => (bool) $enable_urls,
0963                  'bbcode_bitfield'        => $message_parser->bbcode_bitfield,
0964                  'bbcode_uid'            => $message_parser->bbcode_uid,
0965                  'message'                => $message_parser->message,
0966                  'attachment_data'        => $message_parser->attachment_data,
0967                  'filename_data'            => $message_parser->filename_data,
0968                  'address_list'            => $address_list
0969              );
0970   
0971              /**
0972               * Replace Emojis and other 4bit UTF-8 chars not allowed by MySQL to UCR/NCR.
0973               * Using their Numeric Character Reference's Hexadecimal notation.
0974               */
0975              $subject = utf8_encode_ucr($subject);
0976   
0977              // ((!$message_subject) ? $subject : $message_subject)
0978              $msg_id = submit_pm($action, $subject, $pm_data);
0979   
0980              $return_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=view&amp;p=' . $msg_id);
0981              $inbox_folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox');
0982              $outbox_folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=outbox');
0983   
0984              $folder_url = '';
0985              if (($folder_id > 0) && isset($user_folders[$folder_id]))
0986              {
0987                  $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $folder_id);
0988              }
0989   
0990              $return_box_url = ($action === 'post' || $action === 'edit') ? $outbox_folder_url : $inbox_folder_url;
0991              $return_box_lang = ($action === 'post' || $action === 'edit') ? 'PM_OUTBOX' : 'PM_INBOX';
0992   
0993              $save_message = ($action === 'edit') ? $user->lang['MESSAGE_EDITED'] : $user->lang['MESSAGE_STORED'];
0994              $message = $save_message . '<br /><br />' . $user->lang('VIEW_PRIVATE_MESSAGE', '<a href="' . $return_message_url . '">', '</a>');
0995   
0996              $last_click_type = 'CLICK_RETURN_FOLDER';
0997              if ($folder_url)
0998              {
0999                  $message .= '<br /><br />' . sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . $folder_url . '">', '</a>', $user_folders[$folder_id]['folder_name']);
1000                  $last_click_type = 'CLICK_GOTO_FOLDER';
1001              }
1002              $message .= '<br /><br />' . sprintf($user->lang[$last_click_type], '<a href="' . $return_box_url . '">', '</a>', $user->lang[$return_box_lang]);
1003   
1004              meta_refresh(3, $return_message_url);
1005              trigger_error($message);
1006          }
1007   
1008          $message_subject = $subject;
1009      }
1010   
1011      // Preview
1012      if (!count($error) && $preview)
1013      {
1014          $preview_message = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false);
1015   
1016          $preview_signature = $user->data['user_sig'];
1017          $preview_signature_uid = $user->data['user_sig_bbcode_uid'];
1018          $preview_signature_bitfield = $user->data['user_sig_bbcode_bitfield'];
1019   
1020          // Signature
1021          if ($enable_sig && $config['allow_sig'] && $preview_signature)
1022          {
1023              $bbcode_flags = ($enable_bbcode ? OPTION_FLAG_BBCODE : 0) + ($enable_smilies ? OPTION_FLAG_SMILIES : 0) + ($enable_urls ? OPTION_FLAG_LINKS : 0);
1024              $preview_signature = generate_text_for_display($preview_signature, $preview_signature_uid, $preview_signature_bitfield, $bbcode_flags);
1025          }
1026          else
1027          {
1028              $preview_signature = '';
1029          }
1030   
1031          // Attachment Preview
1032          if (count($message_parser->attachment_data))
1033          {
1034              $template->assign_var('S_HAS_ATTACHMENTS', true);
1035   
1036              $update_count = array();
1037              $attachment_data = $message_parser->attachment_data;
1038   
1039              parse_attachments(false, $preview_message, $attachment_data, $update_count, true);
1040   
1041              foreach ($attachment_data as $i => $attachment)
1042              {
1043                  $template->assign_block_vars('attachment', array(
1044                      'DISPLAY_ATTACHMENT'    => $attachment)
1045                  );
1046              }
1047              unset($attachment_data);
1048          }
1049   
1050          $preview_subject = censor_text($subject);
1051   
1052          if (!count($error))
1053          {
1054              $template->assign_vars(array(
1055                  'PREVIEW_SUBJECT'        => $preview_subject,
1056                  'PREVIEW_MESSAGE'        => $preview_message,
1057                  'PREVIEW_SIGNATURE'        => $preview_signature,
1058   
1059                  'S_DISPLAY_PREVIEW'        => true)
1060              );
1061          }
1062          unset($message_text);
1063      }
1064   
1065      // Decode text for message display
1066      $bbcode_uid = (($action == 'quote' || $action == 'forward') && !$preview && !$refresh && (!count($error) || (count($error) && !$submit))) ? $bbcode_uid : $message_parser->bbcode_uid;
1067   
1068      $message_parser->decode_message($bbcode_uid);
1069   
1070      if (($action == 'quote' || $action == 'quotepost') && !$preview && !$refresh && !$submit)
1071      {
1072          if ($action == 'quotepost')
1073          {
1074              $post_id = $request->variable('p', 0);
1075              if ($config['allow_post_links'])
1076              {
1077                  $message_link = generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}";
1078                  $message_link_subject = "{$user->lang['SUBJECT']}{$user->lang['COLON']} {$message_subject}";
1079                  if ($bbcode_status)
1080                  {
1081                      $message_link = "[url=" . $message_link . "]" . $message_link_subject . "[/url]\n\n";
1082                  }
1083                  else
1084                  {
1085                      $message_link = $message_link . " - " . $message_link_subject . "\n\n";
1086                  }
1087              }
1088              else
1089              {
1090                  $message_link = $user->lang['SUBJECT'] . $user->lang['COLON'] . ' ' . $message_subject . " (" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id})\n\n";
1091              }
1092          }
1093          else
1094          {
1095              $message_link = '';
1096          }
1097          $quote_attributes = array(
1098              'author'  => $quote_username,
1099              'time'    => $post['message_time'],
1100              'user_id' => $post['author_id'],
1101          );
1102          if ($action === 'quotepost')
1103          {
1104              $quote_attributes['post_id'] = $post['msg_id'];
1105          }
1106          if ($action === 'quote')
1107          {
1108              $quote_attributes['msg_id'] = $post['msg_id'];
1109          }
1110          /** @var \phpbb\language\language $language */
1111          $language = $phpbb_container->get('language');
1112          /** @var \phpbb\textformatter\utils_interface $text_formatter_utils */
1113          $text_formatter_utils = $phpbb_container->get('text_formatter.utils');
1114          phpbb_format_quote($language, $message_parser, $text_formatter_utils, $bbcode_status, $quote_attributes, $message_link);
1115      }
1116   
1117      if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh)
1118      {
1119          $message_subject = ((!preg_match('/^Re:/', $message_subject)) ? 'Re: ' : '') . censor_text($message_subject);
1120   
1121          /**
1122          * This event allows you to modify the PM subject of the PM being quoted
1123          *
1124          * @event core.pm_modify_message_subject
1125          * @var    string        message_subject        String with the PM subject already censored.
1126          * @since 3.2.8-RC1
1127          */
1128          $vars = array('message_subject');
1129          extract($phpbb_dispatcher->trigger_event('core.pm_modify_message_subject', compact($vars)));
1130      }
1131   
1132      if ($action == 'forward' && !$preview && !$refresh && !$submit)
1133      {
1134          $fwd_to_field = write_pm_addresses(array('to' => $post['to_address']), 0, true);
1135   
1136          if ($config['allow_post_links'])
1137          {
1138              $quote_username_text = '[url=' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&amp;u={$post['author_id']}]{$quote_username}[/url]";
1139          }
1140          else
1141          {
1142              $quote_username_text = $quote_username . ' (' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&amp;u={$post['author_id']})";
1143          }
1144   
1145          $forward_text = array();
1146          $forward_text[] = $user->lang['FWD_ORIGINAL_MESSAGE'];
1147          $forward_text[] = sprintf($user->lang['FWD_SUBJECT'], censor_text($message_subject));
1148          $forward_text[] = sprintf($user->lang['FWD_DATE'], $user->format_date($message_time, false, true));
1149          $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text);
1150          $forward_text[] = sprintf($user->lang['FWD_TO'], implode($user->lang['COMMA_SEPARATOR'], $fwd_to_field['to']));
1151   
1152          $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote(
1153              censor_text($message_parser->message),
1154              array('author' => $quote_username)
1155          );
1156          $message_parser->message = implode("\n", $forward_text) . "\n\n" . $quote_text;
1157          $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject);
1158      }
1159   
1160      $attachment_data = $message_parser->attachment_data;
1161      $filename_data = $message_parser->filename_data;
1162      $message_text = $message_parser->message;
1163   
1164      // MAIN PM PAGE BEGINS HERE
1165   
1166      // Generate smiley listing
1167      generate_smilies('inline', 0);
1168   
1169      // Generate PM Icons
1170      $s_pm_icons = false;
1171      if ($config['enable_pm_icons'])
1172      {
1173          $s_pm_icons = posting_gen_topic_icons($action, $icon_id);
1174      }
1175   
1176      // Generate inline attachment select box
1177      posting_gen_inline_attachments($attachment_data);
1178   
1179      // Build address list for display
1180      // array('u' => array($author_id => 'to'));
1181      if (count($address_list))
1182      {
1183          // Get Usernames and Group Names
1184          $result = array();
1185          if (!empty($address_list['u']))
1186          {
1187              $sql = 'SELECT user_id as id, username as name, user_colour as colour
1188                  FROM ' . USERS_TABLE . '
1189                  WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($address_list['u']))) . '
1190                  ORDER BY username_clean ASC';
1191              $result['u'] = $db->sql_query($sql);
1192          }
1193   
1194          if (!empty($address_list['g']))
1195          {
1196              $sql = 'SELECT g.group_id AS id, g.group_name AS name, g.group_colour AS colour, g.group_type
1197                  FROM ' . GROUPS_TABLE . ' g';
1198   
1199              if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel'))
1200              {
1201                  $sql .= ' LEFT JOIN ' . USER_GROUP_TABLE . ' ug
1202                      ON (
1203                          g.group_id = ug.group_id
1204                          AND ug.user_id = ' . $user->data['user_id'] . '
1205                          AND ug.user_pending = 0
1206                      )
1207                      WHERE (g.group_type <> ' . GROUP_HIDDEN . ' OR ug.user_id = ' . $user->data['user_id'] . ')';
1208              }
1209   
1210              $sql .= ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? ' WHERE ' : ' AND ';
1211   
1212              $sql .= 'g.group_receive_pm = 1
1213                  AND ' . $db->sql_in_set('g.group_id', array_map('intval', array_keys($address_list['g']))) . '
1214                  ORDER BY g.group_name ASC';
1215   
1216              $result['g'] = $db->sql_query($sql);
1217          }
1218   
1219          $u = $g = array();
1220          $_types = array('u', 'g');
1221          foreach ($_types as $type)
1222          {
1223              if (isset($result[$type]) && $result[$type])
1224              {
1225                  while ($row = $db->sql_fetchrow($result[$type]))
1226                  {
1227                      if ($type == 'g')
1228                      {
1229                          $row['name'] = $group_helper->get_name($row['name']);
1230                      }
1231   
1232                      ${$type}[$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
1233                  }
1234                  $db->sql_freeresult($result[$type]);
1235              }
1236          }
1237   
1238          // Now Build the address list
1239          foreach ($address_list as $type => $adr_ary)
1240          {
1241              foreach ($adr_ary as $id => $field)
1242              {
1243                  if (!isset(${$type}[$id]))
1244                  {
1245                      unset($address_list[$type][$id]);
1246                      continue;
1247                  }
1248   
1249                  $field = ($field == 'to') ? 'to' : 'bcc';
1250                  $type = ($type == 'u') ? 'u' : 'g';
1251                  $id = (int) $id;
1252   
1253                  $tpl_ary = array(
1254                      'IS_GROUP'    => ($type == 'g') ? true : false,
1255                      'IS_USER'    => ($type == 'u') ? true : false,
1256                      'UG_ID'        => $id,
1257                      'NAME'        => ${$type}[$id]['name'],
1258                      'COLOUR'    => (${$type}[$id]['colour']) ? '#' . ${$type}[$id]['colour'] : '',
1259                      'TYPE'        => $type,
1260                  );
1261   
1262                  if ($type == 'u')
1263                  {
1264                      $tpl_ary = array_merge($tpl_ary, array(
1265                          'U_VIEW'        => get_username_string('profile', $id, ${$type}[$id]['name'], ${$type}[$id]['colour']),
1266                          'NAME_FULL'        => get_username_string('full', $id, ${$type}[$id]['name'], ${$type}[$id]['colour']),
1267                      ));
1268                  }
1269                  else
1270                  {
1271                      $tpl_ary = array_merge($tpl_ary, array(
1272                          'U_VIEW'        => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $id),
1273                      ));
1274                  }
1275   
1276                  $template->assign_block_vars($field . '_recipient', $tpl_ary);
1277              }
1278          }
1279      }
1280   
1281      // Build hidden address list
1282      $s_hidden_address_field = build_address_field($address_list);
1283   
1284      $bbcode_checked        = (isset($enable_bbcode)) ? !$enable_bbcode : (($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode')) ? !$user->optionget('bbcode') : 1);
1285      $smilies_checked    = (isset($enable_smilies)) ? !$enable_smilies : (($config['allow_smilies'] && $auth->acl_get('u_pm_smilies')) ? !$user->optionget('smilies') : 1);
1286      $urls_checked        = (isset($enable_urls)) ? !$enable_urls : 0;
1287      $sig_checked        = $enable_sig;
1288   
1289      switch ($action)
1290      {
1291          case 'post':
1292              $page_title = $user->lang['POST_NEW_PM'];
1293          break;
1294   
1295          case 'quote':
1296              $page_title = $user->lang['POST_QUOTE_PM'];
1297          break;
1298   
1299          case 'quotepost':
1300              $page_title = $user->lang['POST_PM_POST'];
1301          break;
1302   
1303          case 'reply':
1304              $page_title = $user->lang['POST_REPLY_PM'];
1305          break;
1306   
1307          case 'edit':
1308              $page_title = $user->lang['POST_EDIT_PM'];
1309          break;
1310   
1311          case 'forward':
1312              $page_title = $user->lang['POST_FORWARD_PM'];
1313          break;
1314   
1315          default:
1316              trigger_error('NO_ACTION_MODE', E_USER_ERROR);
1317          break;
1318      }
1319   
1320      $s_hidden_fields = (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : '';
1321      $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input type="hidden" name="draft_loaded" value="' . ((isset($_REQUEST['draft_loaded'])) ? $request->variable('draft_loaded', 0) : $draft_id) . '" />' : '';
1322   
1323      $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"';
1324   
1325      /** @var \phpbb\controller\helper $controller_helper */
1326      $controller_helper = $phpbb_container->get('controller.helper');
1327   
1328      // Start assigning vars for main posting page ...
1329      $template_ary = array(
1330          'L_POST_A'                    => $page_title,
1331          'L_ICON'                    => $user->lang['PM_ICON'],
1332          'L_MESSAGE_BODY_EXPLAIN'    => $user->lang('MESSAGE_BODY_EXPLAIN', (int) $config['max_post_chars']),
1333   
1334          'SUBJECT'                => (isset($message_subject)) ? $message_subject : '',
1335          'MESSAGE'                => $message_text,
1336          'BBCODE_STATUS'            => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
1337          'IMG_STATUS'            => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
1338          'FLASH_STATUS'            => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
1339          'SMILIES_STATUS'        => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
1340          'URL_STATUS'            => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'],
1341          'MAX_FONT_SIZE'            => (int) $config['max_post_font_size'],
1342          'MINI_POST_IMG'            => $user->img('icon_post_target', $user->lang['PM']),
1343          'ERROR'                    => (count($error)) ? implode('<br />', $error) : '',
1344          'MAX_RECIPIENTS'        => ($config['allow_mass_pm'] && ($auth->acl_get('u_masspm') || $auth->acl_get('u_masspm_group'))) ? $max_recipients : 0,
1345   
1346          'S_COMPOSE_PM'            => true,
1347          'S_EDIT_POST'            => ($action == 'edit'),
1348          'S_SHOW_PM_ICONS'        => $s_pm_icons,
1349          'S_BBCODE_ALLOWED'        => ($bbcode_status) ? 1 : 0,
1350          'S_BBCODE_CHECKED'        => ($bbcode_checked) ? ' checked="checked"' : '',
1351          'S_SMILIES_ALLOWED'        => $smilies_status,
1352          'S_SMILIES_CHECKED'        => ($smilies_checked) ? ' checked="checked"' : '',
1353          'S_SIG_ALLOWED'            => ($config['allow_sig'] && $config['allow_sig_pm'] && $auth->acl_get('u_sig')),
1354          'S_SIGNATURE_CHECKED'    => ($sig_checked) ? ' checked="checked"' : '',
1355          'S_LINKS_ALLOWED'        => $url_status,
1356          'S_MAGIC_URL_CHECKED'    => ($urls_checked) ? ' checked="checked"' : '',
1357          'S_SAVE_ALLOWED'        => ($auth->acl_get('u_savedrafts') && $action != 'edit') ? true : false,
1358          'S_HAS_DRAFTS'            => ($auth->acl_get('u_savedrafts') && $drafts),
1359          'S_FORM_ENCTYPE'        => $form_enctype,
1360          'S_ATTACH_DATA'            => json_encode($message_parser->attachment_data),
1361   
1362          'S_BBCODE_IMG'            => $img_status,
1363          'S_BBCODE_FLASH'        => $flash_status,
1364          'S_BBCODE_QUOTE'        => true,
1365          'S_BBCODE_URL'            => $url_status,
1366   
1367          'S_POST_ACTION'                => $s_action,
1368          'S_HIDDEN_ADDRESS_FIELD'    => $s_hidden_address_field,
1369          'S_HIDDEN_FIELDS'            => $s_hidden_fields,
1370   
1371          'S_CLOSE_PROGRESS_WINDOW'    => isset($_POST['add_file']),
1372          'U_PROGRESS_BAR'            => append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&amp;mode=popup'),
1373          'UA_PROGRESS_BAR'            => addslashes(append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&amp;mode=popup')),
1374      );
1375   
1376      /**
1377      * Modify the default template vars
1378      *
1379      * @event core.ucp_pm_compose_template
1380      * @var    array    template_ary    Template variables
1381      * @since 3.2.6-RC1
1382      */
1383      $vars = array('template_ary');
1384      extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_template', compact($vars)));
1385   
1386      $template->assign_vars($template_ary);
1387   
1388      // Build custom bbcodes array
1389      display_custom_bbcodes();
1390   
1391      // Show attachment box for adding attachments if true
1392      $allowed = ($auth->acl_get('u_pm_attach') && $config['allow_pm_attach'] && $form_enctype);
1393   
1394      if ($allowed)
1395      {
1396          $max_files = ($auth->acl_gets('a_', 'm_')) ? 0 : (int) $config['max_attachments_pm'];
1397          $plupload->configure($cache, $template, $s_action, false, $max_files);
1398      }
1399   
1400      // Attachment entry
1401      posting_gen_attachment_entry($attachment_data, $filename_data, $allowed);
1402   
1403      // Message History
1404      if ($action == 'reply' || $action == 'quote' || $action == 'forward')
1405      {
1406          if (message_history($msg_id, $user->data['user_id'], $post, array(), true))
1407          {
1408              $template->assign_var('S_DISPLAY_HISTORY', true);
1409          }
1410      }
1411  }
1412   
1413  /**
1414  * For composing messages, handle list actions
1415  */
1416  function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove_g, $add_to, $add_bcc)
1417  {
1418      global $auth, $db, $user;
1419      global $request, $phpbb_dispatcher;
1420   
1421      // Delete User [TO/BCC]
1422      if ($remove_u && $request->variable('remove_u', array(0 => '')))
1423      {
1424          $remove_user_id = array_keys($request->variable('remove_u', array(0 => '')));
1425   
1426          if (isset($remove_user_id[0]))
1427          {
1428              unset($address_list['u'][(int) $remove_user_id[0]]);
1429          }
1430      }
1431   
1432      // Delete Group [TO/BCC]
1433      if ($remove_g && $request->variable('remove_g', array(0 => '')))
1434      {
1435          $remove_group_id = array_keys($request->variable('remove_g', array(0 => '')));
1436   
1437          if (isset($remove_group_id[0]))
1438          {
1439              unset($address_list['g'][(int) $remove_group_id[0]]);
1440          }
1441      }
1442   
1443      // Add Selected Groups
1444      $group_list = $request->variable('group_list', array(0));
1445   
1446      // Build usernames to add
1447      $usernames = $request->variable('username', '', true);
1448      $usernames = (empty($usernames)) ? array() : array($usernames);
1449   
1450      $username_list = $request->variable('username_list', '', true);
1451      if ($username_list)
1452      {
1453          $usernames = array_merge($usernames, explode("\n", $username_list));
1454      }
1455   
1456      // If add to or add bcc not pressed, users could still have usernames listed they want to add...
1457      if (!$add_to && !$add_bcc && (count($group_list) || count($usernames)))
1458      {
1459          $add_to = true;
1460   
1461          global $refresh, $submit, $preview;
1462   
1463          $refresh = true;
1464          $submit = false;
1465   
1466          // Preview is only true if there was also a message entered
1467          if ($request->variable('message', ''))
1468          {
1469              $preview = true;
1470          }
1471      }
1472   
1473      // Add User/Group [TO]
1474      if ($add_to || $add_bcc)
1475      {
1476          $type = ($add_to) ? 'to' : 'bcc';
1477   
1478          if (count($group_list))
1479          {
1480              foreach ($group_list as $group_id)
1481              {
1482                  $address_list['g'][$group_id] = $type;
1483              }
1484          }
1485   
1486          // User ID's to add...
1487          $user_id_ary = array();
1488   
1489          // Reveal the correct user_ids
1490          if (count($usernames))
1491          {
1492              $user_id_ary = array();
1493              user_get_id_name($user_id_ary, $usernames, array(USER_NORMAL, USER_FOUNDER, USER_INACTIVE));
1494   
1495              // If there are users not existing, we will at least print a notice...
1496              if (!count($user_id_ary))
1497              {
1498                  $error[] = $user->lang['PM_NO_USERS'];
1499              }
1500          }
1501   
1502          // Add Friends if specified
1503          $friend_list = array_keys($request->variable('add_' . $type, array(0)));
1504          $user_id_ary = array_merge($user_id_ary, $friend_list);
1505   
1506          foreach ($user_id_ary as $user_id)
1507          {
1508              if ($user_id == ANONYMOUS)
1509              {
1510                  continue;
1511              }
1512   
1513              $address_list['u'][$user_id] = $type;
1514          }
1515      }
1516   
1517      // Check for disallowed recipients
1518      if (!empty($address_list['u']))
1519      {
1520          $can_ignore_allow_pm = $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_');
1521   
1522          // Administrator deactivated users check and we need to check their
1523          //        PM status (do they want to receive PM's?)
1524          //         Only check PM status if not a moderator or admin, since they
1525          //        are allowed to override this user setting
1526          $sql = 'SELECT user_id, user_allow_pm
1527              FROM ' . USERS_TABLE . '
1528              WHERE ' . $db->sql_in_set('user_id', array_keys($address_list['u'])) . '
1529                  AND (
1530                          (user_type = ' . USER_INACTIVE . '
1531                          AND user_inactive_reason = ' . INACTIVE_MANUAL . ')
1532                          ' . ($can_ignore_allow_pm ? '' : ' OR user_allow_pm = 0') . '
1533                      )';
1534   
1535          $result = $db->sql_query($sql);
1536   
1537          $removed_no_pm = $removed_no_permission = false;
1538          while ($row = $db->sql_fetchrow($result))
1539          {
1540              if (!$can_ignore_allow_pm && !$row['user_allow_pm'])
1541              {
1542                  $removed_no_pm = true;
1543              }
1544              else
1545              {
1546                  $removed_no_permission = true;
1547              }
1548   
1549              unset($address_list['u'][$row['user_id']]);
1550          }
1551          $db->sql_freeresult($result);
1552   
1553          // print a notice about users not being added who do not want to receive pms
1554          if ($removed_no_pm)
1555          {
1556              $error[] = $user->lang['PM_USERS_REMOVED_NO_PM'];
1557          }
1558   
1559          // print a notice about users not being added who do not have permission to receive PMs
1560          if ($removed_no_permission)
1561          {
1562              $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION'];
1563          }
1564   
1565          if (!count(array_keys($address_list['u'])))
1566          {
1567              return;
1568          }
1569   
1570          // Check if users have permission to read PMs
1571          $can_read = $auth->acl_get_list(array_keys($address_list['u']), 'u_readpm');
1572          $can_read = (empty($can_read) || !isset($can_read[0]['u_readpm'])) ? array() : $can_read[0]['u_readpm'];
1573          $cannot_read_list = array_diff(array_keys($address_list['u']), $can_read);
1574          if (!empty($cannot_read_list))
1575          {
1576              foreach ($cannot_read_list as $cannot_read)
1577              {
1578                  unset($address_list['u'][$cannot_read]);
1579              }
1580   
1581              $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION'];
1582          }
1583   
1584          // Check if users are banned
1585          $banned_user_list = phpbb_get_banned_user_ids(array_keys($address_list['u']), false);
1586          if (!empty($banned_user_list))
1587          {
1588              foreach ($banned_user_list as $banned_user)
1589              {
1590                  unset($address_list['u'][$banned_user]);
1591              }
1592   
1593              $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION'];
1594          }
1595      }
1596   
1597      /**
1598      * Event for additional message list actions
1599      *
1600      * @event core.message_list_actions
1601      * @var    array    address_list        The assoc array with the recipient user/group ids
1602      * @var    array    error                The array containing error data
1603      * @var    bool    remove_u            The variable for removing a user
1604      * @var    bool    remove_g            The variable for removing a group
1605      * @var    bool    add_to                The variable for adding a user to the [TO] field
1606      * @var    bool    add_bcc                The variable for adding a user to the [BCC] field
1607      * @since 3.2.4-RC1
1608      */
1609      $vars = array('address_list', 'error', 'remove_u', 'remove_g', 'add_to', 'add_bcc');
1610      extract($phpbb_dispatcher->trigger_event('core.message_list_actions', compact($vars)));
1611  }
1612   
1613  /**
1614  * Build the hidden field for the recipients. Needed, as the variable is not read via $request->variable().
1615  */
1616  function build_address_field($address_list)
1617  {
1618      $s_hidden_address_field = '';
1619      foreach ($address_list as $type => $adr_ary)
1620      {
1621          foreach ($adr_ary as $id => $field)
1622          {
1623              $s_hidden_address_field .= '<input type="hidden" name="address_list[' . (($type == 'u') ? 'u' : 'g') . '][' . (int) $id . ']" value="' . (($field == 'to') ? 'to' : 'bcc') . '" />';
1624          }
1625      }
1626      return $s_hidden_address_field;
1627  }
1628   
1629  /**
1630  * Return number of private message recipients
1631  */
1632  function num_recipients($address_list)
1633  {
1634      $num_recipients = 0;
1635   
1636      foreach ($address_list as $field => $adr_ary)
1637      {
1638          $num_recipients += count($adr_ary);
1639      }
1640   
1641      return $num_recipients;
1642  }
1643   
1644  /**
1645  * Get number of 'num_recipients' recipients from first position
1646  */
1647  function get_recipients($address_list, $num_recipients = 1)
1648  {
1649      $recipient = array();
1650   
1651      $count = 0;
1652      foreach ($address_list as $field => $adr_ary)
1653      {
1654          foreach ($adr_ary as $id => $type)
1655          {
1656              if ($count >= $num_recipients)
1657              {
1658                  break 2;
1659              }
1660              $recipient[$field][$id] = $type;
1661              $count++;
1662          }
1663      }
1664   
1665      return $recipient;
1666  }
1667