From df5ab5b5d842659ad681e86fd519dcc74b352d0f Mon Sep 17 00:00:00 2001 From: rxu Date: Fri, 5 May 2023 19:59:45 +0700 Subject: [PATCH 01/29] [ticket/17135] Introduce Symfony Mailer for emails backend PHPBB3-17135 --- phpBB/includes/functions_messenger.php | 1660 ++++++------------------ phpBB/phpbb/message/message.php | 8 +- tests/email/email_parsing_test.php | 13 +- tests/email/headers_encoding_test.php | 48 - 4 files changed, 432 insertions(+), 1297 deletions(-) delete mode 100644 tests/email/headers_encoding_test.php diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index c94a2a5c42..390463fe3a 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -11,6 +11,12 @@ * */ +use Symfony\Component\Mailer\Transport; +use Symfony\Component\Mailer\Mailer; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\Headers; + /** * @ignore */ @@ -24,85 +30,115 @@ if (!defined('IN_PHPBB')) */ class messenger { - var $msg, $replyto, $from, $subject; - var $addresses = array(); - var $extra_headers = array(); + private const PRIORITY_MAP = [ + Email::PRIORITY_HIGHEST => 'Highest', + Email::PRIORITY_HIGH => 'High', + Email::PRIORITY_NORMAL => 'Normal', + Email::PRIORITY_LOW => 'Low', + Email::PRIORITY_LOWEST => 'Lowest', + ]; + private const HEADER_CLASS_MAP = [ + 'date' => DateHeader::class, + 'from' => MailboxListHeader::class, + 'sender' => MailboxHeader::class, + 'reply-to' => MailboxListHeader::class, + 'to' => MailboxListHeader::class, + 'cc' => MailboxListHeader::class, + 'bcc' => MailboxListHeader::class, + 'message-id' => IdentificationHeader::class, + 'in-reply-to' => UnstructuredHeader::class, + 'references' => UnstructuredHeader::class, + 'return-path' => PathHeader::class, + ]; - var $mail_priority = MAIL_NORMAL_PRIORITY; + var $msg, $replyto, $from, $subject; + var $addresses = []; + var $extra_headers = []; + + /** + * Possible values are: + * Email::PRIORITY_HIGHEST + * Email::PRIORITY_HIGH + * Email::PRIORITY_NORMAL + * Email::PRIORITY_LOW + * Email::PRIORITY_LOWEST + */ + var $mail_priority = Email::PRIORITY_NORMAL; var $use_queue = true; /** @var \phpbb\template\template */ protected $template; /** - * Constructor - */ + * Constructor + */ function __construct($use_queue = true) { - global $config; + global $phpbb_container, $phpbb_root_path, $phpEx; - $this->use_queue = (!$config['email_package_size']) ? false : $use_queue; + $this->phpbb_container = $phpbb_container; + $this->config = $this->phpbb_container->get('config'); + $this->dispatcher = $this->phpbb_container->get('dispatcher'); + $this->language = $this->phpbb_container->get('language'); + $this->log = $this->phpbb_container->get('log'); + $this->request = $this->phpbb_container->get('request'); + $this->user = $this->phpbb_container->get('user'); + $this->email = new Email(); + $this->headers = $this->email->getHeaders(); + $this->use_queue = (!$this->config['email_package_size']) ? false : $use_queue; $this->subject = ''; + $this->root_path = $phpbb_root_path; + $this->php_ext = $phpEx; } /** - * Resets all the data (address, template file, etc etc) to default - */ + * Resets all the data (address, template file, etc etc) to default + */ function reset() { - $this->addresses = $this->extra_headers = array(); + $this->addresses = $this->extra_headers = []; $this->msg = $this->replyto = $this->from = ''; - $this->mail_priority = MAIL_NORMAL_PRIORITY; + $this->mail_priority = Email::PRIORITY_NORMAL; } /** - * Set addresses for to/im as available - * - * @param array $user User row - */ + * Set addresses for to/im as available + * + * @param array $user User row + */ function set_addresses($user) { if (isset($user['user_email']) && $user['user_email']) { - $this->to($user['user_email'], (isset($user['username']) ? $user['username'] : '')); + $this->email->to(new Address($user['user_email'], $user['username'] ?: '')); } if (isset($user['user_jabber']) && $user['user_jabber']) { - $this->im($user['user_jabber'], (isset($user['username']) ? $user['username'] : '')); + $this->im($user['user_jabber'], $user['username'] ?: ''); } } /** - * Sets an email address to send to - */ + * Sets an email address to send to + */ function to($address, $realname = '') { - global $config; - if (!trim($address)) { return; } - $pos = isset($this->addresses['to']) ? count($this->addresses['to']) : 0; - - $this->addresses['to'][$pos]['email'] = trim($address); - // If empty sendmail_path on windows, PHP changes the to line - if (!$config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\') - { - $this->addresses['to'][$pos]['name'] = ''; - } - else - { - $this->addresses['to'][$pos]['name'] = trim($realname); - } + $windows_empty_sendmail_path = !$this->config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\'; + + $to = new Address(trim($address), $windows_empty_sendmail_path ? '' : trim($realname)); + $this->email->getTo() ? $this->email->addTo($to) : $this->email->to($to); } /** - * Sets an cc address to send to - */ + * Sets an cc address to send to + */ function cc($address, $realname = '') { if (!trim($address)) @@ -110,14 +146,13 @@ class messenger return; } - $pos = isset($this->addresses['cc']) ? count($this->addresses['cc']) : 0; - $this->addresses['cc'][$pos]['email'] = trim($address); - $this->addresses['cc'][$pos]['name'] = trim($realname); + $cc = new Address(trim($address), trim($realname)); + $this->email->getCc() ? $this->email->addCc($to) : $this->email->cc($to); } /** - * Sets an bcc address to send to - */ + * Sets an bcc address to send to + */ function bcc($address, $realname = '') { if (!trim($address)) @@ -125,14 +160,13 @@ class messenger return; } - $pos = isset($this->addresses['bcc']) ? count($this->addresses['bcc']) : 0; - $this->addresses['bcc'][$pos]['email'] = trim($address); - $this->addresses['bcc'][$pos]['name'] = trim($realname); + $bcc = new Address(trim($address), trim($realname)); + $this->email->getBcc() ? $this->email->addBcc($to) : $this->email->bcc($to); } /** - * Sets a im contact to send to - */ + * Sets a im contact to send to + */ function im($address, $realname = '') { // IM-Addresses could be empty @@ -147,67 +181,73 @@ class messenger } /** - * Set the reply to address - */ + * Set the reply to address + */ function replyto($address) { - $this->replyto = trim($address); + $this->replyto = new Address(trim($address)); + $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); } /** - * Set the from address - */ + * Set the from address + */ function from($address) { - $this->from = trim($address); + $this->from = new Address(trim($address)); + $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); } /** - * set up subject for mail - */ + * set up subject for mail + */ function subject($subject = '') { - $this->subject = trim($subject); + $this->email->subject(trim($subject)); } /** - * set up extra mail headers - */ - function headers($headers) + * set up extra mail headers + */ + function headers($header_name, $header_value) { - $this->extra_headers[] = trim($headers); + $this->headers->addTextHeader(trim($header_name), trim($header_value)); } /** - * Adds X-AntiAbuse headers - * - * @param \phpbb\config\config $config Config object - * @param \phpbb\user $user User object - * @return void - */ + * Adds X-AntiAbuse headers + * + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object + * @return void + */ function anti_abuse_headers($config, $user) { - $this->headers('X-AntiAbuse: Board servername - ' . mail_encode($config['server_name'])); - $this->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $this->headers('X-AntiAbuse: Username - ' . mail_encode($user->data['username'])); - $this->headers('X-AntiAbuse: User IP - ' . $user->ip); + $this->headers->addTextHeader('X-AntiAbuse', 'Board servername - ' . $config['server_name']); + $this->headers->addTextHeader('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); + $this->headers->addTextHeader('X-AntiAbuse', 'Username - ' . $user->data['username']); + $this->headers->addTextHeader('X-AntiAbuse', 'User IP - ' . $user->ip); } /** - * Set the email priority - */ - function set_mail_priority($priority = MAIL_NORMAL_PRIORITY) + * Set the email priority + * Possible values are: + * Email::PRIORITY_HIGHEST + * Email::PRIORITY_HIGH + * Email::PRIORITY_NORMAL + * Email::PRIORITY_LOW + * Email::PRIORITY_LOWEST + */ + function set_mail_priority($priority = Email::PRIORITY_NORMAL) { - $this->mail_priority = $priority; + $this->email->priority($priority); } /** - * Set email template to use - */ + * Set email template to use + */ function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') { - global $config, $phpbb_root_path, $user; - $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; $this->setup_template(); @@ -222,7 +262,7 @@ class messenger // fall back to board default language if the user's language is // missing $template_file. If this does not exist either, // $this->template->set_filenames will do a trigger_error - $template_lang = basename($config['default_lang']); + $template_lang = basename($this->config['default_lang']); } $ext_template_paths = array( @@ -240,20 +280,20 @@ class messenger } else { - $template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/'; + $template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; $template_path .= $template_lang . '/email'; $template_paths = array( $template_path . $template_dir_prefix, ); - $board_language = basename($config['default_lang']); + $board_language = basename($this->config['default_lang']); // we can only specify default language fallback when the path is not a custom one for which we // do not know the default language alternative if ($template_lang !== $board_language) { - $fallback_template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/'; + $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; $fallback_template_path .= $board_language . '/email'; $template_paths[] = $fallback_template_path . $template_dir_prefix; @@ -266,7 +306,7 @@ class messenger // If everything fails just fall back to en template if ($template_lang !== 'en' && $board_language !== 'en') { - $fallback_template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/'; + $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; $fallback_template_path .= 'en/email'; $template_paths[] = $fallback_template_path . $template_dir_prefix; @@ -288,8 +328,8 @@ class messenger } /** - * assign variables to email template - */ + * assign variables to email template + */ function assign_vars($vars) { $this->setup_template(); @@ -305,61 +345,65 @@ class messenger } /** - * Send the mail out to the recipients set previously in var $this->addresses - * - * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH - * @param bool $break Flag indicating if the function only formats the subject - * and the message without sending it - * - * @return bool - */ + * Send the mail out to the recipients set previously in var $this->addresses + * + * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @param bool $break Flag indicating if the function only formats the subject + * and the message without sending it + * + * @return bool + */ function send($method = NOTIFY_EMAIL, $break = false) { - global $config, $user, $phpbb_dispatcher; - // We add some standard variables we always use, no need to specify them always - $this->assign_vars(array( + $this->assign_vars([ 'U_BOARD' => generate_board_url(), - 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . html_entity_decode($config['board_email_sig'], ENT_COMPAT)), - 'SITENAME' => html_entity_decode($config['sitename'], ENT_COMPAT), - )); + 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . html_entity_decode($this->config['board_email_sig'], ENT_COMPAT)), + 'SITENAME' => html_entity_decode($this->config['sitename'], ENT_COMPAT), + ]); - $subject = $this->subject; + $email = $this->email; + $subject = $this->email->getSubject(); $template = $this->template; /** - * Event to modify the template before parsing - * - * @event core.modify_notification_template - * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH - * @var bool break Flag indicating if the function only formats the subject - * and the message without sending it - * @var string subject The message subject - * @var \phpbb\template\template template The (readonly) template object - * @since 3.2.4-RC1 - */ - $vars = array('method', 'break', 'subject', 'template'); - extract($phpbb_dispatcher->trigger_event('core.modify_notification_template', compact($vars))); + * Event to modify the template before parsing + * + * @event core.modify_notification_template + * @var bool break Flag indicating if the function only formats the subject + * and the message without sending it + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @var string subject The message subject + * @var \phpbb\template\template template The (readonly) template object + * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email. + */ + $vars = ['break', 'email', 'method', 'subject', 'template']; + extract($this->dispatcher->trigger_event('core.modify_notification_template', compact($vars))); // Parse message through template $message = trim($this->template->assign_display('body')); /** - * Event to modify notification message text after parsing - * - * @event core.modify_notification_message - * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH - * @var bool break Flag indicating if the function only formats the subject - * and the message without sending it - * @var string subject The message subject - * @var string message The message text - * @since 3.1.11-RC1 - */ - $vars = array('method', 'break', 'subject', 'message'); - extract($phpbb_dispatcher->trigger_event('core.modify_notification_message', compact($vars))); + * Event to modify notification message text after parsing + * + * @event core.modify_notification_message + * @var bool break Flag indicating if the function only formats the subject + * and the message without sending it + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var string message The message text + * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @var string subject The message subject + * @since 3.1.11-RC1 + * @changed 4.0.0-a1 Added vars: email. + */ + $vars = ['break', 'email', 'message', 'method', 'subject']; + extract($this->dispatcher->trigger_event('core.modify_notification_message', compact($vars))); + $this->email = $email; $this->subject = $subject; $this->msg = $message; - unset($subject, $message, $template); + unset($email, $subject, $message, $template); // Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding $this->msg = str_replace("\r\n", "\n", $this->msg); @@ -370,17 +414,17 @@ class messenger $match = array(); if (preg_match('#^(Subject:(.*?))$#m', $this->msg, $match)) { - $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $user->lang['NO_EMAIL_SUBJECT']); + $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); } else { - $this->subject = (($this->subject != '') ? $this->subject : $user->lang['NO_EMAIL_SUBJECT']); + $this->subject = (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); } if (preg_match('#^(List-Unsubscribe:(.*?))$#m', $this->msg, $match)) { - $this->extra_headers[] = $match[1]; + $this->headers->addTextHeader('List-Unsubscribe', trim($match[2])); $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); } @@ -389,6 +433,9 @@ class messenger $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); } + $this->email->subject($this->subject); + $this->email->text($this->msg); + if ($break) { return true; @@ -415,24 +462,22 @@ class messenger } /** - * Add error message to log - */ + * Add error message to log + */ function error($type, $msg) { - global $user, $config, $request, $phpbb_log; - // Session doesn't exist, create it - if (!isset($user->session_id) || $user->session_id === '') + if (!isset($this->user->session_id) || $this->user->session_id === '') { - $user->session_begin(); + $this->user->session_begin(); } - $calling_page = html_entity_decode($request->server('REQUEST_URI'), ENT_COMPAT); + $calling_page = html_entity_decode($this->request->server('REQUEST_URI'), ENT_COMPAT); switch ($type) { case 'EMAIL': - $message = 'EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()') . ''; + $message = 'EMAIL/' . (($this->config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()') . ''; break; default: @@ -441,17 +486,15 @@ class messenger } $message .= '
' . htmlspecialchars($calling_page, ENT_COMPAT) . '

' . $msg . '
'; - $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_' . $type, false, array($message)); + $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); } /** - * Save to queue - */ + * Save to queue + */ function save_queue() { - global $config; - - if ($config['email_package_size'] && $this->use_queue && !empty($this->queue)) + if ($this->config['email_package_size'] && $this->use_queue && !empty($this->queue)) { $this->queue->save(); return; @@ -459,128 +502,176 @@ class messenger } /** - * Generates a valid message id to be used in emails - * - * @return string message id - */ - function generate_message_id() + * Detect proper method to add header + * + * @return string + */ + public function get_header_method(string $name) { - global $config, $request; + $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); + $method = 'add'.ucfirst(array_pop($parts)); + if ('addUnstructuredHeader' === $method) + { + $method = 'addTextHeader'; + } + else if ('addIdentificationHeader' === $method) + { + $method = 'addIdHeader'; + } - $domain = ($config['server_name']) ?: $request->server('SERVER_NAME', 'phpbb.generated'); - - return md5(unique_id()) . '@' . $domain; + return $method; } /** - * Return email header - */ - function build_header($to, $cc, $bcc) + * Set email headers + */ + function build_header() { - global $config, $phpbb_dispatcher; + $headers = []; - // We could use keys here, but we won't do this for 3.0.x to retain backwards compatibility - $headers = array(); - - $headers[] = 'From: ' . $this->from; - - if ($cc) + $board_contact = $this->config['board_contact']; + if (empty($this->email->getReplyTo())) { - $headers[] = 'Cc: ' . $cc; + $this->replyto = $board_contact; + $headers['Reply-To'] = $this->replyto; } - if ($bcc) + if (empty($this->email->getFrom())) { - $headers[] = 'Bcc: ' . $bcc; + $this->from = $board_contact; + $headers['From'] = $this->from; } - $headers[] = 'Reply-To: ' . $this->replyto; - $headers[] = 'Return-Path: <' . $config['board_email'] . '>'; - $headers[] = 'Sender: <' . $config['board_email'] . '>'; - $headers[] = 'MIME-Version: 1.0'; - $headers[] = 'Message-ID: <' . $this->generate_message_id() . '>'; - $headers[] = 'Date: ' . date('r', time()); - $headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed - $headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit - - $headers[] = 'X-Priority: ' . $this->mail_priority; - $headers[] = 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High')); - $headers[] = 'X-Mailer: phpBB3'; - $headers[] = 'X-MimeOLE: phpBB3'; - $headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()); + $headers['Return-Path'] = new Address($this->config['board_email']); + $headers['Sender'] = new Address($this->config['board_email']); + $headers['X-Priority'] = sprintf('%d (%s)', $this->mail_priority, self::PRIORITY_MAP[$this->mail_priority]); + $headers['X-MSMail-Priority'] = self::PRIORITY_MAP[$this->mail_priority]; + $headers['X-Mailer'] = 'phpBB3'; + $headers['X-MimeOLE'] = 'phpBB3'; + $headers['X-phpBB-Origin'] = 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()); /** - * Event to modify email header entries - * - * @event core.modify_email_headers - * @var array headers Array containing email header entries - * @since 3.1.11-RC1 - */ + * Event to modify email header entries + * + * @event core.modify_email_headers + * @var array headers Array containing email header entries + * @since 3.1.11-RC1 + */ $vars = array('headers'); - extract($phpbb_dispatcher->trigger_event('core.modify_email_headers', compact($vars))); + extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - if (count($this->extra_headers)) + foreach ($headers as $header => $value) { - $headers = array_merge($headers, $this->extra_headers); + // addMailboxListHeader() requires value to be array + if ($this->get_header_method($header) == 'addMailboxListHeader') + { + $value = [$value]; + } + $this->headers->addHeader($header, $value); } - return $headers; + return true; } /** - * Send out emails - */ + * Generates a valid transport to send email + * + * @param bool $dummy Flag to disable mail delivery + * @return Symfony\Component\Mailer\Transport Symfony Transport object + */ + function get_transport($dummy = false) + { + if ($dummy) + { + $dsn = 'null://null'; + } + else if ($this->config['smtp_delivery']) + { + $user = urlencode($this->config['smtp_username']); + $password = urlencode($this->config['smtp_password']); + $smtp_host = urlencode($this->config['smtp_host']); + $smtp_port = $this->config['smtp_port']; + $dsn = "smtp://$user:$password@$smtp_host:$smtp_port"; + } + else + { + $dsn = 'sendmail://default'; + } + + $transport = Transport::fromDsn($dsn); + + if ($this->config['smtp_delivery']) + { + // Set ssl context options, see http://php.net/manual/en/context.ssl.php + $verify_peer = (bool) $this->config['smtp_verify_peer']; + $verify_peer_name = (bool) $this->config['smtp_verify_peer_name']; + $allow_self_signed = (bool) $this->config['smtp_allow_self_signed']; + $options = [ + 'ssl' => [ + 'verify_peer' => $verify_peer, + 'verify_peer_name' => $verify_peer_name, + 'allow_self_signed' => $allow_self_signed, + ] + ]; + $transport->getStream()->setStreamOptions($options); + } + + return $transport; + } + + /** + * Send out emails + */ function msg_email() { - global $config, $phpbb_dispatcher; - - if (empty($config['email_enable'])) + if (empty($this->config['email_enable'])) { return false; } // Addresses to send to? - if (empty($this->addresses) || (empty($this->addresses['to']) && empty($this->addresses['cc']) && empty($this->addresses['bcc']))) + if (empty($this->email->getTo())) { // Send was successful. ;) return true; } $use_queue = false; - if ($config['email_package_size'] && $this->use_queue) + if ($this->config['email_package_size'] && $this->use_queue) { if (empty($this->queue)) { $this->queue = new queue(); - $this->queue->init('email', $config['email_package_size']); + $this->queue->init('email', $this->config['email_package_size']); } $use_queue = true; } - $contact_name = html_entity_decode($config['board_contact_name'], ENT_COMPAT); - $board_contact = (($contact_name !== '') ? '"' . mail_encode($contact_name) . '" ' : '') . '<' . $config['board_contact'] . '>'; + $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); + $board_contact = $this->config['board_contact']; $break = false; - $addresses = $this->addresses; $subject = $this->subject; $msg = $this->msg; + $email = $this->email; /** - * Event to send message via external transport - * - * @event core.notification_message_email - * @var bool break Flag indicating if the function return after hook - * @var array addresses The message recipients - * @var string subject The message subject - * @var string msg The message text - * @since 3.2.4-RC1 - */ + * Event to send message via external transport + * + * @event core.notification_message_email + * @var bool break Flag indicating if the function return after hook + * @var string subject The message subject + * @var string msg The message text + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses + */ $vars = array( 'break', - 'addresses', 'subject', 'msg', + 'email', ); - extract($phpbb_dispatcher->trigger_event('core.notification_message_email', compact($vars))); + extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); $this->addresses = $addresses; $this->subject = $subject; @@ -592,66 +683,87 @@ class messenger return true; } - if (empty($this->replyto)) + if (empty($this->email->getReplyto())) { - $this->replyto = $board_contact; + $this->email->replyTo(new Address($board_contact)); } - if (empty($this->from)) + if (empty($this->email->getFrom())) { - $this->from = $board_contact; - } - - $encode_eol = $config['smtp_delivery'] || PHP_VERSION_ID >= 80000 ? "\r\n" : PHP_EOL; - - // Build to, cc and bcc strings - $to = $cc = $bcc = ''; - foreach ($this->addresses as $type => $address_ary) - { - if ($type == 'im') - { - continue; - } - - foreach ($address_ary as $which_ary) - { - ${$type} .= ((${$type} != '') ? ', ' : '') . (($which_ary['name'] != '') ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']); - } + $this->email->from(new Address($board_contact)); } // Build header - $headers = $this->build_header($to, $cc, $bcc); + $this->build_header(); // Send message ... if (!$use_queue) { - $mail_to = ($to == '') ? 'undisclosed-recipients:;' : $to; - $err_msg = ''; + $transport = $this->get_transport(); + $mailer = new Mailer($transport); - if ($config['smtp_delivery']) - { - $result = smtpmail($this->addresses, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $err_msg, $headers); - } - else - { - $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $encode_eol, $err_msg); - } + $subject = $this->subject; + $msg = $this->msg; + $headers = $this->headers; + $email = $this->email; + /** + * Modify data before sending out emails with PHP's mail function + * + * @event core.phpbb_mail_before + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var string headers The email headers + * @since 3.3.6-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters. + */ + $vars = [ + 'email', + 'subject', + 'msg', + 'headers', + ]; + extract($this->dispatcher->trigger_event('core.phpbb_mail_before', compact($vars))); - if (!$result) + $this->subject = $subject; + $this->msg = $msg; + $this->headers = $headers; + $this->email = $email; + + try { - $this->error('EMAIL', $err_msg); + $mailer->send($this->email); + } + catch (TransportExceptionInterface $e) + { + $this->error('EMAIL', $e->getDebug()); return false; } + + /** + * Execute code after sending out emails with PHP's mail function + * + * @event core.phpbb_mail_after + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var string headers The email headers + * @since 3.3.6-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters, $result. + */ + $vars = [ + 'email', + 'subject', + 'msg', + 'headers', + ]; + extract($this->dispatcher->trigger_event('core.phpbb_mail_after', compact($vars))); } else { - $this->queue->put('email', array( - 'to' => $to, - 'addresses' => $this->addresses, - 'subject' => $this->subject, - 'msg' => $this->msg, - 'headers' => $headers) - ); + $this->queue->put('email', [ + 'email' => $this->email, + ]); } return true; @@ -662,9 +774,7 @@ class messenger */ function msg_jabber() { - global $config, $user, $phpbb_root_path, $phpEx; - - if (empty($config['jab_enable']) || empty($config['jab_host']) || empty($config['jab_username']) || empty($config['jab_password'])) + if (empty($this->config['jab_enable']) || empty($this->config['jab_host']) || empty($this->config['jab_username']) || empty($this->config['jab_password'])) { return false; } @@ -676,12 +786,12 @@ class messenger } $use_queue = false; - if ($config['jab_package_size'] && $this->use_queue) + if ($this->config['jab_package_size'] && $this->use_queue) { if (empty($this->queue)) { $this->queue = new queue(); - $this->queue->init('jabber', $config['jab_package_size']); + $this->queue->init('jabber', $this->config['jab_package_size']); } $use_queue = true; } @@ -695,18 +805,18 @@ class messenger if (!$use_queue) { - include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); - $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], html_entity_decode($config['jab_password'], ENT_COMPAT), $config['jab_use_ssl'], $config['jab_verify_peer'], $config['jab_verify_peer_name'], $config['jab_allow_self_signed']); + include_once($this->root_path . 'includes/functions_jabber.' . $this->php_ext); + $this->jabber = new jabber($this->config['jab_host'], $this->config['jab_port'], $this->config['jab_username'], html_entity_decode($this->config['jab_password'], ENT_COMPAT), $this->config['jab_use_ssl'], $this->config['jab_verify_peer'], $this->config['jab_verify_peer_name'], $this->config['jab_allow_self_signed']); if (!$this->jabber->connect()) { - $this->error('JABBER', $user->lang['ERR_JAB_CONNECT'] . '
' . $this->jabber->get_log()); + $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->jabber->get_log()); return false; } if (!$this->jabber->login()) { - $this->error('JABBER', $user->lang['ERR_JAB_AUTH'] . '
' . $this->jabber->get_log()); + $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->jabber->get_log()); return false; } @@ -734,8 +844,6 @@ class messenger */ protected function setup_template() { - global $phpbb_container, $phpbb_dispatcher; - if ($this->template instanceof \phpbb\template\template) { return; @@ -749,20 +857,20 @@ class messenger $phpbb_container->getParameter('core.template.cache_path'), $phpbb_container->get('ext.manager'), new \phpbb\template\twig\loader(), - $phpbb_dispatcher, - array() + $this->dispatcher, + [] ); - $template_environment->setLexer($phpbb_container->get('template.twig.lexer')); + $template_environment->setLexer($this->phpbb_container->get('template.twig.lexer')); $this->template = new \phpbb\template\twig\twig( - $phpbb_container->get('path_helper'), - $phpbb_container->get('config'), + $this->phpbb_container->get('path_helper'), + $this->config, new \phpbb\template\context(), $template_environment, - $phpbb_container->getParameter('core.template.cache_path'), - $phpbb_container->get('user'), - $phpbb_container->get('template.twig.extensions.collection'), - $phpbb_container->get('ext.manager') + $this->phpbb_container->getParameter('core.template.cache_path'), + $this->user, + $this->phpbb_container->get('template.twig.extensions.collection'), + $this->phpbb_container->get('ext.manager') ); } @@ -782,8 +890,8 @@ class messenger */ class queue { - var $data = array(); - var $queue_data = array(); + var $data = []; + var $queue_data = []; var $package_size = 0; var $cache_file = ''; var $eol = "\n"; @@ -798,11 +906,15 @@ class queue */ function __construct() { - global $phpEx, $phpbb_root_path, $phpbb_filesystem, $phpbb_container; + global $phpbb_container; - $this->data = array(); - $this->cache_file = $phpbb_container->getParameter('core.cache_dir') . "queue.$phpEx"; - $this->filesystem = $phpbb_filesystem; + $this->phpbb_container = $phpbb_container; + $this->php_ext = $this->phpbb_container->getParameter('core.php_ext'); + $this->root_path = $this->phpbb_container->getParameter('core.root_path'); + $this->cache_file = $this->phpbb_container->getParameter('core.cache_dir') . "queue.{$this->php_ext}"; + $this->filesystem = $this->phpbb_container->get('filesystem'); + $this->config = $this->phpbb_container->get('config'); + $this->dispatcher = $this->phpbb_container->get('dispatcher'); } /** @@ -829,25 +941,23 @@ class queue */ function process() { - global $config, $phpEx, $phpbb_root_path, $user, $phpbb_dispatcher; - $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); // avoid races, check file existence once $have_cache_file = file_exists($this->cache_file); - if (!$have_cache_file || $config['last_queue_run'] > time() - $config['queue_interval']) + if (!$have_cache_file || $this->config['last_queue_run'] > time() - $this->config['queue_interval']) { if (!$have_cache_file) { - $config->set('last_queue_run', time(), false); + $this->config->set('last_queue_run', time(), false); } $lock->release(); return; } - $config->set('last_queue_run', time(), false); + $this->config->set('last_queue_run', time(), false); include($this->cache_file); @@ -880,7 +990,7 @@ class queue { case 'email': // Delete the email queued objects if mailing is disabled - if (!$config['email_enable']) + if (!$this->config['email_enable']) { unset($this->queue_data['email']); continue 2; @@ -888,26 +998,26 @@ class queue break; case 'jabber': - if (!$config['jab_enable']) + if (!$this->config['jab_enable']) { unset($this->queue_data['jabber']); continue 2; } - include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); - $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], html_entity_decode($config['jab_password'], ENT_COMPAT), $config['jab_use_ssl'], $config['jab_verify_peer'], $config['jab_verify_peer_name'], $config['jab_allow_self_signed']); + include_once($this->root_path . 'includes/functions_jabber.' . $this->php_ext); + $this->jabber = new jabber($this->config['jab_host'], $this->config['jab_port'], $this->config['jab_username'], html_entity_decode($this->config['jab_password'], ENT_COMPAT), $this->config['jab_use_ssl'], $this->config['jab_verify_peer'], $this->config['jab_verify_peer_name'], $this->config['jab_allow_self_signed']); if (!$this->jabber->connect()) { $messenger = new messenger(); - $messenger->error('JABBER', $user->lang['ERR_JAB_CONNECT']); + $messenger->error('JABBER', $this->user->lang['ERR_JAB_CONNECT']); continue 2; } if (!$this->jabber->login()) { $messenger = new messenger(); - $messenger->error('JABBER', $user->lang['ERR_JAB_AUTH']); + $messenger->error('JABBER', $this->user->lang['ERR_JAB_AUTH']); continue 2; } @@ -928,42 +1038,33 @@ class queue case 'email': $break = false; /** - * Event to send message via external transport - * - * @event core.notification_message_process - * @var bool break Flag indicating if the function return after hook - * @var array addresses The message recipients - * @var string subject The message subject - * @var string msg The message text - * @since 3.2.4-RC1 - */ - $vars = array( + * Event to send message via external transport + * + * @event core.notification_message_process + * @var bool break Flag indicating if the function return after hook + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, subject, msg. + */ + $vars = [ 'break', - 'addresses', - 'subject', - 'msg', - ); - extract($phpbb_dispatcher->trigger_event('core.notification_message_process', compact($vars))); + 'email', + ]; + extract($this->dispatcher->trigger_event('core.notification_message_process', compact($vars))); if (!$break) { - $err_msg = ''; - $to = (!$to) ? 'undisclosed-recipients:;' : $to; + $messenger = new messenger(); + $transport = $messenger->get_transport(); + $mailer = new Mailer($transport); - if ($config['smtp_delivery']) + try { - $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); + $mailer->send($email); } - else + catch (TransportExceptionInterface $e) { - $encode_eol = $config['smtp_delivery'] || PHP_VERSION_ID >= 80000 ? "\r\n" : PHP_EOL; - $result = phpbb_mail($to, $subject, $msg, $headers, $encode_eol, $err_msg); - } - - if (!$result) - { - $messenger = new messenger(); - $messenger->error('EMAIL', $err_msg); + $messenger->error('EMAIL', $e->getDebug()); continue 2; } } @@ -1085,932 +1186,3 @@ class queue $lock->release(); } } - -/** -* Replacement or substitute for PHP's mail command -*/ -function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) -{ - global $config, $user; - - // Fix any bare linefeeds in the message to make it RFC821 Compliant. - $message = preg_replace("#(?lang['NO_EMAIL_SUBJECT'])) ? $user->lang['NO_EMAIL_SUBJECT'] : 'No email subject specified'; - return false; - } - - if (trim($message) == '') - { - $err_msg = (isset($user->lang['NO_EMAIL_MESSAGE'])) ? $user->lang['NO_EMAIL_MESSAGE'] : 'Email message was blank'; - return false; - } - - $mail_rcpt = $mail_to = $mail_cc = array(); - - // Build correct addresses for RCPT TO command and the client side display (TO, CC) - if (isset($addresses['to']) && count($addresses['to'])) - { - foreach ($addresses['to'] as $which_ary) - { - $mail_to[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>'; - $mail_rcpt['to'][] = '<' . trim($which_ary['email']) . '>'; - } - } - - if (isset($addresses['bcc']) && count($addresses['bcc'])) - { - foreach ($addresses['bcc'] as $which_ary) - { - $mail_rcpt['bcc'][] = '<' . trim($which_ary['email']) . '>'; - } - } - - if (isset($addresses['cc']) && count($addresses['cc'])) - { - foreach ($addresses['cc'] as $which_ary) - { - $mail_cc[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>'; - $mail_rcpt['cc'][] = '<' . trim($which_ary['email']) . '>'; - } - } - - $smtp = new smtp_class(); - - $errno = 0; - $errstr = ''; - - $smtp->add_backtrace('Connecting to ' . $config['smtp_host'] . ':' . $config['smtp_port']); - - // Ok we have error checked as much as we can to this point let's get on it already. - if (!class_exists('\phpbb\error_collector')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/error_collector.' . $phpEx); - } - $collector = new \phpbb\error_collector; - $collector->install(); - - $options = array(); - $verify_peer = (bool) $config['smtp_verify_peer']; - $verify_peer_name = (bool) $config['smtp_verify_peer_name']; - $allow_self_signed = (bool) $config['smtp_allow_self_signed']; - $remote_socket = $config['smtp_host'] . ':' . $config['smtp_port']; - - // Set ssl context options, see http://php.net/manual/en/context.ssl.php - $options['ssl'] = array('verify_peer' => $verify_peer, 'verify_peer_name' => $verify_peer_name, 'allow_self_signed' => $allow_self_signed); - $socket_context = stream_context_create($options); - - $smtp->socket = @stream_socket_client($remote_socket, $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $socket_context); - $collector->uninstall(); - $error_contents = $collector->format_errors(); - - if (!$smtp->socket) - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - } - - $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr"; - $err_msg .= ($error_contents) ? '

' . htmlspecialchars($error_contents, ENT_COMPAT) : ''; - return false; - } - - // Wait for reply - if ($err_msg = $smtp->server_parse('220', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Let me in. This function handles the complete authentication process - if ($err_msg = $smtp->log_into_server($config['smtp_host'], $config['smtp_username'], html_entity_decode($config['smtp_password'], ENT_COMPAT), $config['smtp_auth_method'])) - { - $smtp->close_session($err_msg); - return false; - } - - // From this point onward most server response codes should be 250 - // Specify who the mail is from.... - $smtp->server_send('MAIL FROM:<' . $config['board_email'] . '>'); - if ($err_msg = $smtp->server_parse('250', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Specify each user to send to and build to header. - $to_header = implode(', ', $mail_to); - $cc_header = implode(', ', $mail_cc); - - // Now tell the MTA to send the Message to the following people... [TO, BCC, CC] - $rcpt = false; - foreach ($mail_rcpt as $type => $mail_to_addresses) - { - foreach ($mail_to_addresses as $mail_to_address) - { - // Add an additional bit of error checking to the To field. - if (preg_match('#[^ ]+\@[^ ]+#', $mail_to_address)) - { - $smtp->server_send("RCPT TO:$mail_to_address"); - if ($err_msg = $smtp->server_parse('250', __LINE__)) - { - // We continue... if users are not resolved we do not care - if ($smtp->numeric_response_code != 550) - { - $smtp->close_session($err_msg); - return false; - } - } - else - { - $rcpt = true; - } - } - } - } - - // We try to send messages even if a few people do not seem to have valid email addresses, but if no one has, we have to exit here. - if (!$rcpt) - { - $user->session_begin(); - $err_msg .= '

'; - $err_msg .= (isset($user->lang['INVALID_EMAIL_LOG'])) ? sprintf($user->lang['INVALID_EMAIL_LOG'], htmlspecialchars($mail_to_address, ENT_COMPAT)) : '' . htmlspecialchars($mail_to_address, ENT_COMPAT) . ' possibly an invalid email address?'; - $smtp->close_session($err_msg); - return false; - } - - // Ok now we tell the server we are ready to start sending data - $smtp->server_send('DATA'); - - // This is the last response code we look for until the end of the message. - if ($err_msg = $smtp->server_parse('354', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Send the Subject Line... - $smtp->server_send("Subject: $subject"); - - // Now the To Header. - $to_header = ($to_header == '') ? 'undisclosed-recipients:;' : $to_header; - $smtp->server_send("To: $to_header"); - - // Now the CC Header. - if ($cc_header != '') - { - $smtp->server_send("CC: $cc_header"); - } - - // Now any custom headers.... - if ($headers !== false) - { - $smtp->server_send("$headers\r\n"); - } - - // Ok now we are ready for the message... - $smtp->server_send($message); - - // Ok the all the ingredients are mixed in let's cook this puppy... - $smtp->server_send('.'); - if ($err_msg = $smtp->server_parse('250', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Now tell the server we are done and close the socket... - $smtp->server_send('QUIT'); - $smtp->close_session($err_msg); - - return true; -} - -/** -* SMTP Class -* Auth Mechanisms originally taken from the AUTH Modules found within the PHP Extension and Application Repository (PEAR) -* See docs/AUTHORS for more details -*/ -class smtp_class -{ - var $server_response = ''; - var $socket = 0; - protected $socket_tls = false; - var $responses = array(); - var $commands = array(); - var $numeric_response_code = 0; - - var $backtrace = false; - var $backtrace_log = array(); - - function __construct() - { - // Always create a backtrace for admins to identify SMTP problems - $this->backtrace = true; - $this->backtrace_log = array(); - } - - /** - * Add backtrace message for debugging - */ - function add_backtrace($message) - { - if ($this->backtrace) - { - $this->backtrace_log[] = utf8_htmlspecialchars($message, ENT_COMPAT); - } - } - - /** - * Send command to smtp server - */ - function server_send($command, $private_info = false) - { - fputs($this->socket, $command . "\r\n"); - - (!$private_info) ? $this->add_backtrace("# $command") : $this->add_backtrace('# Omitting sensitive information'); - - // We could put additional code here - } - - /** - * We use the line to give the support people an indication at which command the error occurred - */ - function server_parse($response, $line) - { - global $user; - - $this->server_response = ''; - $this->responses = array(); - $this->numeric_response_code = 0; - - while (substr($this->server_response, 3, 1) != ' ') - { - if (!($this->server_response = fgets($this->socket, 256))) - { - return (isset($user->lang['NO_EMAIL_RESPONSE_CODE'])) ? $user->lang['NO_EMAIL_RESPONSE_CODE'] : 'Could not get mail server response codes'; - } - $this->responses[] = substr(rtrim($this->server_response), 4); - $this->numeric_response_code = (int) substr($this->server_response, 0, 3); - - $this->add_backtrace("LINE: $line <- {$this->server_response}"); - } - - if (!(substr($this->server_response, 0, 3) == $response)) - { - $this->numeric_response_code = (int) substr($this->server_response, 0, 3); - return (isset($user->lang['EMAIL_SMTP_ERROR_RESPONSE'])) ? sprintf($user->lang['EMAIL_SMTP_ERROR_RESPONSE'], $line, $this->server_response) : "Ran into problems sending Mail at Line $line. Response: $this->server_response"; - } - - return 0; - } - - /** - * Close session - */ - function close_session(&$err_msg) - { - fclose($this->socket); - - if ($this->backtrace) - { - $message = '

Backtrace

' . implode('
', $this->backtrace_log) . '

'; - $err_msg .= $message; - } - } - - /** - * Log into server and get possible auth codes if neccessary - */ - function log_into_server($hostname, $username, $password, $default_auth_method) - { - global $user; - - // Here we try to determine the *real* hostname (reverse DNS entry preferrably) - if (function_exists('php_uname') && !empty($local_host = php_uname('n'))) - { - // Able to resolve name to IP - if (($addr = @gethostbyname($local_host)) !== $local_host) - { - // Able to resolve IP back to name - if (!empty($name = @gethostbyaddr($addr)) && $name !== $addr) - { - $local_host = $name; - } - } - } - else - { - $local_host = $user->host; - } - - // If we are authenticating through pop-before-smtp, we - // have to login ones before we get authenticated - // NOTE: on some configurations the time between an update of the auth database takes so - // long that the first email send does not work. This is not a biggie on a live board (only - // the install mail will most likely fail) - but on a dynamic ip connection this might produce - // severe problems and is not fixable! - if ($default_auth_method == 'POP-BEFORE-SMTP' && $username && $password) - { - global $config; - - $errno = 0; - $errstr = ''; - - $this->server_send("QUIT"); - fclose($this->socket); - - $this->pop_before_smtp($hostname, $username, $password); - $username = $password = $default_auth_method = ''; - - // We need to close the previous session, else the server is not - // able to get our ip for matching... - if (!$this->socket = @fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 10)) - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - } - - $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr"; - return $err_msg; - } - - // Wait for reply - if ($err_msg = $this->server_parse('220', __LINE__)) - { - $this->close_session($err_msg); - return $err_msg; - } - } - - $hello_result = $this->hello($local_host); - if (!is_null($hello_result)) - { - return $hello_result; - } - - // SMTP STARTTLS (RFC 3207) - if (!$this->socket_tls) - { - $this->socket_tls = $this->starttls(); - - if ($this->socket_tls) - { - // Switched to TLS - // RFC 3207: "The client MUST discard any knowledge obtained from the server, [...]" - // So say hello again - $hello_result = $this->hello($local_host); - - if (!is_null($hello_result)) - { - return $hello_result; - } - } - } - - // If we are not authenticated yet, something might be wrong if no username and passwd passed - if (!$username || !$password) - { - return false; - } - - if (!isset($this->commands['AUTH'])) - { - return (isset($user->lang['SMTP_NO_AUTH_SUPPORT'])) ? $user->lang['SMTP_NO_AUTH_SUPPORT'] : 'SMTP server does not support authentication'; - } - - // Get best authentication method - $available_methods = explode(' ', $this->commands['AUTH']); - - // Define the auth ordering if the default auth method was not found - $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5'); - $method = ''; - - if (in_array($default_auth_method, $available_methods)) - { - $method = $default_auth_method; - } - else - { - foreach ($auth_methods as $_method) - { - if (in_array($_method, $available_methods)) - { - $method = $_method; - break; - } - } - } - - if (!$method) - { - return (isset($user->lang['NO_SUPPORTED_AUTH_METHODS'])) ? $user->lang['NO_SUPPORTED_AUTH_METHODS'] : 'No supported authentication methods'; - } - - $method = strtolower(str_replace('-', '_', $method)); - return $this->$method($username, $password); - } - - /** - * SMTP EHLO/HELO - * - * @return mixed Null if the authentication process is supposed to continue - * False if already authenticated - * Error message (string) otherwise - */ - protected function hello($hostname) - { - // Try EHLO first - $this->server_send("EHLO $hostname"); - if ($err_msg = $this->server_parse('250', __LINE__)) - { - // a 503 response code means that we're already authenticated - if ($this->numeric_response_code == 503) - { - return false; - } - - // If EHLO fails, we try HELO - $this->server_send("HELO $hostname"); - if ($err_msg = $this->server_parse('250', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - } - - foreach ($this->responses as $response) - { - $response = explode(' ', $response); - $response_code = $response[0]; - unset($response[0]); - $this->commands[$response_code] = implode(' ', $response); - } - - return null; - } - - /** - * SMTP STARTTLS (RFC 3207) - * - * @return bool Returns true if TLS was started - * Otherwise false - */ - protected function starttls() - { - global $config; - - // allow SMTPS (what was used by phpBB 3.0) if hostname is prefixed with tls:// or ssl:// - if (strpos($config['smtp_host'], 'tls://') === 0 || strpos($config['smtp_host'], 'ssl://') === 0) - { - return true; - } - - if (!function_exists('stream_socket_enable_crypto')) - { - return false; - } - - if (!isset($this->commands['STARTTLS'])) - { - return false; - } - - $this->server_send('STARTTLS'); - - if ($err_msg = $this->server_parse('220', __LINE__)) - { - return false; - } - - $result = false; - $stream_meta = stream_get_meta_data($this->socket); - - if (socket_set_blocking($this->socket, 1)) - { - // https://secure.php.net/manual/en/function.stream-socket-enable-crypto.php#119122 - $crypto = (phpbb_version_compare(PHP_VERSION, '5.6.7', '<')) ? STREAM_CRYPTO_METHOD_TLS_CLIENT : STREAM_CRYPTO_METHOD_SSLv23_CLIENT; - $result = stream_socket_enable_crypto($this->socket, true, $crypto); - socket_set_blocking($this->socket, (int) $stream_meta['blocked']); - } - - return $result; - } - - /** - * Pop before smtp authentication - */ - function pop_before_smtp($hostname, $username, $password) - { - global $user; - - if (!$this->socket = @fsockopen($hostname, 110, $errno, $errstr, 10)) - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - } - - return (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr"; - } - - $this->server_send("USER $username", true); - if ($err_msg = $this->server_parse('+OK', __LINE__)) - { - return $err_msg; - } - - $this->server_send("PASS $password", true); - if ($err_msg = $this->server_parse('+OK', __LINE__)) - { - return $err_msg; - } - - $this->server_send('QUIT'); - fclose($this->socket); - - return false; - } - - /** - * Plain authentication method - */ - function plain($username, $password) - { - $this->server_send('AUTH PLAIN'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $base64_method_plain = base64_encode("\0" . $username . "\0" . $password); - $this->server_send($base64_method_plain, true); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } - - /** - * Login authentication method - */ - function login($username, $password) - { - $this->server_send('AUTH LOGIN'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $this->server_send(base64_encode($username), true); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return $err_msg; - } - - $this->server_send(base64_encode($password), true); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } - - /** - * cram_md5 authentication method - */ - function cram_md5($username, $password) - { - $this->server_send('AUTH CRAM-MD5'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $md5_challenge = base64_decode($this->responses[0]); - $password = (strlen($password) > 64) ? pack('H32', md5($password)) : ((strlen($password) < 64) ? str_pad($password, 64, chr(0)) : $password); - $md5_digest = md5((substr($password, 0, 64) ^ str_repeat(chr(0x5C), 64)) . (pack('H32', md5((substr($password, 0, 64) ^ str_repeat(chr(0x36), 64)) . $md5_challenge)))); - - $base64_method_cram_md5 = base64_encode($username . ' ' . $md5_digest); - - $this->server_send($base64_method_cram_md5, true); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } - - /** - * digest_md5 authentication method - * A real pain in the *** - */ - function digest_md5($username, $password) - { - global $config, $user; - - $this->server_send('AUTH DIGEST-MD5'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $md5_challenge = base64_decode($this->responses[0]); - - // Parse the md5 challenge - from AUTH_SASL (PEAR) - $tokens = array(); - while (preg_match('/^([a-z-]+)=("[^"]+(?host; - } - - // Maxbuf - if (empty($tokens['maxbuf'])) - { - $tokens['maxbuf'] = 65536; - } - - // Required: nonce, algorithm - if (empty($tokens['nonce']) || empty($tokens['algorithm'])) - { - $tokens = array(); - } - $md5_challenge = $tokens; - - if (!empty($md5_challenge)) - { - $str = ''; - for ($i = 0; $i < 32; $i++) - { - $str .= chr(mt_rand(0, 255)); - } - $cnonce = base64_encode($str); - - $digest_uri = 'smtp/' . $config['smtp_host']; - - $auth_1 = sprintf('%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $username, $md5_challenge['realm'], $password))), $md5_challenge['nonce'], $cnonce); - $auth_2 = 'AUTHENTICATE:' . $digest_uri; - $response_value = md5(sprintf('%s:%s:00000001:%s:auth:%s', md5($auth_1), $md5_challenge['nonce'], $cnonce, md5($auth_2))); - - $input_string = sprintf('username="%s",realm="%s",nonce="%s",cnonce="%s",nc="00000001",qop=auth,digest-uri="%s",response=%s,%d', $username, $md5_challenge['realm'], $md5_challenge['nonce'], $cnonce, $digest_uri, $response_value, $md5_challenge['maxbuf']); - } - else - { - return (isset($user->lang['INVALID_DIGEST_CHALLENGE'])) ? $user->lang['INVALID_DIGEST_CHALLENGE'] : 'Invalid digest challenge'; - } - - $base64_method_digest_md5 = base64_encode($input_string); - $this->server_send($base64_method_digest_md5, true); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return $err_msg; - } - - $this->server_send(' '); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } -} - -/** - * Encodes the given string for proper display in UTF-8 or US-ASCII. - * - * This version is based on iconv_mime_encode() implementation - * from symfomy/polyfill-iconv - * https://github.com/symfony/polyfill-iconv/blob/fd324208ec59a39ebe776e6e9ec5540ad4f40aaa/Iconv.php#L355 - * - * @param string $str - * @param string $eol Lines delimiter (optional to be backwards compatible) - * - * @return string - */ -function mail_encode($str, $eol = "\r\n") -{ - // Check if string contains ASCII only characters - $is_ascii = strlen($str) === utf8_strlen($str); - - $scheme = $is_ascii ? 'Q' : 'B'; - - // Define start delimiter, end delimiter - // Use the Quoted-Printable encoding for ASCII strings to avoid unnecessary encoding in Base64 - $start = '=?' . ($is_ascii ? 'US-ASCII' : 'UTF-8') . '?' . $scheme . '?'; - $end = '?='; - - // Maximum encoded-word length is 75 as per RFC 2047 section 2. - // $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $eol . $end)!!! - $split_length = 75 - strlen($start . $eol . $end); - $split_length = $split_length - $split_length % 4; - - $line_length = strlen($start) + strlen($end); - $line_offset = strlen($start) + 1; - $line_data = ''; - - $is_quoted_printable = 'Q' === $scheme; - - preg_match_all('/./us', $str, $chars); - $chars = $chars[0] ?? []; - - $str = []; - foreach ($chars as $char) - { - $encoded_char = $is_quoted_printable - ? $char = preg_replace_callback( - '/[()<>@,;:\\\\".\[\]=_?\x20\x00-\x1F\x80-\xFF]/', - function ($matches) - { - $hex = dechex(ord($matches[0])); - $hex = strlen($hex) == 1 ? "0$hex" : $hex; - return '=' . strtoupper($hex); - }, - $char - ) - : base64_encode($line_data . $char); - - if (isset($encoded_char[$split_length - $line_length])) - { - if (!$is_quoted_printable) - { - $line_data = base64_encode($line_data); - } - $str[] = $start . $line_data . $end; - $line_length = $line_offset; - $line_data = ''; - } - - $line_data .= $char; - $is_quoted_printable && $line_length += strlen($char); - } - - if ($line_data !== '') - { - if (!$is_quoted_printable) - { - $line_data = base64_encode($line_data); - } - $str[] = $start . $line_data . $end; - } - - return implode($eol . ' ', $str); -} - -/** - * Wrapper for sending out emails with the PHP's mail function - */ -function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) -{ - global $config, $phpbb_root_path, $phpEx, $phpbb_dispatcher; - - // Convert Numeric Character References to UTF-8 chars (ie. Emojis) - $subject = utf8_decode_ncr($subject); - $msg = utf8_decode_ncr($msg); - - /** - * We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. - * On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... - * Reference: http://bugs.php.net/bug.php?id=15841 - */ - $headers = implode($eol, $headers); - - if (!class_exists('\phpbb\error_collector')) - { - include($phpbb_root_path . 'includes/error_collector.' . $phpEx); - } - - $collector = new \phpbb\error_collector; - $collector->install(); - - /** - * On some PHP Versions mail() *may* fail if there are newlines within the subject. - * Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. - * Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space - * (Use '' as parameter to mail_encode() results in SPACE used) - */ - $additional_parameters = $config['email_force_sender'] ? '-f' . $config['board_email'] : ''; - - /** - * Modify data before sending out emails with PHP's mail function - * - * @event core.phpbb_mail_before - * @var string to The message recipient - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers - * @var string eol The endline character - * @var string additional_parameters The additional parameters - * @since 3.3.6-RC1 - */ - $vars = [ - 'to', - 'subject', - 'msg', - 'headers', - 'eol', - 'additional_parameters', - ]; - extract($phpbb_dispatcher->trigger_event('core.phpbb_mail_before', compact($vars))); - - $result = mail($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers, $additional_parameters); - - /** - * Execute code after sending out emails with PHP's mail function - * - * @event core.phpbb_mail_after - * @var string to The message recipient - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers - * @var string eol The endline character - * @var string additional_parameters The additional parameters - * @var bool result True if the email was sent, false otherwise - * @since 3.3.6-RC1 - */ - $vars = [ - 'to', - 'subject', - 'msg', - 'headers', - 'eol', - 'additional_parameters', - 'result', - ]; - extract($phpbb_dispatcher->trigger_event('core.phpbb_mail_after', compact($vars))); - - $collector->uninstall(); - $err_msg = $collector->format_errors(); - - return $result; -} diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index d77f56c73f..554fe48a12 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -250,16 +250,16 @@ class message $messenger->to($recipient['address'], $recipient['name']); $messenger->im($recipient['jabber'], $recipient['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $this->server_name); - $messenger->headers('X-AntiAbuse: User IP - ' . $this->sender_ip); + $messenger->headers('X-AntiAbuse', 'Board servername - ' . $this->server_name); + $messenger->headers('X-AntiAbuse', 'User IP - ' . $this->sender_ip); if ($this->sender_id) { - $messenger->headers('X-AntiAbuse: User_id - ' . $this->sender_id); + $messenger->headers('X-AntiAbuse', 'User_id - ' . $this->sender_id); } if ($this->sender_username) { - $messenger->headers('X-AntiAbuse: Username - ' . $this->sender_username); + $messenger->headers('X-AntiAbuse', 'Username - ' . $this->sender_username); } $messenger->subject(html_entity_decode($this->subject, ENT_COMPAT)); diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index a346508624..e287bea407 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -70,6 +70,7 @@ class phpbb_email_parsing_test extends phpbb_test_case $phpbb_container->set('assets.bag', $assets_bag); $context = new \phpbb\template\context(); + $dispatcher = new \phpbb\event\dispatcher(); $twig = new \phpbb\template\twig\environment( $assets_bag, $config, @@ -78,7 +79,7 @@ class phpbb_email_parsing_test extends phpbb_test_case $cache_path, null, new \phpbb\template\twig\loader(''), - new \phpbb\event\dispatcher(), + $dispatcher, array( 'cache' => false, 'debug' => false, @@ -95,6 +96,16 @@ class phpbb_email_parsing_test extends phpbb_test_case $twig->addExtension($twig_extension); $phpbb_container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); + $phpbb_container->set('dispatcher', $dispatcher); + $phpbb_container->set('language', $lang); + $phpbb_container->set('request', $request); + + $db = $this->getMockBuilder('\phpbb\db\driver\mysqli') + ->disableOriginalConstructor() + ->getMock(); + $auth = $this->createMock('\phpbb\auth\auth'); + $log = new \phpbb\log\log($db, $user, $auth, $dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); + $phpbb_container->set('log', $log); if (!class_exists('messenger')) { diff --git a/tests/email/headers_encoding_test.php b/tests/email/headers_encoding_test.php deleted file mode 100644 index a884a4cc21..0000000000 --- a/tests/email/headers_encoding_test.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @license GNU General Public License, version 2 (GPL-2.0) - * - * For full copyright and license information, please see - * the docs/CREDITS.txt file. - * - */ - -class phpbb_headers_encoding_test extends phpbb_test_case -{ - protected function setUp(): void - { - global $phpbb_root_path, $phpEx; - - if (!function_exists('mail_encode')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - } - - public function headers_encoding_data() - { - return [ - ['test@yourdomain.com ', 'Q', 'US-ASCII'], - ['test@yourdomain.com <Несуществующий почтовый адрес phpBB>', 'B', 'UTF-8'], - ["\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88", 'B', 'UTF-8'], - ]; - } - - /** - * @dataProvider headers_encoding_data - */ - public function test_headers_encoding($header, $scheme, $encoding) - { - $encoded_string = mail_encode($header); - $this->assertStringStartsWith("=?$encoding?$scheme?", $encoded_string); - $this->assertStringEndsWith('?=', $encoded_string); - - // Result of iconv_mime_decode() on decoded header should be equal to initial header - $decoded_string = iconv_mime_decode($encoded_string, 0, $encoding); - $this->assertEquals(0, strcmp($header, $decoded_string)); - } -} From 715496b76de749c7008ee845f9eea58d41557003 Mon Sep 17 00:00:00 2001 From: rxu Date: Fri, 5 May 2023 21:24:15 +0700 Subject: [PATCH 02/29] [ticket/17135] Fix invalid smtp in tests PHPBB3-17135 --- phpBB/includes/functions_messenger.php | 4 ++-- tests/test_framework/phpbb_functional_test_case.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 390463fe3a..dd22f6bb9c 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -581,7 +581,7 @@ class messenger */ function get_transport($dummy = false) { - if ($dummy) + if ($dummy || empty($this->config['smtp_host'])) { $dsn = 'null://null'; } @@ -600,7 +600,7 @@ class messenger $transport = Transport::fromDsn($dsn); - if ($this->config['smtp_delivery']) + if ($this->config['smtp_delivery'] && $dsn != 'null://null') { // Set ssl context options, see http://php.net/manual/en/context.ssl.php $verify_peer = (bool) $this->config['smtp_verify_peer']; diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 2ce670d390..ddfca1e0be 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -418,7 +418,7 @@ class phpbb_functional_test_case extends phpbb_test_case $iohandler->set_input('email_enable', true); $iohandler->set_input('smtp_delivery', '1'); - $iohandler->set_input('smtp_host', 'nxdomain.phpbb.com'); + $iohandler->set_input('smtp_host', ''); $iohandler->set_input('smtp_auth', 'PLAIN'); $iohandler->set_input('smtp_user', 'nxuser'); $iohandler->set_input('smtp_pass', 'nxpass'); From d5f411a16d9245cdb93d81db26d3ade1e4787b28 Mon Sep 17 00:00:00 2001 From: rxu Date: Fri, 5 May 2023 23:31:01 +0700 Subject: [PATCH 03/29] [ticket/17135] Remove SMTP auth method option Symfony Mailer handles SMTP auth method internally. PHPBB3-17135 --- phpBB/docs/install-config.sample.yml | 1 - phpBB/includes/acp/acp_board.php | 25 ------------ .../includes/questionnaire/questionnaire.php | 1 - phpBB/install/schemas/schema_data.sql | 1 - phpBB/language/en/acp/board.php | 7 ---- .../data/v400/remove_smtp_auth_method.php | 38 +++++++++++++++++++ .../console/command/install/install.php | 1 - .../phpbb/install/installer_configuration.php | 3 -- .../task/add_config_settings.php | 1 - .../obtain_data/task/obtain_email_data.php | 20 ---------- .../phpbb_functional_test_case.php | 1 - vagrant/phpbb-install-config.yml | 1 - 12 files changed, 38 insertions(+), 62 deletions(-) create mode 100644 phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php diff --git a/phpBB/docs/install-config.sample.yml b/phpBB/docs/install-config.sample.yml index a354e52e2f..5ef6c643be 100644 --- a/phpBB/docs/install-config.sample.yml +++ b/phpBB/docs/install-config.sample.yml @@ -23,7 +23,6 @@ installer: smtp_delivery : ~ smtp_host: ~ smtp_port: ~ - smtp_auth: ~ smtp_user: ~ smtp_pass: ~ diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index bda5661278..2afa79b1e6 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -473,7 +473,6 @@ class acp_board 'smtp_delivery' => array('lang' => 'USE_SMTP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'smtp_host' => array('lang' => 'SMTP_SERVER', 'validate' => 'string', 'type' => 'text:25:50', 'explain' => true), 'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true), - 'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true), 'smtp_username' => array('lang' => 'SMTP_USERNAME', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true), 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true), 'smtp_verify_peer' => array('lang' => 'SMTP_VERIFY_PEER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), @@ -884,30 +883,6 @@ class acp_board ]; } - /** - * Select mail authentication method - */ - function mail_auth_select($selected_method, $key = '') - { - global $user; - - $auth_methods = ['PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP']; - $s_smtp_auth_options = []; - - foreach ($auth_methods as $method) - { - $s_smtp_auth_options[] = [ - 'value' => $method, - 'selected' => $selected_method == $method, - 'label' => $user->lang('SMTP_' . str_replace('-', '_', $method)), - ]; - } - - return [ - 'options' => $s_smtp_auth_options, - ]; - } - /** * Select full folder action */ diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php index 74675e0e03..319537f3e3 100644 --- a/phpBB/includes/questionnaire/questionnaire.php +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -435,7 +435,6 @@ class phpbb_questionnaire_phpbb_data_provider 'secure_downloads' => true, 'session_gc' => true, 'session_length' => true, - 'smtp_auth_method' => true, 'smtp_delivery' => true, 'topics_per_page' => true, 'version' => true, diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 21b26ee9c8..43b8f95fc8 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -287,7 +287,6 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('sitename_short', ' INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_path', 'images/smilies'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_per_page', '50'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_allow_self_signed', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_auth_method', 'PLAIN'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_delivery', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_host', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_port', '25'); diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 633df91138..e46091c954 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -553,15 +553,8 @@ $lang = array_merge($lang, array( 'SEND_TEST_EMAIL_EXPLAIN' => 'This will send a test email to the address defined in your account.', 'SMTP_ALLOW_SELF_SIGNED' => 'Allow self-signed SSL certificates', 'SMTP_ALLOW_SELF_SIGNED_EXPLAIN'=> 'Allow connections to SMTP server with self-signed SSL certificate.
Warning: Allowing self-signed SSL certificates may cause security implications.', - 'SMTP_AUTH_METHOD' => 'Authentication method for SMTP', - 'SMTP_AUTH_METHOD_EXPLAIN' => 'Only used if a username/password is set, ask your provider if you are unsure which method to use.', - 'SMTP_CRAM_MD5' => 'CRAM-MD5', - 'SMTP_DIGEST_MD5' => 'DIGEST-MD5', - 'SMTP_LOGIN' => 'LOGIN', 'SMTP_PASSWORD' => 'SMTP password', 'SMTP_PASSWORD_EXPLAIN' => 'Only enter a password if your SMTP server requires it.
Warning: This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.', - 'SMTP_PLAIN' => 'PLAIN', - 'SMTP_POP_BEFORE_SMTP' => 'POP-BEFORE-SMTP', 'SMTP_PORT' => 'SMTP server port', 'SMTP_PORT_EXPLAIN' => 'Only change this if you know your SMTP server is on a different port.', 'SMTP_SERVER' => 'SMTP server address', diff --git a/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php b/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php new file mode 100644 index 0000000000..eed17067b7 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php @@ -0,0 +1,38 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v400; + +use phpbb\db\migration\migration; + +class remove_smtp_auth_method extends migration +{ + public function effectively_installed() + { + return !$this->config->offsetExists('smtp_auth_method'); + } + + public static function depends_on() + { + return [ + '\phpbb\db\migration\data\v400\dev', + ]; + } + + public function update_data() + { + return [ + ['config.remove', ['smtp_auth_method']], + ]; + } +} diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php index 84c8aa688a..6641f9b944 100644 --- a/phpBB/phpbb/install/console/command/install/install.php +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -195,7 +195,6 @@ class install extends \phpbb\console\command\command $iohandler->set_input('smtp_delivery', $config['email']['smtp_delivery']); $iohandler->set_input('smtp_host', $config['email']['smtp_host']); $iohandler->set_input('smtp_port', $config['email']['smtp_port']); - $iohandler->set_input('smtp_auth', $config['email']['smtp_auth']); $iohandler->set_input('smtp_user', $config['email']['smtp_user']); $iohandler->set_input('smtp_pass', $config['email']['smtp_pass']); $iohandler->set_input('submit_email', 'submit'); diff --git a/phpBB/phpbb/install/installer_configuration.php b/phpBB/phpbb/install/installer_configuration.php index 974080dc55..f1051095e2 100644 --- a/phpBB/phpbb/install/installer_configuration.php +++ b/phpBB/phpbb/install/installer_configuration.php @@ -97,9 +97,6 @@ class installer_configuration implements ConfigurationInterface ->scalarNode('smtp_port') ->defaultValue(null) ->end() - ->scalarNode('smtp_auth') - ->defaultValue(null) - ->end() ->scalarNode('smtp_user') ->defaultValue(null) ->end() diff --git a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php index 5b9a9da536..14c88a04d3 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php +++ b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php @@ -150,7 +150,6 @@ class add_config_settings extends database_task 'smtp_delivery' => $this->install_config->get('smtp_delivery'), 'smtp_host' => $this->install_config->get('smtp_host'), 'smtp_port' => $this->install_config->get('smtp_port'), - 'smtp_auth_method' => $this->install_config->get('smtp_auth'), 'smtp_username' => $this->install_config->get('smtp_user'), 'smtp_password' => $this->install_config->get('smtp_pass'), diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php index 93c0eb385e..3c6508f6a7 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php @@ -52,12 +52,9 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta $smtp_delivery = $this->io_handler->get_input('smtp_delivery', ''); $smtp_host = $this->io_handler->get_input('smtp_host', '', true); $smtp_port = $this->io_handler->get_input('smtp_port', ''); - $smtp_auth = $this->io_handler->get_input('smtp_auth', ''); $smtp_user = $this->io_handler->get_input('smtp_user', '', true); $smtp_passwd = $this->io_handler->get_input('smtp_pass', '', true); - $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); - // Check if data is sent if ($this->io_handler->get_input('submit_email', false)) { @@ -65,22 +62,11 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta $this->install_config->set('smtp_delivery', $smtp_delivery); $this->install_config->set('smtp_host', $smtp_host); $this->install_config->set('smtp_port', $smtp_port); - $this->install_config->set('smtp_auth', $smtp_auth); $this->install_config->set('smtp_user', $smtp_user); $this->install_config->set('smtp_pass', $smtp_passwd); } else { - $auth_options = array(); - foreach ($auth_methods as $method) - { - $auth_options[] = array( - 'value' => $method, - 'label' => 'SMTP_' . str_replace('-', '_', $method), - 'selected' => false, - ); - } - $email_form = array( 'email_enable' => array( 'label' => 'ENABLE_EMAIL', @@ -126,12 +112,6 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta 'type' => 'text', 'default' => $smtp_port, ), - 'smtp_auth' => array( - 'label' => 'SMTP_AUTH_METHOD', - 'description' => 'SMTP_AUTH_METHOD_EXPLAIN', - 'type' => 'select', - 'options' => $auth_options, - ), 'smtp_user' => array( 'label' => 'SMTP_USERNAME', 'description' => 'SMTP_USERNAME_EXPLAIN', diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index ddfca1e0be..3e9b654b0e 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -419,7 +419,6 @@ class phpbb_functional_test_case extends phpbb_test_case $iohandler->set_input('email_enable', true); $iohandler->set_input('smtp_delivery', '1'); $iohandler->set_input('smtp_host', ''); - $iohandler->set_input('smtp_auth', 'PLAIN'); $iohandler->set_input('smtp_user', 'nxuser'); $iohandler->set_input('smtp_pass', 'nxpass'); $iohandler->set_input('submit_email', 'submit'); diff --git a/vagrant/phpbb-install-config.yml b/vagrant/phpbb-install-config.yml index db7b525b9f..0b89958299 100644 --- a/vagrant/phpbb-install-config.yml +++ b/vagrant/phpbb-install-config.yml @@ -38,7 +38,6 @@ installer: enabled: false smtp_delivery : ~ smtp_host: ~ - smtp_auth: ~ smtp_user: ~ smtp_pass: ~ From 3ef7f806b3882e99420e1eca4618a8cd3773465f Mon Sep 17 00:00:00 2001 From: rxu Date: Fri, 12 May 2023 19:56:16 +0700 Subject: [PATCH 04/29] [ticket/17135] Further formatting and adjusting the messenger code PHPBB3-17135 --- phpBB/includes/functions_messenger.php | 431 ++++++++++++++++--------- tests/email/email_parsing_test.php | 2 + 2 files changed, 284 insertions(+), 149 deletions(-) diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index dd22f6bb9c..6a32349d4f 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -1,15 +1,15 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; @@ -18,18 +18,19 @@ use Symfony\Component\Mime\Email; use Symfony\Component\Mime\Header\Headers; /** -* @ignore -*/ + * @ignore + */ if (!defined('IN_PHPBB')) { exit; } /** -* Messenger -*/ + * Messenger class + */ class messenger { + /** @var array */ private const PRIORITY_MAP = [ Email::PRIORITY_HIGHEST => 'Highest', Email::PRIORITY_HIGH => 'High', @@ -37,6 +38,8 @@ class messenger Email::PRIORITY_LOW => 'Low', Email::PRIORITY_LOWEST => 'Lowest', ]; + + /** @var array */ private const HEADER_CLASS_MAP = [ 'date' => DateHeader::class, 'from' => MailboxListHeader::class, @@ -51,11 +54,22 @@ class messenger 'return-path' => PathHeader::class, ]; - var $msg, $replyto, $from, $subject; - var $addresses = []; - var $extra_headers = []; + /** @var array */ + protected $addresses = []; /** + * @var string + * + * Symfony Mailer transport DSN + */ + protected $dsn = ''; + + /** @var string */ + protected $from; + + /** + * @var int + * * Possible values are: * Email::PRIORITY_HIGHEST * Email::PRIORITY_HIGH @@ -63,18 +77,34 @@ class messenger * Email::PRIORITY_LOW * Email::PRIORITY_LOWEST */ - var $mail_priority = Email::PRIORITY_NORMAL; - var $use_queue = true; + protected $mail_priority = Email::PRIORITY_NORMAL; + + /** @var string */ + protected $msg; + + /** @var string */ + protected $replyto; + + /** @var string */ + protected $subject; /** @var \phpbb\template\template */ protected $template; + /** @var Symfony\Component\Mailer\Transport */ + protected $transport; + + /** @var bool */ + protected $use_queue = true; + /** - * Constructor + * Messenger class constructor + * + * @param bool $use_queue Flag to switch the use of the messenger file queue */ function __construct($use_queue = true) { - global $phpbb_container, $phpbb_root_path, $phpEx; + global $phpbb_container; $this->phpbb_container = $phpbb_container; $this->config = $this->phpbb_container->get('config'); @@ -87,16 +117,19 @@ class messenger $this->headers = $this->email->getHeaders(); $this->use_queue = (!$this->config['email_package_size']) ? false : $use_queue; $this->subject = ''; - $this->root_path = $phpbb_root_path; - $this->php_ext = $phpEx; + $this->php_ext = $this->phpbb_container->getParameter('core.php_ext'); + $this->root_path = $this->phpbb_container->getParameter('core.root_path'); + $this->set_transport(); } /** * Resets all the data (address, template file, etc etc) to default + * + * @return void */ - function reset() + public function reset() { - $this->addresses = $this->extra_headers = []; + $this->addresses = []; $this->msg = $this->replyto = $this->from = ''; $this->mail_priority = Email::PRIORITY_NORMAL; } @@ -105,8 +138,9 @@ class messenger * Set addresses for to/im as available * * @param array $user User row + * @return void */ - function set_addresses($user) + public function set_addresses($user) { if (isset($user['user_email']) && $user['user_email']) { @@ -120,9 +154,13 @@ class messenger } /** - * Sets an email address to send to + * Sets email address to send to + * + * @param string $address Email "To" recipient address + * @param string $realname Email "To" recipient name + * @return void */ - function to($address, $realname = '') + public function to($address, $realname = '') { if (!trim($address)) { @@ -137,9 +175,13 @@ class messenger } /** - * Sets an cc address to send to + * Sets cc address to send to + * + * @param string $address Email carbon copy recipient address + * @param string $realname Email carbon copy recipient name + * @return void */ - function cc($address, $realname = '') + public function cc($address, $realname = '') { if (!trim($address)) { @@ -151,9 +193,13 @@ class messenger } /** - * Sets an bcc address to send to + * Sets bcc address to send to + * + * @param string $address Email black carbon copy recipient address + * @param string $realname Email black carbon copy recipient name + * @return void */ - function bcc($address, $realname = '') + public function bcc($address, $realname = '') { if (!trim($address)) { @@ -166,8 +212,12 @@ class messenger /** * Sets a im contact to send to + * + * @param string $address Jabber recipient address + * @param string $realname Jabber recipient name + * @return void */ - function im($address, $realname = '') + public function im($address, $realname = '') { // IM-Addresses could be empty if (!trim($address)) @@ -182,8 +232,11 @@ class messenger /** * Set the reply to address + * + * @param string $address Email "Reply to" address + * @return void */ - function replyto($address) + public function replyto($address) { $this->replyto = new Address(trim($address)); $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); @@ -191,25 +244,36 @@ class messenger /** * Set the from address + * + * @param string $address Email "from" address + * @return void */ - function from($address) + public function from($address) { $this->from = new Address(trim($address)); $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); } /** - * set up subject for mail + * Set up subject for mail + * + * @param string $subject Email subject + * @return void */ - function subject($subject = '') + public function subject($subject = '') { - $this->email->subject(trim($subject)); + $this->subject = $subject; + $this->email->subject(trim($this->subject)); } /** - * set up extra mail headers + * Set up extra mail headers + * + * @param string $header_name Email header name + * @param string $header_value Email header body + * @return void */ - function headers($header_name, $header_value) + public function headers($header_name, $header_value) { $this->headers->addTextHeader(trim($header_name), trim($header_value)); } @@ -221,7 +285,7 @@ class messenger * @param \phpbb\user $user User object * @return void */ - function anti_abuse_headers($config, $user) + public function anti_abuse_headers($config, $user) { $this->headers->addTextHeader('X-AntiAbuse', 'Board servername - ' . $config['server_name']); $this->headers->addTextHeader('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); @@ -231,22 +295,33 @@ class messenger /** * Set the email priority + * * Possible values are: - * Email::PRIORITY_HIGHEST - * Email::PRIORITY_HIGH - * Email::PRIORITY_NORMAL - * Email::PRIORITY_LOW - * Email::PRIORITY_LOWEST + * Email::PRIORITY_HIGHEST = 1 + * Email::PRIORITY_HIGH = 2 + * Email::PRIORITY_NORMAL = 3 + * Email::PRIORITY_LOW = 4 + * Email::PRIORITY_LOWEST = 5 + * + * @param int $priority Email priority level + * @return void */ - function set_mail_priority($priority = Email::PRIORITY_NORMAL) + public function set_mail_priority($priority = Email::PRIORITY_NORMAL) { $this->email->priority($priority); } /** * Set email template to use + * + * @param string $template_file Email template file name + * @param string $template_lang Email template language + * @param string $template_path Email template path + * @param string $template_dir_prefix Email template directory prefix + * + * @return bool */ - function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') + public function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') { $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; @@ -265,27 +340,27 @@ class messenger $template_lang = basename($this->config['default_lang']); } - $ext_template_paths = array( - array( + $ext_template_paths = [ + [ 'name' => $template_lang . '_email', 'ext_path' => 'language/' . $template_lang . '/email' . $template_dir_prefix, - ), - ); + ], + ]; if ($template_path) { - $template_paths = array( + $template_paths = [ $template_path . $template_dir_prefix, - ); + ]; } else { $template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; $template_path .= $template_lang . '/email'; - $template_paths = array( + $template_paths = [ $template_path . $template_dir_prefix, - ); + ]; $board_language = basename($this->config['default_lang']); @@ -298,10 +373,10 @@ class messenger $template_paths[] = $fallback_template_path . $template_dir_prefix; - $ext_template_paths[] = array( + $ext_template_paths[] = [ 'name' => $board_language . '_email', 'ext_path' => 'language/' . $board_language . '/email' . $template_dir_prefix, - ); + ]; } // If everything fails just fall back to en template if ($template_lang !== 'en' && $board_language !== 'en') @@ -311,33 +386,36 @@ class messenger $template_paths[] = $fallback_template_path . $template_dir_prefix; - $ext_template_paths[] = array( + $ext_template_paths[] = [ 'name' => 'en_email', 'ext_path' => 'language/en/email' . $template_dir_prefix, - ); + ]; } } $this->set_template_paths($ext_template_paths, $template_paths); - $this->template->set_filenames(array( + $this->template->set_filenames([ 'body' => $template_file . '.txt', - )); + ]); return true; } /** - * assign variables to email template + * Assign variables to email template + * + * @param array $vars Array of VAR => VALUE to assign to email template + * @return void */ - function assign_vars($vars) + public function assign_vars($vars) { $this->setup_template(); $this->template->assign_vars($vars); } - function assign_block_vars($blockname, $vars) + public function assign_block_vars($blockname, $vars) { $this->setup_template(); @@ -345,15 +423,14 @@ class messenger } /** - * Send the mail out to the recipients set previously in var $this->addresses + * Send the mail out to the recipients * * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH * @param bool $break Flag indicating if the function only formats the subject * and the message without sending it - * * @return bool */ - function send($method = NOTIFY_EMAIL, $break = false) + public function send($method = NOTIFY_EMAIL, $break = false) { // We add some standard variables we always use, no need to specify them always $this->assign_vars([ @@ -411,7 +488,7 @@ class messenger // We now try and pull a subject from the email body ... if it exists, // do this here because the subject may contain a variable $drop_header = ''; - $match = array(); + $match = []; if (preg_match('#^(Subject:(.*?))$#m', $this->msg, $match)) { $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); @@ -463,8 +540,12 @@ class messenger /** * Add error message to log + * + * @param string $type Error type: EMAIL / etc + * @param string $msg Error message text + * @return void */ - function error($type, $msg) + public function error($type, $msg) { // Session doesn't exist, create it if (!isset($this->user->session_id) || $this->user->session_id === '') @@ -490,9 +571,10 @@ class messenger } /** - * Save to queue + * Save message data to the messemger file queue + * @return void */ - function save_queue() + public function save_queue() { if ($this->config['email_package_size'] && $this->use_queue && !empty($this->queue)) { @@ -502,11 +584,12 @@ class messenger } /** - * Detect proper method to add header + * Detect proper Header class method to add header * + * @param string $name Email header name * @return string */ - public function get_header_method(string $name) + protected function get_header_method(string $name) { $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); $method = 'add'.ucfirst(array_pop($parts)); @@ -524,8 +607,10 @@ class messenger /** * Set email headers + * + * @return bool */ - function build_header() + protected function build_header() { $headers = []; @@ -557,7 +642,7 @@ class messenger * @var array headers Array containing email header entries * @since 3.1.11-RC1 */ - $vars = array('headers'); + $vars = ['headers']; extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); foreach ($headers as $header => $value) @@ -574,33 +659,64 @@ class messenger } /** - * Generates a valid transport to send email + * Generates valid DSN for Symfony Mailer transport * - * @param bool $dummy Flag to disable mail delivery - * @return Symfony\Component\Mailer\Transport Symfony Transport object + * @param string $dsn Symfony Mailer transport DSN + * @return void */ - function get_transport($dummy = false) + public function set_dsn($dsn = '') { - if ($dummy || empty($this->config['smtp_host'])) + if (!empty($dsn)) { - $dsn = 'null://null'; + $this->dsn = $dsn; } else if ($this->config['smtp_delivery']) { - $user = urlencode($this->config['smtp_username']); - $password = urlencode($this->config['smtp_password']); - $smtp_host = urlencode($this->config['smtp_host']); - $smtp_port = $this->config['smtp_port']; - $dsn = "smtp://$user:$password@$smtp_host:$smtp_port"; + if (empty($this->config['smtp_host'])) + { + $this->dsn = 'null://null'; + } + else + { + $user = urlencode($this->config['smtp_username']); + $password = urlencode($this->config['smtp_password']); + $smtp_host = urlencode($this->config['smtp_host']); + $smtp_port = $this->config['smtp_port']; + + $this->dsn = "smtp://$user:$password@$smtp_host:$smtp_port"; + } } else { - $dsn = 'sendmail://default'; + $this->dsn = 'sendmail://default'; + } + } + + /** + * Get Symfony Mailer transport DSN + * + * @return void + */ + public function get_dsn() + { + return $this->dsn; + } + + /** + * Generates a valid transport to send email + * + * @return void + */ + public function set_transport() + { + if (empty($this->dsn)) + { + $this->set_dsn(); } - $transport = Transport::fromDsn($dsn); + $this->transport = Transport::fromDsn($this->dsn); - if ($this->config['smtp_delivery'] && $dsn != 'null://null') + if ($this->config['smtp_delivery'] && !in_array($this->dsn, ['null://null', 'sendmail://default'])) { // Set ssl context options, see http://php.net/manual/en/context.ssl.php $verify_peer = (bool) $this->config['smtp_verify_peer']; @@ -613,16 +729,26 @@ class messenger 'allow_self_signed' => $allow_self_signed, ] ]; - $transport->getStream()->setStreamOptions($options); + $this->transport->getStream()->setStreamOptions($options); } + } - return $transport; + /** + * Get mailer transport object + * + * @return Symfony\Component\Mailer\Transport Symfony Mailer transport object + */ + public function get_transport() + { + return $this->transport; } /** * Send out emails + * + * @return bool */ - function msg_email() + protected function msg_email() { if (empty($this->config['email_enable'])) { @@ -665,12 +791,12 @@ class messenger * @since 3.2.4-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses */ - $vars = array( + $vars = [ 'break', 'subject', 'msg', 'email', - ); + ]; extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); $this->addresses = $addresses; @@ -699,8 +825,7 @@ class messenger // Send message ... if (!$use_queue) { - $transport = $this->get_transport(); - $mailer = new Mailer($transport); + $mailer = new Mailer($this->transport); $subject = $this->subject; $msg = $this->msg; @@ -770,9 +895,11 @@ class messenger } /** - * Send jabber message out - */ - function msg_jabber() + * Send jabber message out + * + * @return bool + */ + protected function msg_jabber() { if (empty($this->config['jab_enable']) || empty($this->config['jab_host']) || empty($this->config['jab_username']) || empty($this->config['jab_password'])) { @@ -796,7 +923,7 @@ class messenger $use_queue = true; } - $addresses = array(); + $addresses = []; foreach ($this->addresses['im'] as $type => $uid_ary) { $addresses[] = $uid_ary['uid']; @@ -829,19 +956,21 @@ class messenger } else { - $this->queue->put('jabber', array( + $this->queue->put('jabber', [ 'addresses' => $addresses, 'subject' => $this->subject, - 'msg' => $this->msg) - ); + 'msg' => $this->msg + ]); } unset($addresses); return true; } /** - * Setup template engine - */ + * Setup template engine + * + * @return void + */ protected function setup_template() { if ($this->template instanceof \phpbb\template\template) @@ -875,8 +1004,12 @@ class messenger } /** - * Set template paths to load - */ + * Set template paths to load + * + * @param string $path_name Email template path name + * @param string $paths Email template paths + * @return void + */ protected function set_template_paths($path_name, $paths) { $this->setup_template(); @@ -886,15 +1019,18 @@ class messenger } /** -* handling email and jabber queue -*/ + * Handling messenger file queue + */ class queue { - var $data = []; - var $queue_data = []; - var $package_size = 0; - var $cache_file = ''; - var $eol = "\n"; + /** @var array */ + protected $data = []; + + /** @var array */ + protected $queue_data = []; + + /** @var string */ + protected $cache_file = ''; /** * @var \phpbb\filesystem\filesystem_interface @@ -902,8 +1038,8 @@ class queue protected $filesystem; /** - * constructor - */ + * Messenger file queue class constructor + */ function __construct() { global $phpbb_container; @@ -918,28 +1054,37 @@ class queue } /** - * Init a queue object - */ - function init($object, $package_size) + * Init a queue object + * + * @param string $object Queue object type: email/jabber/etc + * @param int $package_size Size of the messenger package to send + * @return void + */ + public function init($object, $package_size) { - $this->data[$object] = array(); + $this->data[$object] = []; $this->data[$object]['package_size'] = $package_size; - $this->data[$object]['data'] = array(); + $this->data[$object]['data'] = []; } /** - * Put object in queue - */ - function put($object, $scope) + * Put message into the messenger file queue + * + * @param string $object Queue object type: email/jabber/etc + * @param mixed $message_data Message data to send + * @return void + */ + public function put($object, $message_data) { - $this->data[$object]['data'][] = $scope; + $this->data[$object]['data'][] = $message_data; } /** - * Process queue - * Using lock file - */ - function process() + * Process the messemger file queue (using lock file) + * + * @return void + */ + public function process() { $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); @@ -973,19 +1118,6 @@ class queue $package_size = $data_ary['package_size']; $num_items = (!$package_size || count($data_ary['data']) < $package_size) ? count($data_ary['data']) : $package_size; - /* - * This code is commented out because it causes problems on some web hosts. - * The core problem is rather restrictive email sending limits. - * This code is nly useful if you have no such restrictions from the - * web host and the package size setting is wrong. - - // If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs... - if (count($data_ary['data']) > $package_size * 2.5) - { - $num_items = count($data_ary['data']); - } - */ - switch ($object) { case 'email': @@ -1055,8 +1187,7 @@ class queue if (!$break) { $messenger = new messenger(); - $transport = $messenger->get_transport(); - $mailer = new Mailer($transport); + $mailer = new Mailer($messenger->get_transport()); try { @@ -1132,9 +1263,11 @@ class queue } /** - * Save queue - */ - function save() + * Save message data to the messenger file queue + * + * @return void + */ + public function save() { if (!count($this->data)) { @@ -1180,7 +1313,7 @@ class queue // Do nothing } - $this->data = array(); + $this->data = []; } $lock->release(); diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index e287bea407..dd7b055ac7 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -106,6 +106,8 @@ class phpbb_email_parsing_test extends phpbb_test_case $auth = $this->createMock('\phpbb\auth\auth'); $log = new \phpbb\log\log($db, $user, $auth, $dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); $phpbb_container->set('log', $log); + $phpbb_container->setParameter('core.root_path', $phpbb_root_path); + $phpbb_container->setParameter('core.php_ext', $phpEx); if (!class_exists('messenger')) { From 1869b2a99e1d79c44706f600fe95bd54881c4be2 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 23 May 2023 14:03:07 +0700 Subject: [PATCH 05/29] [ticket/17135] Further formatting and adjusting the messenger code PHPBB3-17135 --- phpBB/includes/functions_jabber.php | 427 +++++++++++++++---------- phpBB/includes/functions_messenger.php | 145 ++++++--- 2 files changed, 360 insertions(+), 212 deletions(-) diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php index ec7d090257..282e6105a2 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/includes/functions_jabber.php @@ -31,65 +31,134 @@ if (!defined('IN_PHPBB')) */ class jabber { - var $connection = null; - var $session = array(); - var $timeout = 10; + /** @var string */ + protected $connect_server; - var $server; - var $connect_server; - var $port; - var $username; - var $password; - var $use_ssl; - var $verify_peer; - var $verify_peer_name; - var $allow_self_signed; - var $resource = 'functions_jabber.phpbb.php'; + /** @var resource */ + protected $connection = null; - var $enable_logging; - var $log_array; + /** @var bool */ + protected $enable_logging = true; - var $features = array(); + /** @var array */ + protected $features = []; + + /** @var array */ + protected $jid = []; + + /** @var array */ + protected $log_array = []; + + /** @var string */ + protected $password; + + /** @var string */ + protected $port; + + /** @var string */ + protected $resource = 'functions_jabber.phpbb.php'; + + /** @var string */ + protected $server; + + /** @var array */ + protected $session = []; + + /** @var array */ + protected $stream_options = []; + + /** @var int */ + protected $timeout = 10; + + /** @var bool */ + protected $use_ssl = false; + + /** @var string */ + protected $username; /** @var string Stream close handshake */ private const STREAM_CLOSE_HANDSHAKE = ''; /** - * Constructor - * - * @param string $server Jabber server - * @param int $port Jabber server port - * @param string $username Jabber username or JID - * @param string $password Jabber password - * @param bool $use_ssl Use ssl - * @param bool $verify_peer Verify SSL certificate - * @param bool $verify_peer_name Verify Jabber peer name - * @param bool $allow_self_signed Allow self signed certificates - */ - function __construct($server, $port, $username, $password, $use_ssl = false, $verify_peer = true, $verify_peer_name = true, $allow_self_signed = false) + * Jabber class constructor + * + * Use (username() call should go before server() + * and ssl() call should go before port() and stream_options()): + * + * new jabber() + * -> username($username) + * -> password($password) + * -> ssl($use_ssl) + * -> server($server) + * -> port($port) + * -> stream_options( + * 'verify_peer' => true, + * 'verify_peer_name' => true, + * 'allow_self_signed' => false, + * ); + */ + function __construct() { - $this->connect_server = ($server) ? $server : 'localhost'; - $this->port = ($port) ? $port : 5222; + } - // Get the server and the username - if (strpos($username, '@') === false) + /** + * Set ssl context options + * See http://php.net/manual/en/context.ssl.php + * + * @param array $options SSL context options array + * @return $this + */ + public function stream_options($options = []) + { + if ($this->use_ssl) { - $this->server = $this->connect_server; - $this->username = $username; - } - else - { - $jid = explode('@', $username, 2); - - $this->username = $jid[0]; - $this->server = $jid[1]; + // Set default stream options and change it if needed + $this->stream_options['ssl'] = array_merge([ + 'verify_peer' => true, + 'verify_peer_name' => true, + 'allow_self_signed' => false, + ], $options); } - $this->password = $password; - $this->use_ssl = ($use_ssl && self::can_use_ssl()) ? true : false; - $this->verify_peer = $verify_peer; - $this->verify_peer_name = $verify_peer_name; - $this->allow_self_signed = $allow_self_signed; + return $this; + } + + /** + * Set password to connect to server + * + * @param string $password Password to connect to server + * @return $this + */ + public function password($password = '') + { + $this->password = $password; + + return $this; + } + + /** + * Set use of ssl to connect to server + * + * @param bool $use_ssl Flag indicating use of ssl to connect to server + * @return $this + */ + public function ssl($use_ssl = false) + { + $this->use_ssl = $use_ssl && self::can_use_ssl(); + + return $this; + } + + /** + * Set port to connect to server + * use_ssl flag should be set first + * + * @param string $port Port to connect to server + * @return $this + */ + public function port($port = '') + { + $this->port = ($port) ? $port : 5222; // Change port if we use SSL if ($this->port == 5222 && $this->use_ssl) @@ -97,21 +166,56 @@ class jabber $this->port = 5223; } - $this->enable_logging = true; - $this->log_array = array(); + return $this; } /** - * Able to use the SSL functionality? - */ + * Set username to connect to server + * + * @param string $username Username to connect to server + * @return $this + */ + public function username($username = '') + { + if (strpos($username, '@') === false) + { + $this->username = $username; + } + else + { + $this->jid = explode('@', $username, 2); + $this->username = $this->jid[0]; + } + + return $this; + } + + /** + * Set server to connect + * Username should be set first + * + * @param string $server Server to connect + * @return $this + */ + public function server($server = '') + { + $this->connect_server = ($server) ? $server : 'localhost'; + $this->server = $this->jid[1] ?? $this->connect_server; + + return $this; + } + + /** + * Able to use the SSL functionality? + */ public static function can_use_ssl() { return @extension_loaded('openssl'); } /** - * Able to use TLS? - */ + * Able to use TLS? + */ public static function can_use_tls() { if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('stream_set_blocking') || !function_exists('stream_get_wrappers')) @@ -135,19 +239,19 @@ class jabber } /** - * Sets the resource which is used. No validation is done here, only escaping. - * @param string $name - * @access public - */ - function set_resource($name) + * Sets the resource which is used. No validation is done here, only escaping. + * @param string $name + * @access public + */ + public function set_resource($name) { $this->resource = $name; } /** - * Connect - */ - function connect() + * Connect + */ + public function connect() { /* if (!$this->check_jid($this->username . '@' . $this->server)) { @@ -157,7 +261,7 @@ class jabber $this->session['ssl'] = $this->use_ssl; - if ($this->open_socket($this->connect_server, $this->port, $this->use_ssl, $this->verify_peer, $this->verify_peer_name, $this->allow_self_signed)) + if ($this->open_socket($this->connect_server, $this->port)) { $this->send("\n"); $this->send("\n"); @@ -174,9 +278,9 @@ class jabber } /** - * Disconnect - */ - function disconnect() + * Disconnect + */ + public function disconnect() { if ($this->connected()) { @@ -195,7 +299,7 @@ class jabber $this->add_to_log("Error: Unexpected stream close handshake reply ”{$stream_close_reply}”"); } - $this->session = array(); + $this->session = []; return fclose($this->connection); } @@ -203,20 +307,20 @@ class jabber } /** - * Connected? - */ - function connected() + * Connected? + */ + public function connected() { - return (is_resource($this->connection) && !feof($this->connection)) ? true : false; + return is_resource($this->connection) && !feof($this->connection); } /** - * Initiates login (using data from contructor, after calling connect()) - * @access public - * @return bool - */ - function login() + * Initiates login (using data from contructor, after calling connect()) + * + * @return bool + */ + public function login() { if (empty($this->features)) { @@ -228,12 +332,13 @@ class jabber } /** - * Send data to the Jabber server - * @param string $xml - * @access public - * @return bool - */ - function send($xml) + * Send data to the Jabber server + * + * @param string $xml + * + * @return bool + */ + public function send($xml) { if ($this->connected()) { @@ -248,17 +353,14 @@ class jabber } /** - * OpenSocket - * @param string $server host to connect to - * @param int $port port number - * @param bool $use_ssl use ssl or not - * @param bool $verify_peer verify ssl certificate - * @param bool $verify_peer_name verify peer name - * @param bool $allow_self_signed allow self-signed ssl certificates - * @access public - * @return bool - */ - function open_socket($server, $port, $use_ssl, $verify_peer, $verify_peer_name, $allow_self_signed) + * OpenSocket + * + * @param string $server host to connect to + * @param int $port port number + * + * @return bool + */ + public function open_socket($server, $port) { if (@function_exists('dns_get_record')) { @@ -269,21 +371,8 @@ class jabber } } - $options = array(); - - if ($use_ssl) - { - $remote_socket = 'ssl://' . $server . ':' . $port; - - // Set ssl context options, see http://php.net/manual/en/context.ssl.php - $options['ssl'] = array('verify_peer' => $verify_peer, 'verify_peer_name' => $verify_peer_name, 'allow_self_signed' => $allow_self_signed); - } - else - { - $remote_socket = $server . ':' . $port; - } - - $socket_context = stream_context_create($options); + $remote_socket = $this->use_ssl ? 'ssl://' . $server . ':' . $port : $server . ':' . $port; + $socket_context = stream_context_create($this->stream_options); if ($this->connection = @stream_socket_client($remote_socket, $errorno, $errorstr, $this->timeout, STREAM_CLIENT_CONNECT, $socket_context)) { @@ -299,9 +388,9 @@ class jabber } /** - * Return log - */ - function get_log() + * Return log + */ + public function get_log() { if ($this->enable_logging && count($this->log_array)) { @@ -312,9 +401,9 @@ class jabber } /** - * Add information to log - */ - function add_to_log($string) + * Add information to log + */ + protected function add_to_log($string) { if ($this->enable_logging) { @@ -323,12 +412,12 @@ class jabber } /** - * Listens to the connection until it gets data or the timeout is reached. - * Thus, it should only be called if data is expected to be received. - * @access public - * @return mixed either false for timeout or an array with the received data - */ - function listen($timeout = 10, $wait = false) + * Listens to the connection until it gets data or the timeout is reached. + * Thus, it should only be called if data is expected to be received. + * + * @return mixed either false for timeout or an array with the received data + */ + public function listen($timeout = 10, $wait = false) { if (!$this->connected()) { @@ -358,11 +447,11 @@ class jabber } /** - * Initiates account registration (based on data used for contructor) - * @access public - * @return bool - */ - function register() + * Initiates account registration (based on data used for contructor) + * + * @return bool + */ + public function register() { if (!isset($this->session['id']) || isset($this->session['jid'])) { @@ -375,13 +464,14 @@ class jabber } /** - * Sets account presence. No additional info required (default is "online" status) - * @param $message online, offline... - * @param $type dnd, away, chat, xa or nothing - * @param $unavailable set this to true if you want to become unavailable - * @access public - * @return bool - */ + * Sets account presence. No additional info required (default is "online" status) + * + * @param string $message online, offline... + * @param string $type dnd, away, chat, xa or nothing + * @param bool $unavailable set this to true if you want to become unavailable + * + * @return bool + */ function send_presence($message = '', $type = '', $unavailable = false) { if (!isset($this->session['jid'])) @@ -402,11 +492,12 @@ class jabber } /** - * This handles all the different XML elements - * @param array $xml - * @access public - * @return bool - */ + * This handles all the different XML elements + * + * @param array $xml + * + * @return bool + */ function response($xml) { if (!is_array($xml) || !count($xml)) @@ -716,7 +807,17 @@ class jabber } } - function send_message($to, $text, $subject = '', $type = 'normal') + /** + * Send Jabber message + * + * @param string $to Recepient usermane + * @param string $text Message text + * @param string $subject Message subject + * @param string $type Message type + * + * @return string + */ + public function send_message($to, $text, $subject = '', $type = 'normal') { if (!isset($this->session['jid'])) { @@ -736,12 +837,13 @@ class jabber } /** - * Encrypts a password as in RFC 2831 - * @param array $data Needs data from the client-server connection - * @access public - * @return string - */ - function encrypt_password($data) + * Encrypts a password as in RFC 2831 + * + * @param array $data Needs data from the client-server connection + * + * @return string + */ + public function encrypt_password($data) { // let's me think about again... foreach (array('realm', 'cnonce', 'digest-uri') as $key) @@ -770,12 +872,12 @@ class jabber } /** - * parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,... - * @param string $data - * @access public - * @return array a => b ... - */ - function parse_data($data) + * parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,... + * @param string $data + * + * @return array a => b ... + */ + public function parse_data($data) { $data = explode(',', $data); $pairs = array(); @@ -802,12 +904,13 @@ class jabber } /** - * opposite of jabber::parse_data() - * @param array $data - * @access public - * @return string - */ - function implode_data($data) + * opposite of jabber::parse_data() + * + * @param array $data + * + * @return string + */ + public function implode_data($data) { $return = array(); foreach ($data as $key => $value) @@ -818,10 +921,10 @@ class jabber } /** - * xmlize() - * @author Hans Anderson - * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ - */ + * xmlize() + * @author Hans Anderson + * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ + */ function xmlize($data, $skip_white = 1, $encoding = 'UTF-8') { $data = trim($data); @@ -854,10 +957,10 @@ class jabber } /** - * _xml_depth() - * @author Hans Anderson - * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ - */ + * _xml_depth() + * @author Hans Anderson + * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ + */ function _xml_depth($vals, &$i) { $children = array(); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 6a32349d4f..323ab31999 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -54,9 +54,18 @@ class messenger 'return-path' => PathHeader::class, ]; + /** @var array */ + protected $additional_headers = []; + /** @var array */ protected $addresses = []; + /** @var \phpbb\config\config */ + protected $config; + + /** @var \phpbb\event\dispatcher */ + protected $dispatcher; + /** * @var string * @@ -67,6 +76,15 @@ class messenger /** @var string */ protected $from; + /** @var Symfony\Component\Mime\Header\Headers */ + protected $headers; + + /** @var \phpbb\language\language */ + protected $language; + + /** @var \phpbb\log\log_interface */ + protected $log; + /** * @var int * @@ -82,9 +100,21 @@ class messenger /** @var string */ protected $msg; + /** @var string */ + protected $php_ext; + + /** @var queue */ + protected $queue; + /** @var string */ protected $replyto; + /** @var \phpbb\request\request */ + protected $request; + + /** @var string */ + protected $root_path; + /** @var string */ protected $subject; @@ -97,6 +127,9 @@ class messenger /** @var bool */ protected $use_queue = true; + /** @var phpbb\user */ + protected $user; + /** * Messenger class constructor * @@ -144,7 +177,7 @@ class messenger { if (isset($user['user_email']) && $user['user_email']) { - $this->email->to(new Address($user['user_email'], $user['username'] ?: '')); + $this->to($user['user_email'], $user['username'] ?: ''); } if (isset($user['user_jabber']) && $user['user_jabber']) @@ -273,9 +306,17 @@ class messenger * @param string $header_value Email header body * @return void */ - public function headers($header_name, $header_value) + public function header($header_name, $header_value) { - $this->headers->addTextHeader(trim($header_name), trim($header_value)); + $header_name = trim($header_name); + $header_value = trim($header_value); + + // addMailboxListHeader() requires value to be array + if ($this->get_header_method($header_name) == 'addMailboxListHeader') + { + $header_value = [$header_value]; + } + $this->headers->addHeader($header_name, $header_value); } /** @@ -287,10 +328,10 @@ class messenger */ public function anti_abuse_headers($config, $user) { - $this->headers->addTextHeader('X-AntiAbuse', 'Board servername - ' . $config['server_name']); - $this->headers->addTextHeader('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); - $this->headers->addTextHeader('X-AntiAbuse', 'Username - ' . $user->data['username']); - $this->headers->addTextHeader('X-AntiAbuse', 'User IP - ' . $user->ip); + $this->header('X-AntiAbuse', 'Board servername - ' . $config['server_name']); + $this->header('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); + $this->header('X-AntiAbuse', 'Username - ' . $user->data['username']); + $this->header('X-AntiAbuse', 'User IP - ' . $user->ip); } /** @@ -415,6 +456,13 @@ class messenger $this->template->assign_vars($vars); } + /** + * Assign block of variables to email template + * + * @param string $blockname Template block name + * @param array $vars Array of VAR => VALUE to assign to email template block + * @return void + */ public function assign_block_vars($blockname, $vars) { $this->setup_template(); @@ -423,14 +471,11 @@ class messenger } /** - * Send the mail out to the recipients + * Prepare message before sending out to the recipients * - * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH - * @param bool $break Flag indicating if the function only formats the subject - * and the message without sending it - * @return bool + * @return void */ - public function send($method = NOTIFY_EMAIL, $break = false) + public function prepare_message() { // We add some standard variables we always use, no need to specify them always $this->assign_vars([ @@ -446,16 +491,13 @@ class messenger * Event to modify the template before parsing * * @event core.modify_notification_template - * @var bool break Flag indicating if the function only formats the subject - * and the message without sending it * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH * @var string subject The message subject * @var \phpbb\template\template template The (readonly) template object * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. + * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. */ - $vars = ['break', 'email', 'method', 'subject', 'template']; + $vars = ['email', 'subject', 'template']; extract($this->dispatcher->trigger_event('core.modify_notification_template', compact($vars))); // Parse message through template @@ -465,16 +507,13 @@ class messenger * Event to modify notification message text after parsing * * @event core.modify_notification_message - * @var bool break Flag indicating if the function only formats the subject - * and the message without sending it * @var Symfony\Component\Mime\Email email The Symfony Email object * @var string message The message text - * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH * @var string subject The message subject * @since 3.1.11-RC1 - * @changed 4.0.0-a1 Added vars: email. + * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. */ - $vars = ['break', 'email', 'message', 'method', 'subject']; + $vars = ['email', 'message', 'subject']; extract($this->dispatcher->trigger_event('core.modify_notification_message', compact($vars))); $this->email = $email; @@ -489,30 +528,39 @@ class messenger // do this here because the subject may contain a variable $drop_header = ''; $match = []; - if (preg_match('#^(Subject:(.*?))$#m', $this->msg, $match)) + if (preg_match('#^(Subject):(.*?)$#m', $this->msg, $match)) { $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); - $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); + $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); } else { $this->subject = (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); } - if (preg_match('#^(List-Unsubscribe:(.*?))$#m', $this->msg, $match)) + if (preg_match('#^(List-Unsubscribe):(.*?)$#m', $this->msg, $match)) { - $this->headers->addTextHeader('List-Unsubscribe', trim($match[2])); - $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); + $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); + $this->additional_headers[$match[1]] = trim($match[2]); } if ($drop_header) { $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); } + } - $this->email->subject($this->subject); - $this->email->text($this->msg); - + /** + * Send the mail out to the recipients + * + * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @param bool $break Flag indicating if the function only formats the subject + * and the message without sending it + * @return bool + */ + public function send($method = NOTIFY_EMAIL, $break = false) + { + $this->prepare_message(); if ($break) { return true; @@ -617,13 +665,13 @@ class messenger $board_contact = $this->config['board_contact']; if (empty($this->email->getReplyTo())) { - $this->replyto = $board_contact; + $this->replyto($board_contact); $headers['Reply-To'] = $this->replyto; } if (empty($this->email->getFrom())) { - $this->from = $board_contact; + $this->from($board_contact); $headers['From'] = $this->from; } @@ -647,12 +695,7 @@ class messenger foreach ($headers as $header => $value) { - // addMailboxListHeader() requires value to be array - if ($this->get_header_method($header) == 'addMailboxListHeader') - { - $value = [$value]; - } - $this->headers->addHeader($header, $value); + $this->header($header, $value); } return true; @@ -719,15 +762,10 @@ class messenger if ($this->config['smtp_delivery'] && !in_array($this->dsn, ['null://null', 'sendmail://default'])) { // Set ssl context options, see http://php.net/manual/en/context.ssl.php - $verify_peer = (bool) $this->config['smtp_verify_peer']; - $verify_peer_name = (bool) $this->config['smtp_verify_peer_name']; - $allow_self_signed = (bool) $this->config['smtp_allow_self_signed']; - $options = [ - 'ssl' => [ - 'verify_peer' => $verify_peer, - 'verify_peer_name' => $verify_peer_name, - 'allow_self_signed' => $allow_self_signed, - ] + $options['ssl'] = [ + 'verify_peer' => (bool) $this->config['smtp_verify_peer'], + 'verify_peer_name' => (bool) $this->config['smtp_verify_peer_name'], + 'allow_self_signed' => (bool) $this->config['smtp_allow_self_signed'], ]; $this->transport->getStream()->setStreamOptions($options); } @@ -776,6 +814,9 @@ class messenger $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); $board_contact = $this->config['board_contact']; + $this->email->subject($this->subject); + $this->email->text($this->msg); + $break = false; $subject = $this->subject; $msg = $this->msg; @@ -811,15 +852,19 @@ class messenger if (empty($this->email->getReplyto())) { - $this->email->replyTo(new Address($board_contact)); + $this->replyto($board_contact); } if (empty($this->email->getFrom())) { - $this->email->from(new Address($board_contact)); + $this->from($board_contact); } // Build header + foreach ($this->additional_headers as $header_name => $header_value) + { + $this->header($header_name, $header_value); + } $this->build_header(); // Send message ... From df5b7fd66e9da5964683b51069d15fc7dc5219ff Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 5 Jun 2023 22:47:14 +0700 Subject: [PATCH 06/29] [ticket/17135] Refactor messenger code to services [ci skip] PHPBB3-17135 --- phpBB/config/default/container/services.yml | 1 + .../default/container/services_messenger.yml | 46 ++ phpBB/phpbb/messenger/method/base.php | 408 +++++++++++++ phpBB/phpbb/messenger/method/email.php | 576 ++++++++++++++++++ .../messenger/method/jabber.php} | 247 ++++++-- 5 files changed, 1213 insertions(+), 65 deletions(-) create mode 100644 phpBB/config/default/container/services_messenger.yml create mode 100644 phpBB/phpbb/messenger/method/base.php create mode 100644 phpBB/phpbb/messenger/method/email.php rename phpBB/{includes/functions_jabber.php => phpbb/messenger/method/jabber.php} (79%) diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 8a4336e832..c09f21b5c6 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -19,6 +19,7 @@ imports: - { resource: services_http.yml } - { resource: services_language.yml } - { resource: services_mention.yml } + - { resource: services_messenger.yml } - { resource: services_migrator.yml } - { resource: services_mimetype_guesser.yml } - { resource: services_module.yml } diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml new file mode 100644 index 0000000000..659a4fa558 --- /dev/null +++ b/phpBB/config/default/container/services_messenger.yml @@ -0,0 +1,46 @@ +parameters: + core.messenger_queue_file: '%core.cache_dir%queue.%core.php_ext%' + +services: + messenger.method_collection: + class: phpbb\di\service_collection + arguments: + - '@service_container' + tags: + - { name: service_collection, tag: messenger.method, class_name_aware: true } + + messenger.method_base: + class: phpbb\messenger\method\base + shared: false + arguments: + - '@config' + - '@dispatcher' + - '@language' + - '@log' + - '@request' + - '@user' + - '@messenger.queue' + + messenger.method_email: + class: phpbb\messenger\method\email + shared: false + parent: messenger.method_base + calls: + - [init, []] + - [set_transport, []] + + messenger.method_jabber: + class: phpbb\messenger\method\jabber + shared: false + parent: messenger.method_base + calls: + - [init, []] + + messenger.queue: + class: phpbb\messenger\queue + shared: false + arguments: + - '@config' + - '@dispatcher' + - '@messenger.method_collection' + - '%core.messenger_queue_file%' diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php new file mode 100644 index 0000000000..507b5beea8 --- /dev/null +++ b/phpBB/phpbb/messenger/method/base.php @@ -0,0 +1,408 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\messenger\method; + +use phpbb\config\config; +use phpbb\event\dispatcher; +use phpbb\language\language; +use phpbb\log\log_interface; +use phpbb\request\request; +use phpbb\messenger\queue; +use phpbb\template\template; +use phpbb\user; + +/** + * Messenger base class + */ +class base +{ + /** @var array */ + protected $additional_headers = []; + + /** @var array */ + protected $addresses = []; + + /** @var config */ + protected $config; + + /** @var dispatcher */ + protected $dispatcher; + + /** @var language */ + protected $language; + + /** @var log_interface */ + protected $log; + + /** @var string */ + protected $msg = ''; + + /** @var queue */ + protected $queue; + + /** @var request */ + protected $request; + + /** @var string */ + protected $subject = ''; + + /** @var template */ + protected $template; + + /** @var bool */ + protected $use_queue = true; + + /** @var user */ + protected $user; + + /** + * Messenger base class constructor + * + * @param config $config + * @param dispatcher $dispatcher + * @param language $language + * @param log_interface $log + * @param request $request + * @param user $user + * @param queue $queue + */ + function __construct(config $config, dispatcher $dispatcher, language $language, log_interface $log, request $request, user $user, queue $queue) + { + $this->config = $config; + $this->dispatcher = $dispatcher; + $this->language = $language; + $this->log = $log; + $this->request = $request; + $this->user = $user; + $this->queue = $queue; + + $this->set_use_queue(); + } + + /** + * Sets the use of messenger queue flag + * + * @return void + */ + public function set_use_queue($use_queue = true) + { + $this->use_queue = $use_queue; + } + + /** + * Resets all the data (address, template file, etc etc) to default + * + * @return void + */ + public function reset() + { + $this->addresses = []; + $this->msg = ''; + } + + /** + * Set addresses for to/im as available + * + * @param array $user User row + * @return void + */ + public function set_addresses($user) + { + } + + /** + * Set up subject for mail + * + * @param string $subject Email subject + * @return void + */ + public function subject($subject = '') + { + $this->subject = $subject; + } + + /** + * Set email template to use + * + * @param string $template_file Email template file name + * @param string $template_lang Email template language + * @param string $template_path Email template path + * @param string $template_dir_prefix Email template directory prefix + * + * @return bool + */ + public function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') + { + $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; + + $this->setup_template(); + + if (!trim($template_file)) + { + trigger_error('No template file for emailing set.', E_USER_ERROR); + } + + if (!trim($template_lang)) + { + // fall back to board default language if the user's language is + // missing $template_file. If this does not exist either, + // $this->template->set_filenames will do a trigger_error + $template_lang = basename($this->config['default_lang']); + } + + $ext_template_paths = [ + [ + 'name' => $template_lang . '_email', + 'ext_path' => 'language/' . $template_lang . '/email' . $template_dir_prefix, + ], + ]; + + if ($template_path) + { + $template_paths = [ + $template_path . $template_dir_prefix, + ]; + } + else + { + $template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; + $template_path .= $template_lang . '/email'; + + $template_paths = [ + $template_path . $template_dir_prefix, + ]; + + $board_language = basename($this->config['default_lang']); + + // we can only specify default language fallback when the path is not a custom one for which we + // do not know the default language alternative + if ($template_lang !== $board_language) + { + $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; + $fallback_template_path .= $board_language . '/email'; + + $template_paths[] = $fallback_template_path . $template_dir_prefix; + + $ext_template_paths[] = [ + 'name' => $board_language . '_email', + 'ext_path' => 'language/' . $board_language . '/email' . $template_dir_prefix, + ]; + } + // If everything fails just fall back to en template + if ($template_lang !== 'en' && $board_language !== 'en') + { + $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; + $fallback_template_path .= 'en/email'; + + $template_paths[] = $fallback_template_path . $template_dir_prefix; + + $ext_template_paths[] = [ + 'name' => 'en_email', + 'ext_path' => 'language/en/email' . $template_dir_prefix, + ]; + } + } + + $this->set_template_paths($ext_template_paths, $template_paths); + + $this->template->set_filenames([ + 'body' => $template_file . '.txt', + ]); + + return true; + } + + /** + * Assign variables to email template + * + * @param array $vars Array of VAR => VALUE to assign to email template + * @return void + */ + public function assign_vars($vars) + { + $this->setup_template(); + + $this->template->assign_vars($vars); + } + + /** + * Assign block of variables to email template + * + * @param string $blockname Template block name + * @param array $vars Array of VAR => VALUE to assign to email template block + * @return void + */ + public function assign_block_vars($blockname, $vars) + { + $this->setup_template(); + + $this->template->assign_block_vars($blockname, $vars); + } + + /** + * Prepare message before sending out to the recipients + * + * @return void + */ + public function prepare_message() + { + // We add some standard variables we always use, no need to specify them always + $this->assign_vars([ + 'U_BOARD' => generate_board_url(), + 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . html_entity_decode($this->config['board_email_sig'], ENT_COMPAT)), + 'SITENAME' => html_entity_decode($this->config['sitename'], ENT_COMPAT), + ]); + + $subject = $this->email->getSubject(); + $template = $this->template; + /** + * Event to modify the template before parsing + * + * @event core.modify_notification_template + * @var string subject The message subject + * @var \phpbb\template\template template The (readonly) template object + * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. + */ + $vars = ['subject', 'template']; + extract($this->dispatcher->trigger_event('core.modify_notification_template', compact($vars))); + + // Parse message through template + $message = trim($this->template->assign_display('body')); + + /** + * Event to modify notification message text after parsing + * + * @event core.modify_notification_message + * @var string message The message text + * @var string subject The message subject + * @since 3.1.11-RC1 + * @changed 4.0.0-a1 Removed vars: method, break. + */ + $vars = ['message', 'subject']; + extract($this->dispatcher->trigger_event('core.modify_notification_message', compact($vars))); + + $this->subject = $subject; + $this->msg = $message; + unset($subject, $message, $template); + + // Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding + $this->msg = str_replace("\r\n", "\n", $this->msg); + + // We now try and pull a subject from the email body ... if it exists, + // do this here because the subject may contain a variable + $drop_header = ''; + $match = []; + if (preg_match('#^(Subject):(.*?)$#m', $this->msg, $match)) + { + $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $this->language->lang('NO_EMAIL_SUBJECT')); + $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); + } + else + { + $this->subject = (($this->subject != '') ? $this->subject : $this->language->lang('NO_EMAIL_SUBJECT')); + } + + if (preg_match('#^(List-Unsubscribe):(.*?)$#m', $this->msg, $match)) + { + $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); + $this->additional_headers[$match[1]] = trim($match[2]); + } + + if ($drop_header) + { + $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); + } + } + + /** + * Add error message to log + * + * @param string $type Error type: EMAIL / etc + * @param string $msg Error message text + * @return void + */ + public function error($type, $msg) + { + // Session doesn't exist, create it + if (!isset($this->user->session_id) || $this->user->session_id === '') + { + $this->user->session_begin(); + } + + $calling_page = html_entity_decode($this->request->server('PHP_SELF'), ENT_COMPAT); + $message = '' . $type . '
' . htmlspecialchars($calling_page, ENT_COMPAT) . '

' . $msg . '
'; + $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); + } + + /** + * Save message data to the messemger file queue + * @return void + */ + public function save_queue() + { + $this->queue->save(); + return; + } + + /** + * Setup template engine + * + * @return void + */ + protected function setup_template() + { + if ($this->template instanceof \phpbb\template\template) + { + return; + } + + $template_environment = new \phpbb\template\twig\environment( + $this->config, + $this->phpbb_container->get('filesystem'), + $this->phpbb_container->get('path_helper'), + $this->phpbb_container->getParameter('core.template.cache_path'), + $this->phpbb_container->get('ext.manager'), + new \phpbb\template\twig\loader(), + $this->dispatcher, + [] + ); + $template_environment->setLexer($this->phpbb_container->get('template.twig.lexer')); + + $this->template = new \phpbb\template\twig\twig( + $this->phpbb_container->get('path_helper'), + $this->config, + new \phpbb\template\context(), + $template_environment, + $this->phpbb_container->getParameter('core.template.cache_path'), + $this->user, + $this->phpbb_container->get('template.twig.extensions.collection'), + $this->phpbb_container->get('ext.manager') + ); + } + + /** + * Set template paths to load + * + * @param string $path_name Email template path name + * @param string $paths Email template paths + * @return void + */ + protected function set_template_paths($path_name, $paths) + { + $this->setup_template(); + + $this->template->set_custom_style($path_name, $paths); + } +} diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php new file mode 100644 index 0000000000..039591feb7 --- /dev/null +++ b/phpBB/phpbb/messenger/method/email.php @@ -0,0 +1,576 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\messenger\method; + +use Symfony\Component\Mailer\Transport; +use Symfony\Component\Mailer\Mailer; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\Headers; + +/** + * Messenger class + */ +class email extends base +{ + /** @var array */ + private const PRIORITY_MAP = [ + Email::PRIORITY_HIGHEST => 'Highest', + Email::PRIORITY_HIGH => 'High', + Email::PRIORITY_NORMAL => 'Normal', + Email::PRIORITY_LOW => 'Low', + Email::PRIORITY_LOWEST => 'Lowest', + ]; + + /** @var array */ + private const HEADER_CLASS_MAP = [ + 'date' => DateHeader::class, + 'from' => MailboxListHeader::class, + 'sender' => MailboxHeader::class, + 'reply-to' => MailboxListHeader::class, + 'to' => MailboxListHeader::class, + 'cc' => MailboxListHeader::class, + 'bcc' => MailboxListHeader::class, + 'message-id' => IdentificationHeader::class, + 'in-reply-to' => UnstructuredHeader::class, + 'references' => UnstructuredHeader::class, + 'return-path' => PathHeader::class, + ]; + + /** + * @var string + * + * Symfony Mailer transport DSN + */ + protected $dsn = ''; + + /** @var string */ + protected $from; + + /** @var Symfony\Component\Mime\Header\Headers */ + protected $headers; + + /** + * @var int + * + * Possible values are: + * Email::PRIORITY_HIGHEST + * Email::PRIORITY_HIGH + * Email::PRIORITY_NORMAL + * Email::PRIORITY_LOW + * Email::PRIORITY_LOWEST + */ + protected $mail_priority = Email::PRIORITY_NORMAL; + + /** @var queue */ + protected $queue; + + /** @var string */ + protected $replyto = ''; + + /** @var Symfony\Component\Mailer\Transport */ + protected $transport; + + /** + * Check if the messenger method is enabled + * @return void + */ + public function is_enabled() + { + return (bool) $this->config['email_enable']; + } + + /** + * Inits/resets the data to default + * + * @return void + */ + public function init() + { + $this->email = new Email(); + $this->headers = $this->email->getHeaders(); + $this->msg = $this->replyto = $this->from = ''; + $this->mail_priority = Email::PRIORITY_NORMAL; + } + + /** + * Sets the use of messenger queue flag + * + * @return void + */ + public function set_use_queue($use_queue = true) + { + $this->use_queue = !$this->config['email_package_size'] ? false : $use_queue; + } + + /** + * Set address as available + * + * @param array $user User row + * @return void + */ + public function set_addresses($user) + { + if (isset($user['user_email']) && $user['user_email']) + { + $this->to($user['user_email'], $user['username'] ?: ''); + } + } + + /** + * Sets email address to send to + * + * @param string $address Email "To" recipient address + * @param string $realname Email "To" recipient name + * @return void + */ + public function to($address, $realname = '') + { + if (!$address = trim($address)) + { + return; + } + + // If empty sendmail_path on windows, PHP changes the to line + $windows_empty_sendmail_path = !$this->config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\'; + + $to = new Address($address, $windows_empty_sendmail_path ? '' : trim($realname)); + $this->email->getTo() ? $this->email->addTo($to) : $this->email->to($to); + } + + /** + * Sets cc address to send to + * + * @param string $address Email carbon copy recipient address + * @param string $realname Email carbon copy recipient name + * @return void + */ + public function cc($address, $realname = '') + { + if (!$address = trim($address)) + { + return; + } + + $cc = new Address($address, trim($realname)); + $this->email->getCc() ? $this->email->addCc($to) : $this->email->cc($to); + } + + /** + * Sets bcc address to send to + * + * @param string $address Email black carbon copy recipient address + * @param string $realname Email black carbon copy recipient name + * @return void + */ + public function bcc($address, $realname = '') + { + if (!$address = trim($address)) + { + return; + } + + $bcc = new Address($address, trim($realname)); + $this->email->getBcc() ? $this->email->addBcc($to) : $this->email->bcc($to); + } + + /** + * Set the reply to address + * + * @param string $address Email "Reply to" address + * @return void + */ + public function replyto($address) + { + $this->replyto = new Address(trim($address)); + $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); + } + + /** + * Set the from address + * + * @param string $address Email "from" address + * @return void + */ + public function from($address) + { + $this->from = new Address(trim($address)); + $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); + } + + /** + * Set up subject for mail + * + * @param string $subject Email subject + * @return void + */ + public function subject($subject = '') + { + parent::subject(trim($subject)); + $this->email->subject($this->subject); + } + + /** + * Set up extra mail headers + * + * @param string $header_name Email header name + * @param string $header_value Email header body + * @return void + */ + public function header($header_name, $header_value) + { + $header_name = trim($header_name); + $header_value = trim($header_value); + + // addMailboxListHeader() requires value to be array + if ($this->get_header_method($header_name) == 'addMailboxListHeader') + { + $header_value = [$header_value]; + } + $this->headers->addHeader($header_name, $header_value); + } + + /** + * Adds X-AntiAbuse headers + * + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object + * @return void + */ + public function anti_abuse_headers($config, $user) + { + $this->header('X-AntiAbuse', 'Board servername - ' . $config['server_name']); + $this->header('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); + $this->header('X-AntiAbuse', 'Username - ' . $user->data['username']); + $this->header('X-AntiAbuse', 'User IP - ' . $user->ip); + } + + /** + * Set the email priority + * + * Possible values are: + * Email::PRIORITY_HIGHEST = 1 + * Email::PRIORITY_HIGH = 2 + * Email::PRIORITY_NORMAL = 3 + * Email::PRIORITY_LOW = 4 + * Email::PRIORITY_LOWEST = 5 + * + * @param int $priority Email priority level + * @return void + */ + public function set_mail_priority($priority = Email::PRIORITY_NORMAL) + { + $this->email->priority($priority); + } + + /** + * Add error message to log + * + * @param string $msg Error message text + * @return void + */ + public function error($msg) + { + $type = 'EMAIL/' . ($this->config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()'; + parent::error($type, $msg); + } + + /** + * Save message data to the messenger file queue + * @return void + */ + public function save_queue() + { + if ($this->config['email_package_size'] && $this->use_queue && !empty($this->queue)) + { + $this->queue->save(); + return; + } + } + + /** + * Detect proper Header class method to add header + * + * @param string $name Email header name + * @return string + */ + protected function get_header_method(string $name) + { + $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); + $method = 'add'.ucfirst(array_pop($parts)); + if ('addUnstructuredHeader' === $method) + { + $method = 'addTextHeader'; + } + else if ('addIdentificationHeader' === $method) + { + $method = 'addIdHeader'; + } + + return $method; + } + + /** + * Set email headers + * + * @return bool + */ + protected function build_header() + { + $headers = []; + + $board_contact = $this->config['board_contact']; + if (empty($this->email->getReplyTo())) + { + $this->replyto($board_contact); + $headers['Reply-To'] = $this->replyto; + } + + if (empty($this->email->getFrom())) + { + $this->from($board_contact); + $headers['From'] = $this->from; + } + + $headers['Return-Path'] = new Address($this->config['board_email']); + $headers['Sender'] = new Address($this->config['board_email']); + $headers['X-Priority'] = sprintf('%d (%s)', $this->mail_priority, self::PRIORITY_MAP[$this->mail_priority]); + $headers['X-MSMail-Priority'] = self::PRIORITY_MAP[$this->mail_priority]; + $headers['X-Mailer'] = 'phpBB3'; + $headers['X-MimeOLE'] = 'phpBB3'; + $headers['X-phpBB-Origin'] = 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()); + + /** + * Event to modify email header entries + * + * @event core.modify_email_headers + * @var array headers Array containing email header entries + * @since 3.1.11-RC1 + */ + $vars = ['headers']; + extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); + + foreach ($headers as $header => $value) + { + $this->header($header, $value); + } + + return true; + } + + /** + * Generates valid DSN for Symfony Mailer transport + * + * @param string $dsn Symfony Mailer transport DSN + * @return void + */ + public function set_dsn($dsn = '') + { + if (!empty($dsn)) + { + $this->dsn = $dsn; + } + else if ($this->config['smtp_delivery']) + { + if (empty($this->config['smtp_host'])) + { + $this->dsn = 'null://null'; + } + else + { + $user = urlencode($this->config['smtp_username']); + $password = urlencode($this->config['smtp_password']); + $smtp_host = urlencode($this->config['smtp_host']); + $smtp_port = $this->config['smtp_port']; + + $this->dsn = "smtp://$user:$password@$smtp_host:$smtp_port"; + } + } + else + { + $this->dsn = 'sendmail://default'; + } + } + + /** + * Get Symfony Mailer transport DSN + * + * @return void + */ + public function get_dsn() + { + return $this->dsn; + } + + /** + * Generates a valid transport to send email + * + * @return void + */ + public function set_transport() + { + if (empty($this->dsn)) + { + $this->set_dsn(); + } + + $this->transport = Transport::fromDsn($this->dsn); + + if ($this->config['smtp_delivery'] && !in_array($this->dsn, ['null://null', 'sendmail://default'])) + { + // Set ssl context options, see http://php.net/manual/en/context.ssl.php + $options['ssl'] = [ + 'verify_peer' => (bool) $this->config['smtp_verify_peer'], + 'verify_peer_name' => (bool) $this->config['smtp_verify_peer_name'], + 'allow_self_signed' => (bool) $this->config['smtp_allow_self_signed'], + ]; + $this->transport->getStream()->setStreamOptions($options); + } + } + + /** + * Get mailer transport object + * + * @return Symfony\Component\Mailer\Transport Symfony Mailer transport object + */ + public function get_transport() + { + return $this->transport; + } + + /** + * Send out emails + * + * @return bool + */ + protected function send() + { + $this->prepare_message(); + + $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); + $board_contact = trim($this->config['board_contact']); + + $this->email->subject($this->subject); + $this->email->text($this->msg); + + $subject = $this->subject; + $msg = $this->msg; + $email = $this->email; + /** + * Event to send message via external transport + * + * @event core.notification_message_email + * @var string subject The message subject + * @var string msg The message text + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, break + */ + $vars = [ + 'subject', + 'msg', + 'email', + ]; + extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); + + if (empty($this->email->getReplyto())) + { + $this->replyto($board_contact); + } + + if (empty($this->email->getFrom())) + { + $this->from($board_contact); + } + + // Build headers + foreach ($this->additional_headers as $header_name => $header_value) + { + $this->header($header_name, $header_value); + } + $this->build_header(); + + // Send message ... + if (!$this->use_queue) + { + $mailer = new Mailer($this->transport); + + $subject = $this->subject; + $msg = $this->msg; + $headers = $this->headers; + $email = $this->email; + /** + * Modify data before sending out emails with PHP's mail function + * + * @event core.phpbb_mail_before + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var string headers The email headers + * @since 3.3.6-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters. + */ + $vars = [ + 'email', + 'subject', + 'msg', + 'headers', + ]; + extract($this->dispatcher->trigger_event('core.phpbb_mail_before', compact($vars))); + + $this->subject = $subject; + $this->msg = $msg; + $this->headers = $headers; + $this->email = $email; + + try + { + $mailer->send($this->email); + } + catch (TransportExceptionInterface $e) + { + $this->error($e->getDebug()); + return false; + } + + /** + * Execute code after sending out emails with PHP's mail function + * + * @event core.phpbb_mail_after + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var string headers The email headers + * @since 3.3.6-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters, $result. + */ + $vars = [ + 'email', + 'subject', + 'msg', + 'headers', + ]; + extract($this->dispatcher->trigger_event('core.phpbb_mail_after', compact($vars))); + } + else + { + $this->queue->init('email', $this->config['email_package_size']); + $this->queue->put('email', [ + 'email' => $this->email, + ]); + } + + return true; + } +} diff --git a/phpBB/includes/functions_jabber.php b/phpBB/phpbb/messenger/method/jabber.php similarity index 79% rename from phpBB/includes/functions_jabber.php rename to phpBB/phpbb/messenger/method/jabber.php index 282e6105a2..2e7f2040da 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -1,35 +1,30 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\messenger\method; /** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* -* Jabber class from Flyspray project -* -* @version class.jabber2.php 1595 2008-09-19 (0.9.9) -* @copyright 2006 Flyspray.org -* @author Florian Schmitz (floele) -* -* Only slightly modified by Acyd Burn -*/ -class jabber + * + * Based on Jabber class from Flyspray project + * + * @version class.jabber2.php 1595 2008-09-19 (0.9.9) + * @copyright 2006 Flyspray.org + * @author Florian Schmitz (floele) + * + * Slightly modified by Acyd Burn (2006) + * Refactored to a service (2023) + */ +class jabber extends base { /** @var string */ protected $connect_server; @@ -70,6 +65,9 @@ class jabber /** @var int */ protected $timeout = 10; + /** @var array */ + protected $to = []; + /** @var bool */ protected $use_ssl = false; @@ -80,25 +78,49 @@ class jabber private const STREAM_CLOSE_HANDSHAKE = '
'; /** - * Jabber class constructor + * Set initial parameter values + * To init correctly, username() call should go before server() + * and ssl() call should go before port() and stream_options() calls. * - * Use (username() call should go before server() - * and ssl() call should go before port() and stream_options()): - * - * new jabber() - * -> username($username) - * -> password($password) - * -> ssl($use_ssl) - * -> server($server) - * -> port($port) - * -> stream_options( + * Example: + * $this->username($username) + * ->password($password) + * ->ssl($use_ssl) + * ->server($server) + * ->port($port) + * ->stream_options( * 'verify_peer' => true, * 'verify_peer_name' => true, * 'allow_self_signed' => false, * ); + * + * @return void */ - function __construct() + public function init() { + $this->username($this->config['jab_username']) + ->password($this->config['jab_password']) + ->ssl((bool) $this->config['jab_use_ssl']) + ->server($this->config['jab_host']) + ->port($this->config['jab_port']) + ->stream_options['ssl'] = [ + 'verify_peer' => $this->config['jab_verify_peer'], + 'verify_peer_name' => $this->config['jab_verify_peer_name'], + 'allow_self_signed' => $this->config['jab_allow_self_signed'], + ]; + } + + /** + * Check if the messenger method is enabled + * @return void + */ + public function is_enabled() + { + return + empty($this->config['jab_enable']) || + empty($this->config['jab_host']) || + empty($this->config['jab_username']) || + empty($this->config['jab_password']); } /** @@ -112,12 +134,8 @@ class jabber { if ($this->use_ssl) { - // Set default stream options and change it if needed - $this->stream_options['ssl'] = array_merge([ - 'verify_peer' => true, - 'verify_peer_name' => true, - 'allow_self_signed' => false, - ], $options); + // Change default stream options if needed + $this->stream_options['ssl'] = array_merge($this->stream_options['ssl'], $options); } return $this; @@ -131,7 +149,7 @@ class jabber */ public function password($password = '') { - $this->password = $password; + $this->password = html_entity_decode($password, ENT_COMPAT); return $this; } @@ -263,8 +281,8 @@ class jabber if ($this->open_socket($this->connect_server, $this->port)) { - $this->send("\n"); - $this->send("\n"); + $this->send_xml("\n"); + $this->send_xml("\n"); } else { @@ -331,6 +349,105 @@ class jabber return $this->response($this->features); } + /** + * Set address as available + * + * @param array $user User row + * @return void + */ + public function set_addresses($user) + { + if (isset($user['user_jabber']) && $user['user_jabber']) + { + $this->to($user['user_jabber'], (isset($user['username']) ? $user['username'] : '')); + } + } + + /** + * Sets jabber contact to send message to + * + * @param string $address Jabber "To" recipient address + * @param string $realname Jabber "To" recipient name + * @return void + */ + public function to($address, $realname = '') + { + // IM-Addresses could be empty + if (!trim($address)) + { + return; + } + + $pos = !empty($this->to) ? count($this->to) : 0; + $this->to[$pos]['uid'] = trim($address); + $this->to[$pos]['name'] = trim($realname); + } + + /** + * Sets the use of messenger queue flag + * + * @return void + */ + public function set_use_queue($use_queue = true) + { + $this->use_queue = !$this->config['jab_package_size'] ? false : $use_queue; + } + + /** + * Send jabber message out + */ + public function send() + { + $this->prepare_message(); + + if (empty($this->to)) + { + $this->add_to_log('Error: Could not send, recepient addresses undefined.'); + return false; + } + + $addresses = []; + foreach ($this->to as $uid_ary) + { + $addresses[] = $uid_ary['uid']; + } + $addresses = array_unique($addresses); + + if (!$this->use_queue) + { + if (!$this->connect()) + { + $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->get_log()); + return false; + } + + if (!$this->login()) + { + $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->get_log()); + return false; + } + + foreach ($addresses as $address) + { + $this->send_message($address, $this->msg, $this->subject); + } + + $this->disconnect(); + } + else + { + $this->queue->init('jabber', $this->config['jab_package_size']); + $this->queue->put('jabber', array( + 'addresses' => $addresses, + 'subject' => $this->subject, + 'msg' => $this->msg) + ); + } + unset($addresses); + + return true; + } + /** * Send data to the Jabber server * @@ -338,7 +455,7 @@ class jabber * * @return bool */ - public function send($xml) + public function send_xml($xml) { if ($this->connected()) { @@ -459,7 +576,7 @@ class jabber return false; } - $this->send(""); + $this->send_xml(""); return $this->response($this->listen()); } @@ -488,7 +605,7 @@ class jabber $this->session['sent_presence'] = !$unavailable; - return $this->send("" . $type . $message . ''); + return $this->send_xml("" . $type . $message . ''); } /** @@ -567,7 +684,7 @@ class jabber // session required? $this->session['sess_required'] = isset($xml['stream:features'][0]['#']['session']); - $this->send(" + $this->send_xml(" " . utf8_htmlspecialchars($this->resource) . ' @@ -579,7 +696,7 @@ class jabber if (!$this->session['ssl'] && self::can_use_tls() && self::can_use_ssl() && isset($xml['stream:features'][0]['#']['starttls'])) { $this->add_to_log('Switching to TLS.'); - $this->send("\n"); + $this->send_xml("\n"); return $this->response($this->listen()); } @@ -605,18 +722,18 @@ class jabber if (in_array('DIGEST-MD5', $methods)) { - $this->send(""); + $this->send_xml(""); } else if (in_array('PLAIN', $methods) && ($this->session['ssl'] || !empty($this->session['tls']))) { // http://www.ietf.org/rfc/rfc4616.txt (PLAIN SASL Mechanism) - $this->send("" + $this->send_xml("" . base64_encode($this->username . '@' . $this->server . chr(0) . $this->username . chr(0) . $this->password) . ''); } else if (in_array('ANONYMOUS', $methods)) { - $this->send(""); + $this->send_xml(""); } else { @@ -653,7 +770,7 @@ class jabber // second challenge? if (isset($decoded['rspauth'])) { - $this->send(""); + $this->send_xml(""); } else { @@ -680,7 +797,7 @@ class jabber } } - $this->send("" . base64_encode($this->implode_data($response)) . ''); + $this->send_xml("" . base64_encode($this->implode_data($response)) . ''); } return $this->response($this->listen()); @@ -707,15 +824,15 @@ class jabber $this->session['tls'] = true; // new stream - $this->send("\n"); - $this->send("\n"); + $this->send_xml("\n"); + $this->send_xml("\n"); return $this->response($this->listen()); break; case 'success': // Yay, authentication successful. - $this->send("\n"); + $this->send_xml("\n"); $this->session['authenticated'] = true; // we have to wait for another response @@ -738,7 +855,7 @@ class jabber // and (maybe) yet another request to be able to send messages *finally* if ($this->session['sess_required']) { - $this->send(" + $this->send_xml(" "); return $this->response($this->listen()); @@ -752,7 +869,7 @@ class jabber break; case 'reg_1': - $this->send(" + $this->send_xml(" " . utf8_htmlspecialchars($this->username) . " " . utf8_htmlspecialchars($this->password) . " @@ -829,7 +946,7 @@ class jabber $type = 'normal'; } - return $this->send(" + return $this->send_xml(" " . utf8_htmlspecialchars($subject) . " " . utf8_htmlspecialchars($text) . " " From 5be1f5d5c9db05d2329d10701e2b72bb7e5d2986 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 6 Jun 2023 12:54:15 +0700 Subject: [PATCH 07/29] [ticket/17135] Refactor messenger code to services [ci skip] PHPBB3-17135 --- .../default/container/services_console.yml | 2 + .../default/container/services_cron.yml | 5 +- .../default/container/services_messenger.yml | 14 ++-- .../container/services_notification.yml | 2 + .../config/default/container/services_ucp.yml | 1 + .../container/services_install_finish.yml | 2 - phpBB/memberlist.php | 28 +++---- phpBB/phpbb/console/command/user/activate.php | 31 +++---- phpBB/phpbb/console/command/user/add.php | 32 ++++---- phpBB/phpbb/cron/task/core/queue.php | 36 ++++----- .../install_finish/task/notify_user.php | 78 +++++++----------- phpBB/phpbb/message/form.php | 4 +- phpBB/phpbb/message/message.php | 80 ++++++++++--------- phpBB/phpbb/messenger/method/base.php | 42 ++++++++-- phpBB/phpbb/messenger/method/email.php | 23 +++--- phpBB/phpbb/messenger/method/jabber.php | 10 +++ phpBB/phpbb/notification/method/email.php | 30 +++++-- phpBB/phpbb/notification/method/jabber.php | 18 +++-- .../notification/method/messenger_base.php | 52 ++++++------ phpBB/phpbb/ucp/controller/reset_password.php | 42 +++++----- 20 files changed, 296 insertions(+), 236 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 6c85e22f9a..704c122d59 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -331,6 +331,7 @@ services: - '@user_loader' - '%core.root_path%' - '%core.php_ext%' + - '@messenger.method_collection' tags: - { name: console.command } @@ -344,6 +345,7 @@ services: - '@passwords.manager' - '%core.root_path%' - '%core.php_ext%' + - '@messenger.method_collection' tags: - { name: console.command } diff --git a/phpBB/config/default/container/services_cron.yml b/phpBB/config/default/container/services_cron.yml index a19ed9900d..85d5c1631f 100644 --- a/phpBB/config/default/container/services_cron.yml +++ b/phpBB/config/default/container/services_cron.yml @@ -86,10 +86,9 @@ services: cron.task.core.queue: class: phpbb\cron\task\core\queue arguments: - - '%core.root_path%' - - '%core.php_ext%' - '@config' - - '%core.cache_dir%' + - '@messenger.queue' + - '%core.messenger_queue_file%' calls: - [set_name, [cron.task.core.queue]] tags: diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index 659a4fa558..83037d6427 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -9,7 +9,7 @@ services: tags: - { name: service_collection, tag: messenger.method, class_name_aware: true } - messenger.method_base: + messenger.method.base: class: phpbb\messenger\method\base shared: false arguments: @@ -21,20 +21,24 @@ services: - '@user' - '@messenger.queue' - messenger.method_email: + messenger.method.email: class: phpbb\messenger\method\email shared: false - parent: messenger.method_base + parent: messenger.method.base calls: - [init, []] - [set_transport, []] + tags: + - { name: messenger.method } - messenger.method_jabber: + messenger.method.jabber: class: phpbb\messenger\method\jabber shared: false - parent: messenger.method_base + parent: messenger.method.base calls: - [init, []] + tags: + - { name: messenger.method } messenger.queue: class: phpbb\messenger\queue diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml index 92592850f9..0ac9dc6a88 100644 --- a/phpBB/config/default/container/services_notification.yml +++ b/phpBB/config/default/container/services_notification.yml @@ -229,6 +229,7 @@ services: - '%core.root_path%' - '%core.php_ext%' - '%tables.notification_emails%' + - '@messenger.method_collection' tags: - { name: notification.method } @@ -241,6 +242,7 @@ services: - '@config' - '%core.root_path%' - '%core.php_ext%' + - '@messenger.method_collection' tags: - { name: notification.method } diff --git a/phpBB/config/default/container/services_ucp.yml b/phpBB/config/default/container/services_ucp.yml index acd78f8440..6321e431db 100644 --- a/phpBB/config/default/container/services_ucp.yml +++ b/phpBB/config/default/container/services_ucp.yml @@ -26,6 +26,7 @@ services: - '%tables.users%' - '%core.root_path%' - '%core.php_ext%' + - '@messenger.method_collection' phpbb.ucp.controller.webpush: class: phpbb\ucp\controller\webpush diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index b200118e11..c9acdad025 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -23,8 +23,6 @@ services: - '@installer.helper.container_factory' - '@installer.helper.config' - '@installer.helper.iohandler' - - '%core.root_path%' - - '%core.php_ext%' tags: - { name: install_finish, order: 3 } diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 28b1adbdee..f61fd21502 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -428,8 +428,6 @@ switch ($mode) if (check_form_key('memberlist_messaging')) { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $subject = sprintf($user->lang['IM_JABBER_SUBJECT'], $user->data['username'], $config['server_name']); $message = $request->variable('message', '', true); @@ -438,22 +436,22 @@ switch ($mode) trigger_error('EMPTY_MESSAGE_IM'); } - $messenger = new messenger(false); + $messenger = $phpbb_container->get('messenger.method_collection'); + $jabber = $messenger->offsetGet('messenger.method.jabber'); + $jabber->set_use_queue(false); - $messenger->template('profile_send_im', $row['user_lang']); - $messenger->subject(html_entity_decode($subject, ENT_COMPAT)); + $jabber->template('profile_send_im', $row['user_lang']); + $jabber->subject(html_entity_decode($subject, ENT_COMPAT)); + $jabber->set_addresses($row); - $messenger->replyto($user->data['user_email']); - $messenger->set_addresses($row); - - $messenger->assign_vars(array( + $jabber->assign_vars([ 'BOARD_CONTACT' => phpbb_get_board_contact($config, $phpEx), 'FROM_USERNAME' => html_entity_decode($user->data['username'], ENT_COMPAT), 'TO_USERNAME' => html_entity_decode($row['username'], ENT_COMPAT), - 'MESSAGE' => html_entity_decode($message, ENT_COMPAT)) - ); + 'MESSAGE' => html_entity_decode($message, ENT_COMPAT), + ]); - $messenger->send(NOTIFY_IM); + $jabber->send(); $s_select = 'S_SENT_JABBER'; } @@ -903,10 +901,7 @@ switch ($mode) case 'contactadmin': case 'email': - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } + $messenger = $phpbb_container->get('messenger.method_collection'); $user_id = $request->variable('u', 0); $topic_id = $request->variable('t', 0); @@ -940,7 +935,6 @@ switch ($mode) if ($request->is_set_post('submit')) { - $messenger = new messenger(false); $form->submit($messenger); } diff --git a/phpBB/phpbb/console/command/user/activate.php b/phpBB/phpbb/console/command/user/activate.php index 1d635b46dc..9157206e0a 100644 --- a/phpBB/phpbb/console/command/user/activate.php +++ b/phpBB/phpbb/console/command/user/activate.php @@ -20,6 +20,7 @@ use phpbb\log\log_interface; use phpbb\notification\manager; use phpbb\user; use phpbb\user_loader; +use phpbb\di\service_collection; use Symfony\Component\Console\Command\Command as symfony_command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -58,6 +59,9 @@ class activate extends command */ protected $php_ext; + /** @var service_collection */ + protected $messenger; + /** * Construct method * @@ -69,8 +73,9 @@ class activate extends command * @param user_loader $user_loader * @param string $phpbb_root_path * @param string $php_ext + * @param service_collection $messenger */ - public function __construct(user $user, config $config, language $language, log_interface $log, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext) + public function __construct(user $user, config $config, language $language, log_interface $log, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext, service_collection $messenger) { $this->config = $config; $this->language = $language; @@ -79,6 +84,7 @@ class activate extends command $this->user_loader = $user_loader; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + $this->messenger = $messenger; $this->language->add_lang('acp/users'); parent::__construct($user); @@ -194,20 +200,15 @@ class activate extends command if ($input->getOption('send-email')) { - if (!class_exists('messenger')) - { - require($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); - } - - $messenger = new \messenger(false); - $messenger->template('admin_welcome_activated', $user_row['user_lang']); - $messenger->set_addresses($user_row); - $messenger->anti_abuse_headers($this->config, $this->user); - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT)) - ); - - $messenger->send(NOTIFY_EMAIL); + $email = $this->messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template('admin_welcome_activated', $user_row['user_lang']); + $email->set_addresses($user_row); + $email->anti_abuse_headers($this->config, $this->user); + $email->assign_vars([ + 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), + ]); + $email->send(); } } } diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php index c01aac7cb6..3a54cc409f 100644 --- a/phpBB/phpbb/console/command/user/add.php +++ b/phpBB/phpbb/console/command/user/add.php @@ -20,6 +20,7 @@ use phpbb\exception\runtime_exception; use phpbb\language\language; use phpbb\passwords\manager; use phpbb\user; +use phpbb\di\service_collection; use Symfony\Component\Console\Command\Command as symfony_command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; @@ -59,6 +60,9 @@ class add extends command */ protected $php_ext; + /** @var service_collection */ + protected $messenger; + /** * Construct method * @@ -69,8 +73,9 @@ class add extends command * @param manager $password_manager * @param string $phpbb_root_path * @param string $php_ext + * @param service_collection $messenger */ - public function __construct(user $user, driver_interface $db, config $config, language $language, manager $password_manager, $phpbb_root_path, $php_ext) + public function __construct(user $user, driver_interface $db, config $config, language $language, manager $password_manager, $phpbb_root_path, $php_ext, service_collection $messenger) { $this->db = $db; $this->config = $config; @@ -78,6 +83,7 @@ class add extends command $this->password_manager = $password_manager; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + $this->messenger = $messenger; $this->language->add_lang('ucp'); parent::__construct($user); @@ -307,24 +313,18 @@ class add extends command $user_actkey = $this->get_activation_key($user_id); - if (!class_exists('messenger')) - { - require($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); - } - - $messenger = new \messenger(false); - $messenger->template($email_template, $this->user->lang_name); - $messenger->to($this->data['email'], $this->data['username']); - $messenger->anti_abuse_headers($this->config, $this->user); - $messenger->assign_vars(array( + $email = $this->messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template($email_template, $this->user->lang_name); + $email->to($this->data['email'], $this->data['username']); + $email->anti_abuse_headers($this->config, $this->user); + $email->assign_vars([ 'WELCOME_MSG' => html_entity_decode($this->language->lang('WELCOME_SUBJECT', $this->config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($this->data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->data['new_password'], ENT_COMPAT), - 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey") - ); - - $messenger->send(NOTIFY_EMAIL); - } + 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey", + ]); + $email->send(); /** * Get user activation key diff --git a/phpBB/phpbb/cron/task/core/queue.php b/phpBB/phpbb/cron/task/core/queue.php index 2f0d91d046..5e1f0d1be9 100644 --- a/phpBB/phpbb/cron/task/core/queue.php +++ b/phpBB/phpbb/cron/task/core/queue.php @@ -13,30 +13,35 @@ namespace phpbb\cron\task\core; +use \phpbb\config\config; +use \phpbb\messenger\queue; + /** * Queue cron task. Sends email and jabber messages queued by other scripts. */ class queue extends \phpbb\cron\task\base { - protected $phpbb_root_path; - protected $php_ext; - protected $cache_dir; + /** var config */ protected $config; + /** var queue */ + protected $queue; + + /** var string */ + protected $queue_cache_file; + /** * Constructor. * - * @param string $phpbb_root_path The root path - * @param string $php_ext PHP file extension - * @param \phpbb\config\config $config The config - * @param string $cache_dir phpBB cache directory + * @param config $config The config + * @param string $queue_cache_file The messenger file queue cache filename + * @param queue $queue The messenger file queue object */ - public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, $cache_dir) + public function __construct(config $config, queue $queue, $queue_cache_file) { - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; $this->config = $config; - $this->cache_dir = $cache_dir; + $this->queue = $queue; + $this->queue_cache_file = $queue_cache_file; } /** @@ -46,12 +51,7 @@ class queue extends \phpbb\cron\task\base */ public function run() { - if (!class_exists('queue')) - { - include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); - } - $queue = new \queue(); - $queue->process(); + $this->queue->process(); } /** @@ -63,7 +63,7 @@ class queue extends \phpbb\cron\task\base */ public function is_runnable() { - return file_exists($this->cache_dir . 'queue.' . $this->php_ext); + return file_exists($this->queue_cache_file); } /** diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index 6fb7bc2743..4d3402a6f5 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -14,62 +14,48 @@ namespace phpbb\install\module\install_finish\task; use phpbb\config\db; +use phpbb\install\helper\config; +use phpbb\install\helper\iohandler\iohandler_interface; +use phpbb\auth\auth; +use phpbb\log\log_interface; +use phpbb\user; +use phpbb\install\helper\container_factory; +use phpbb\di\service_collection; /** * Logs installation and sends an email to the admin */ class notify_user extends \phpbb\install\task_base { - /** - * @var \phpbb\install\helper\config - */ + /** @var config */ protected $install_config; - /** - * @var \phpbb\install\helper\iohandler\iohandler_interface - */ + /** @var iohandler_interface */ protected $iohandler; - /** - * @var \phpbb\auth\auth - */ + /** @var auth */ protected $auth; - /** - * @var db - */ + /** @var db */ protected $config; - /** - * @var \phpbb\log\log_interface - */ + /** @var log_interface */ protected $log; - /** - * @var \phpbb\user - */ + /** @var user */ protected $user; - /** - * @var string - */ - protected $phpbb_root_path; - - /** - * @var string - */ - protected $php_ext; + /** @var service_collection */ + protected $messenger; /** * Constructor * - * @param \phpbb\install\helper\container_factory $container - * @param \phpbb\install\helper\config $install_config - * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler - * @param string $phpbb_root_path - * @param string $php_ext + * @param container_factory $container + * @param config $install_config + * @param iohandler_interface $iohandler */ - public function __construct(\phpbb\install\helper\container_factory $container, \phpbb\install\helper\config $install_config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, $phpbb_root_path, $php_ext) + public function __construct(container_factory $container, config $install_config, iohandler_interface $iohandler) { $this->install_config = $install_config; $this->iohandler = $iohandler; @@ -77,8 +63,7 @@ class notify_user extends \phpbb\install\task_base $this->auth = $container->get('auth'); $this->log = $container->get('log'); $this->user = $container->get('user'); - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; + $this->messenger = $container->get('messenger.method_collection'); // We need to reload config for cases when it doesn't have all values /** @var \phpbb\cache\driver\driver_interface $cache */ @@ -107,17 +92,16 @@ class notify_user extends \phpbb\install\task_base if ($this->config['email_enable']) { - include ($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); - - $messenger = new \messenger(false); - $messenger->template('installed', $this->install_config->get('user_language', 'en')); - $messenger->to($this->config['board_email'], $this->install_config->get('admin_name')); - $messenger->anti_abuse_headers($this->config, $this->user); - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($this->install_config->get('admin_name'), ENT_COMPAT), - 'PASSWORD' => html_entity_decode($this->install_config->get('admin_passwd'), ENT_COMPAT)) - ); - $messenger->send(NOTIFY_EMAIL); + $email = $this->messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template('installed', $this->install_config->get('user_language', 'en')); + $email->to($this->config['board_email'], $this->install_config->get('admin_name')); + $email->anti_abuse_headers($this->config, $this->user); + $email->assign_vars([ + 'USERNAME' => html_entity_decode($this->install_config->get('admin_name'), ENT_COMPAT), + 'PASSWORD' => html_entity_decode($this->install_config->get('admin_passwd'), ENT_COMPAT), + ]); + $email->send(); } // Login admin @@ -141,7 +125,7 @@ class notify_user extends \phpbb\install\task_base $this->user->ip, 'LOG_INSTALL_INSTALLED', false, - array($this->config['version']) + [$this->config['version']] ); // Remove install_lock diff --git a/phpBB/phpbb/message/form.php b/phpBB/phpbb/message/form.php index c23b168906..479d687212 100644 --- a/phpBB/phpbb/message/form.php +++ b/phpBB/phpbb/message/form.php @@ -129,10 +129,10 @@ abstract class form /** * Submit form, generate the email and send it * - * @param \messenger $messenger + * @param \phpbb\di\service_collection $messenger * @return void */ - public function submit(\messenger $messenger) + public function submit(\phpbb\di\service_collection $messenger) { if (!check_form_key('memberlist_email')) { diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 554fe48a12..23960d4778 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -138,10 +138,10 @@ class message { $this->recipients[] = array( 'name' => $recipient_name, - 'address' => $recipient_address, + 'user_email' => $recipient_address, 'lang' => $recipient_lang, 'username' => $recipient_username, - 'jabber' => $recipient_jabber, + 'user_jabber' => $recipient_jabber, 'notify_type' => $recipient_notify_type, 'to_name' => $recipient_name, ); @@ -220,10 +220,10 @@ class message $this->recipients[] = array( 'lang' => $this->sender_lang, - 'address' => $this->sender_address, + 'user_email' => $this->sender_address, 'name' => $this->sender_name, 'username' => $this->sender_username, - 'jabber' => $this->sender_jabber, + 'user_jabber' => $this->sender_jabber, 'notify_type' => $this->sender_notify_type, 'to_name' => $this->recipients[0]['to_name'], ); @@ -232,11 +232,11 @@ class message /** * Send the email * - * @param \messenger $messenger + * @param \phpbb\di\service_collection $messenger * @param string $contact * @return void */ - public function send(\messenger $messenger, $contact) + public function send(\phpbb\di\service_collection $messenger, $contact) { if (!count($this->recipients)) { @@ -245,38 +245,46 @@ class message foreach ($this->recipients as $recipient) { - $messenger->template($this->template, $recipient['lang']); - $messenger->replyto($this->sender_address); - $messenger->to($recipient['address'], $recipient['name']); - $messenger->im($recipient['jabber'], $recipient['username']); - - $messenger->headers('X-AntiAbuse', 'Board servername - ' . $this->server_name); - $messenger->headers('X-AntiAbuse', 'User IP - ' . $this->sender_ip); - - if ($this->sender_id) + $messenger_collection_iterator = $this->messenger->getIterator(); + while ($messenger_collection_iterator->valid()) { - $messenger->headers('X-AntiAbuse', 'User_id - ' . $this->sender_id); + $messenger_method = $messenger_collection_iterator->current(); + $messenger_method->set_use_queue(false); + if ($messenger_method->get_id() == $recipient['notify_type'] || $recipient['notify_type'] == NOTIFY_BOTH) + { + $messenger_method->template($this->template, $recipient['lang']); + $messenger_method->set_addresses($recipient); + $messenger_method->replyto($this->sender_address); + + $messenger_method->headers('X-AntiAbuse', 'Board servername - ' . $this->server_name); + $messenger_method->headers('X-AntiAbuse', 'User IP - ' . $this->sender_ip); + if ($this->sender_id) + { + $messenger_method->headers('X-AntiAbuse', 'User_id - ' . $this->sender_id); + } + if ($this->sender_username) + { + $messenger_method->headers('X-AntiAbuse', 'Username - ' . $this->sender_username); + } + + $messenger_method->subject(html_entity_decode($this->subject, ENT_COMPAT)); + + $messenger_method->assign_vars([ + 'BOARD_CONTACT' => $contact, + 'TO_USERNAME' => html_entity_decode($recipient['to_name'], ENT_COMPAT), + 'FROM_USERNAME' => html_entity_decode($this->sender_name, ENT_COMPAT), + 'MESSAGE' => html_entity_decode($this->body, ENT_COMPAT), + ]); + + if (count($this->template_vars)) + { + $messenger_method->assign_vars($this->template_vars); + } + + $messenger_method->send(); + } + $messenger_collection_iterator->next(); } - if ($this->sender_username) - { - $messenger->headers('X-AntiAbuse', 'Username - ' . $this->sender_username); - } - - $messenger->subject(html_entity_decode($this->subject, ENT_COMPAT)); - - $messenger->assign_vars(array( - 'BOARD_CONTACT' => $contact, - 'TO_USERNAME' => html_entity_decode($recipient['to_name'], ENT_COMPAT), - 'FROM_USERNAME' => html_entity_decode($this->sender_name, ENT_COMPAT), - 'MESSAGE' => html_entity_decode($this->body, ENT_COMPAT)) - ); - - if (count($this->template_vars)) - { - $messenger->assign_vars($this->template_vars); - } - - $messenger->send($recipient['notify_type']); } } } diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 507b5beea8..d743d00b48 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -132,6 +132,38 @@ class base $this->subject = $subject; } + /** + * Adds antiabuse headers + * + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object + * @return void + */ + public function anti_abuse_headers($config, $user) + { + } + + /** + * Set up extra headers + * + * @param string $header_name Email header name + * @param string $header_value Email header body + * @return void + */ + public function header($header_name, $header_value) + { + } + + /** + * Set the reply to address + * + * @param string $address Email "Reply to" address + * @return void + */ + public function replyto($address) + { + } + /** * Set email template to use * @@ -232,7 +264,6 @@ class base public function assign_vars($vars) { $this->setup_template(); - $this->template->assign_vars($vars); } @@ -352,13 +383,15 @@ class base */ public function save_queue() { - $this->queue->save(); - return; + if ($this->use_queue && !empty($this->queue)) + { + $this->queue->save(); + return; + } } /** * Setup template engine - * * @return void */ protected function setup_template() @@ -402,7 +435,6 @@ class base protected function set_template_paths($path_name, $paths) { $this->setup_template(); - $this->template->set_custom_style($path_name, $paths); } } diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index 039591feb7..f6683e82d0 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -82,6 +82,16 @@ class email extends base /** @var Symfony\Component\Mailer\Transport */ protected $transport; + /** + * Get messenger method id + * + * @return int + */ + public function get_id() + { + return NOTIFY_EMAIL; + } + /** * Check if the messenger method is enabled * @return void @@ -286,19 +296,6 @@ class email extends base parent::error($type, $msg); } - /** - * Save message data to the messenger file queue - * @return void - */ - public function save_queue() - { - if ($this->config['email_package_size'] && $this->use_queue && !empty($this->queue)) - { - $this->queue->save(); - return; - } - } - /** * Detect proper Header class method to add header * diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index 2e7f2040da..33a8d19eb3 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -110,6 +110,16 @@ class jabber extends base ]; } + /** + * Get messenger method id + * + * @return int + */ + public function get_id() + { + return NOTIFY_IM; + } + /** * Check if the messenger method is enabled * @return void diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index cffd259c0e..dd181ac5a3 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -14,6 +14,11 @@ namespace phpbb\notification\method; use phpbb\notification\type\type_interface; +use phpbb\user; +use phpbb\user_loader; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\di\service_collection; /** * Email notification method class @@ -34,20 +39,33 @@ class email extends \phpbb\notification\method\messenger_base /** @var string Notification emails table */ protected $notification_emails_table; + /** @var service_collection */ + protected $messenger; + /** * Notification Method email Constructor * - * @param \phpbb\user_loader $user_loader - * @param \phpbb\user $user - * @param \phpbb\config\config $config - * @param \phpbb\db\driver\driver_interface $db + * @param user_loader $user_loader + * @param user $user + * @param config $config + * @param driver_interface $db * @param string $phpbb_root_path * @param string $php_ext * @param string $notification_emails_table + * @param service_collection $messenger */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext, $notification_emails_table) + public function __construct( + user_loader $user_loader, + user $user, + config $config, + driver_interface $db, + $phpbb_root_path, + $php_ext, + $notification_emails_table, + service_collection $messenger + ) { - parent::__construct($user_loader, $phpbb_root_path, $php_ext); + parent::__construct($messenger, $user_loader, $phpbb_root_path, $php_ext); $this->user = $user; $this->config = $config; diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php index 9a1aadb9a0..5765152139 100644 --- a/phpBB/phpbb/notification/method/jabber.php +++ b/phpBB/phpbb/notification/method/jabber.php @@ -14,6 +14,10 @@ namespace phpbb\notification\method; use phpbb\notification\type\type_interface; +use phpbb\user; +use phpbb\user_loader; +use phpbb\config\config; +use phpbb\di\service_collection; /** * Jabber notification method class @@ -28,18 +32,22 @@ class jabber extends \phpbb\notification\method\messenger_base /** @var \phpbb\config\config */ protected $config; + /** @var service_collection */ + protected $messenger; + /** * Notification Method jabber Constructor * - * @param \phpbb\user_loader $user_loader - * @param \phpbb\user $user - * @param \phpbb\config\config $config + * @param user_loader $user_loader + * @param user $user + * @param config $config * @param string $phpbb_root_path * @param string $php_ext + * @param service_collection $messenger */ - public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, $phpbb_root_path, $php_ext) + public function __construct(user_loader $user_loader, user $user, config $config, $phpbb_root_path, $php_ext, service_collection $messenger) { - parent::__construct($user_loader, $phpbb_root_path, $php_ext); + parent::__construct($messenger, $user_loader, $phpbb_root_path, $php_ext); $this->user = $user; $this->config = $config; diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 85461b282d..0d9b3c163b 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -14,6 +14,8 @@ namespace phpbb\notification\method; use phpbb\notification\type\type_interface; +use phpbb\di\service_collection; +use phpbb\user_loader; /** * Abstract notification method handling email and jabber notifications @@ -21,7 +23,10 @@ use phpbb\notification\type\type_interface; */ abstract class messenger_base extends \phpbb\notification\method\base { - /** @var \phpbb\user_loader */ + /** @var service_collection */ + protected $messenger; + + /** @var user_loader */ protected $user_loader; /** @var string */ @@ -33,12 +38,14 @@ abstract class messenger_base extends \phpbb\notification\method\base /** * Notification Method Board Constructor * - * @param \phpbb\user_loader $user_loader + * @param service_collection $messenger + * @param user_loader $user_loader * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(\phpbb\user_loader $user_loader, $phpbb_root_path, $php_ext) + public function __construct(service_collection $messenger, user_loader $user_loader, $phpbb_root_path, $php_ext) { + $this->messenger = $messenger; $this->user_loader = $user_loader; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -73,7 +80,7 @@ abstract class messenger_base extends \phpbb\notification\method\base } // Load all users we want to notify (we need their email address) - $user_ids = array(); + $user_ids = []; foreach ($this->queue as $notification) { $user_ids[] = $notification->user_id; @@ -89,13 +96,6 @@ abstract class messenger_base extends \phpbb\notification\method\base // Load all the users we need $this->user_loader->load_users(array_diff($user_ids, $banned_users), array(USER_IGNORE)); - // Load the messenger - if (!class_exists('messenger')) - { - include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); - } - $messenger = new \messenger(); - // Time to go through the queue and send emails /** @var type_interface $notification */ foreach ($this->queue as $notification) @@ -112,22 +112,28 @@ abstract class messenger_base extends \phpbb\notification\method\base continue; } - $messenger->template($notification->get_email_template(), $user['user_lang'], '', $template_dir_prefix); + $messenger_collection_iterator = $this->messenger->getIterator(); + while ($messenger_collection_iterator->valid()) + { + $messenger_method = $messenger_collection_iterator->current(); + if ($messenger_method->get_id() == $notify_method || $notify_method == NOTIFY_BOTH) + { + $messenger_method->template($notification->get_email_template(), $user['user_lang'], '', $template_dir_prefix); + $messenger_method->set_addresses($user); + $messenger_method->assign_vars(array_merge([ + 'USERNAME' => $user['username'], + 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications&mode=notification_options', + ], $notification->get_email_template_variables())); - $messenger->set_addresses($user); + $messenger_method->send(); - $messenger->assign_vars(array_merge(array( - 'USERNAME' => $user['username'], - - 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications&mode=notification_options', - ), $notification->get_email_template_variables())); - - $messenger->send($notify_method); + // Save the queue in the messenger method class (has to be called or these messages could be lost) + $messenger_method->save_queue(); + } + $messenger_collection_iterator->next(); + } } - // Save the queue in the messenger class (has to be called or these emails could be lost?) - $messenger->save_queue(); - // We're done, empty the queue $this->empty_queue(); } diff --git a/phpBB/phpbb/ucp/controller/reset_password.php b/phpBB/phpbb/ucp/controller/reset_password.php index 64c43a5d00..ae01972d7f 100644 --- a/phpBB/phpbb/ucp/controller/reset_password.php +++ b/phpBB/phpbb/ucp/controller/reset_password.php @@ -25,6 +25,7 @@ use phpbb\passwords\manager; use phpbb\request\request; use phpbb\template\template; use phpbb\user; +use phpbb\di\service_collection; use Symfony\Component\HttpFoundation\Response; /** @@ -71,6 +72,9 @@ class reset_password /** @var string PHP extension */ protected $php_ext; + /** @var service_collection */ + protected $messenger; + /** * Reset password controller constructor. * @@ -87,11 +91,12 @@ class reset_password * @param string $users_table * @param string $root_path * @param string $php_ext + * @param service_collection $messenger */ public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, helper $helper, language $language, log_interface $log, manager $passwords_manager, request $request, template $template, user $user, string $users_table, - string $root_path, string $php_ext) + string $root_path, string $php_ext, service_collection $messenger) { $this->config = $config; $this->db = $db; @@ -106,6 +111,7 @@ class reset_password $this->users_table = $users_table; $this->root_path = $root_path; $this->php_ext = $php_ext; + $this->messenger = $messenger; } /** @@ -250,29 +256,19 @@ class reset_password WHERE user_id = ' . $user_row['user_id']; $this->db->sql_query($sql); - if (!class_exists('messenger')) - { - include($this->root_path . 'includes/functions_messenger.' . $this->php_ext); - } - - /** @var \messenger $messenger */ - $messenger = new \messenger(false); - - $messenger->template('user_forgot_password', $user_row['user_lang']); - - $messenger->set_addresses($user_row); - - $messenger->anti_abuse_headers($this->config, $this->user); - - $messenger->assign_vars([ - 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), - 'U_RESET_PASSWORD' => generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [ - 'u' => $user_row['user_id'], - 'token' => $reset_token, - ], false) + $email = $this->messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template('user_forgot_password', $user_row['user_lang']); + $email->set_addresses($user_row); + $email->anti_abuse_headers($this->config, $this->user); + $email->assign_vars([ + 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), + 'U_RESET_PASSWORD' => generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [ + 'u' => $user_row['user_id'], + 'token' => $reset_token, + ], false) ]); - - $messenger->send($user_row['user_notify_type']); + $email->send(); return $this->helper->message($message); } From 1f952ca6d84ab48178157d00f887a159d0af4393 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 6 Jun 2023 16:41:55 +0700 Subject: [PATCH 08/29] [ticket/17135] Refactor messenger code to services [ci skip] PHPBB3-17135 --- phpBB/includes/ucp/ucp_register.php | 30 ++++++------- phpBB/includes/ucp/ucp_resend.php | 58 +++++++++++++++---------- phpBB/phpbb/message/message.php | 12 ++--- phpBB/phpbb/messenger/method/base.php | 36 ++++++++++----- phpBB/phpbb/messenger/method/email.php | 5 ++- phpBB/phpbb/messenger/method/jabber.php | 15 +++++++ 6 files changed, 99 insertions(+), 57 deletions(-) diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index b8d0d78b40..734c83089b 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -458,30 +458,26 @@ class ucp_register if ($config['email_enable']) { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - - $messenger = new messenger(false); - - $messenger->template($email_template, $data['lang']); - - $messenger->to($data['email'], $data['username']); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $this->messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template($email_template, $data['lang']); + $email->to($data['email'], $data['username']); + $email->anti_abuse_headers($config, $user); + $email->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($data['new_password'], ENT_COMPAT), - 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$user_id&k=$user_actkey") - ); + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$user_id&k=$user_actkey", + ]); if ($coppa) { - $messenger->assign_vars(array( + $email->assign_vars([ 'FAX_INFO' => $config['coppa_fax'], 'MAIL_INFO' => $config['coppa_mail'], - 'EMAIL_ADDRESS' => $data['email']) - ); + 'EMAIL_ADDRESS' => $data['email'], + ]); } /** @@ -510,7 +506,7 @@ class ucp_register ); extract($phpbb_dispatcher->trigger_event('core.ucp_register_welcome_email_before', compact($vars))); - $messenger->send(NOTIFY_EMAIL); + $email->send(); } if ($config['require_activation'] == USER_ACTIVATION_ADMIN) diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 31e0878663..122aeeca37 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -30,7 +30,7 @@ class ucp_resend function main($id, $mode) { global $config, $phpbb_root_path, $phpEx; - global $db, $user, $auth, $template, $request; + global $db, $user, $auth, $template, $request, $phpbb_container; $username = $request->variable('username', '', true); $email = strtolower($request->variable('email', '')); @@ -94,32 +94,33 @@ class ucp_resend $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false; - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $messenger = new messenger(false); + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa) { - $messenger->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); - $messenger->set_addresses($user_row); + $email->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); + $email->set_addresses($user_row); - $messenger->anti_abuse_headers($config, $user); + $email->anti_abuse_headers($config, $user); - $messenger->assign_vars(array( + $email->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), - 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}") - ); + 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", + ]); if ($coppa) { - $messenger->assign_vars(array( + $email->assign_vars([ 'FAX_INFO' => $config['coppa_fax'], 'MAIL_INFO' => $config['coppa_mail'], - 'EMAIL_ADDRESS' => $user_row['user_email']) - ); + 'EMAIL_ADDRESS' => $user_row['user_email'], + ]); } - $messenger->send(NOTIFY_EMAIL); + $email->send(); } if ($config['require_activation'] == USER_ACTIVATION_ADMIN) @@ -132,20 +133,31 @@ class ucp_resend WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); $result = $db->sql_query($sql); + $messenger_collection_iterator = $messenger->getIterator(); while ($row = $db->sql_fetchrow($result)) { - $messenger->template('admin_activate', $row['user_lang']); - $messenger->set_addresses($row); + while ($messenger_collection_iterator->valid()) + { + $messenger_method = $messenger_collection_iterator->current(); + $messenger_method->set_use_queue(false); + if ($messenger_method->get_id() == $row['user_notify_type'] || $row['user_notify_type'] == NOTIFY_BOTH) + { + $messenger_method->template('admin_activate', $row['user_lang']); + $messenger_method->set_addresses($row); + $messenger_method->anti_abuse_headers($config, $user); + $messenger_method->assign_vars([ + 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), + 'U_USER_DETAILS' => generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$user_row['user_id']}", + 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", + ]); - $messenger->anti_abuse_headers($config, $user); + $messenger_method->send(); - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), - 'U_USER_DETAILS' => generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$user_row['user_id']}", - 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}") - ); - - $messenger->send($row['user_notify_type']); + // Save the queue in the messenger method class (has to be called or these messages could be lost) + $messenger_method->save_queue(); + } + $messenger_collection_iterator->next(); + } } $db->sql_freeresult($result); } diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 23960d4778..2a750c1f21 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -141,7 +141,7 @@ class message 'user_email' => $recipient_address, 'lang' => $recipient_lang, 'username' => $recipient_username, - 'user_jabber' => $recipient_jabber, + 'user_jabber' => $recipient_jabber, 'notify_type' => $recipient_notify_type, 'to_name' => $recipient_name, ); @@ -245,7 +245,7 @@ class message foreach ($this->recipients as $recipient) { - $messenger_collection_iterator = $this->messenger->getIterator(); + $messenger_collection_iterator = $messenger->getIterator(); while ($messenger_collection_iterator->valid()) { $messenger_method = $messenger_collection_iterator->current(); @@ -256,15 +256,15 @@ class message $messenger_method->set_addresses($recipient); $messenger_method->replyto($this->sender_address); - $messenger_method->headers('X-AntiAbuse', 'Board servername - ' . $this->server_name); - $messenger_method->headers('X-AntiAbuse', 'User IP - ' . $this->sender_ip); + $messenger_method->header('X-AntiAbuse', 'Board servername - ' . $this->server_name); + $messenger_method->header('X-AntiAbuse', 'User IP - ' . $this->sender_ip); if ($this->sender_id) { - $messenger_method->headers('X-AntiAbuse', 'User_id - ' . $this->sender_id); + $messenger_method->header('X-AntiAbuse', 'User_id - ' . $this->sender_id); } if ($this->sender_username) { - $messenger_method->headers('X-AntiAbuse', 'Username - ' . $this->sender_username); + $messenger_method->header('X-AntiAbuse', 'Username - ' . $this->sender_username); } $messenger_method->subject(html_entity_decode($this->subject, ENT_COMPAT)); diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index d743d00b48..71e0b798d1 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -25,14 +25,11 @@ use phpbb\user; /** * Messenger base class */ -class base +abstract class base { /** @var array */ protected $additional_headers = []; - /** @var array */ - protected $addresses = []; - /** @var config */ protected $config; @@ -90,6 +87,15 @@ class base $this->set_use_queue(); } + /** + * Get messenger method id + * @return mixed + */ + abstract public function get_id() + { + return; + } + /** * Sets the use of messenger queue flag * @@ -105,10 +111,12 @@ class base * * @return void */ - public function reset() + abstract public function reset() { - $this->addresses = []; + $this->subject = $this->additional_headers = []; $this->msg = ''; + $this->use_queue = true; + unset($this->template); } /** @@ -117,7 +125,7 @@ class base * @param array $user User row * @return void */ - public function set_addresses($user) + abstract public function set_addresses($user) { } @@ -164,6 +172,14 @@ class base { } + /** + * Send out messages + * @return bool + */ + abstract protected function send() + { + } + /** * Set email template to use * @@ -295,7 +311,7 @@ class base 'SITENAME' => html_entity_decode($this->config['sitename'], ENT_COMPAT), ]); - $subject = $this->email->getSubject(); + $subject = $this->subject; $template = $this->template; /** * Event to modify the template before parsing @@ -304,7 +320,7 @@ class base * @var string subject The message subject * @var \phpbb\template\template template The (readonly) template object * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. + * @changed 4.0.0-a1 Removed vars: method, break. */ $vars = ['subject', 'template']; extract($this->dispatcher->trigger_event('core.modify_notification_template', compact($vars))); @@ -378,7 +394,7 @@ class base } /** - * Save message data to the messemger file queue + * Save message data to the messenger file queue * @return void */ public function save_queue() diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index f6683e82d0..d8025d431b 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -106,12 +106,14 @@ class email extends base * * @return void */ - public function init() + public function reset() { $this->email = new Email(); $this->headers = $this->email->getHeaders(); $this->msg = $this->replyto = $this->from = ''; $this->mail_priority = Email::PRIORITY_NORMAL; + + parent::reset(); } /** @@ -567,6 +569,7 @@ class email extends base 'email' => $this->email, ]); } + $this->reset(); return true; } diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index 33a8d19eb3..439150a013 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -393,6 +393,19 @@ class jabber extends base $this->to[$pos]['name'] = trim($realname); } + /** + * Inits/resets the data to default + * + * @return void + */ + public function reset() + { + $this->msg = ''; + $this->to = []; + + parent::reset(); + } + /** * Sets the use of messenger queue flag * @@ -455,6 +468,8 @@ class jabber extends base } unset($addresses); + $this->reset(); + return true; } From 5873c72ca5dd53d964bc7ab25cce1e24490ed7a4 Mon Sep 17 00:00:00 2001 From: rxu Date: Wed, 7 Jun 2023 21:16:41 +0700 Subject: [PATCH 09/29] [ticket/17135] Refactor messenger code to services [ci skip] PHPBB3-17135 --- phpBB/phpbb/messenger/method/base.php | 19 +++ phpBB/phpbb/messenger/method/email.php | 74 ++++++++ phpBB/phpbb/messenger/method/jabber.php | 88 +++++++++- phpBB/phpbb/messenger/queue.php | 217 ++++++++++++++++++++++++ 4 files changed, 390 insertions(+), 8 deletions(-) create mode 100644 phpBB/phpbb/messenger/queue.php diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 71e0b798d1..28b9cde636 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -96,6 +96,15 @@ abstract class base return; } + /** + * get messenger method fie queue object name + * @return string + */ + abstract public function get_queue_object_name($user) + { + return ''; + } + /** * Sets the use of messenger queue flag * @@ -180,6 +189,16 @@ abstract class base { } + /** + * Send messages from the queue + * + * @param array $queue_data Queue data array + * @return void + */ + abstract public function process_queue(&$queue_data) + { + } + /** * Set email template to use * diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index d8025d431b..1968c6771e 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -92,6 +92,15 @@ class email extends base return NOTIFY_EMAIL; } + /** + * get messenger method fie queue object name + * @return string + */ + abstract public function get_queue_object_name($user) + { + return 'email'; + } + /** * Check if the messenger method is enabled * @return void @@ -438,6 +447,71 @@ class email extends base } } + /** + * Send messages from the queue + * + * @param array $queue_data Queue data array + * @return void + */ + public function process_queue(&$queue_data) + { + $queue_object_name = $this->get_queue_object_name(); + $messages_count = count($queue_data[$queue_object_name]['data']; + + if (!$this->is_enabled() || !$messages_count) + { + unset($queue_data[$queue_object_name]); + return; + } + + @set_time_limit(0); + + $package_size = $queue_data[$queue_object_name]['package_size'] ?? 0; + $num_items = (!$package_size || $messages_count < $package_size) ? $messages_count : $package_size; + $mailer = new Mailer($this->transport); + + for ($i = 0; $i < $num_items; $i++) + { + // Make variables available... + extract(array_shift($queue_data[$queue_object_name]['data'])); + + $break = false; + /** + * Event to send message via external transport + * + * @event core.notification_message_process + * @var bool break Flag indicating if the function return after hook + * @var Symfony\Component\Mime\Email email The Symfony Email object + * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, subject, msg. + */ + $vars = [ + 'break', + 'email', + ]; + extract($this->dispatcher->trigger_event('core.notification_message_process', compact($vars))); + + if (!$break) + { + try + { + $mailer->send($email); + } + catch (TransportExceptionInterface $e) + { + $this->error('EMAIL', $e->getDebug()); + continue; + } + } + } + + // No more data for this object? Unset it + if (!count($this->queue_data[$queue_object_name]['data'])) + { + unset($this->queue_data[$queue_object_name]); + } + } + /** * Get mailer transport object * diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index 439150a013..9661efc64a 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -120,6 +120,15 @@ class jabber extends base return NOTIFY_IM; } + /** + * get messenger method fie queue object name + * @return string + */ + abstract public function get_queue_object_name($user) + { + return 'jabber'; + } + /** * Check if the messenger method is enabled * @return void @@ -127,10 +136,10 @@ class jabber extends base public function is_enabled() { return - empty($this->config['jab_enable']) || - empty($this->config['jab_host']) || - empty($this->config['jab_username']) || - empty($this->config['jab_password']); + !empty($this->config['jab_enable']) && + !empty($this->config['jab_host']) && + !empty($this->config['jab_username']) && + !empty($this->config['jab_password']); } /** @@ -416,6 +425,65 @@ class jabber extends base $this->use_queue = !$this->config['jab_package_size'] ? false : $use_queue; } + /** + * Send messages from the queue + * + * @param array $queue_data Queue data array + * @return void + */ + public function process_queue(&$queue_data) + { + $queue_object_name = $this->get_queue_object_name(); + $messages_count = count($queue_data[$queue_object_name]['data']; + + if (!$this->is_enabled() || !$messages_count) + { + unset($queue_data[$queue_object_name]); + return; + } + + @set_time_limit(0); + + $package_size = $queue_data[$queue_object_name]['package_size'] ?? 0; + $num_items = (!$package_size || $messages_count < $package_size) ? $messages_count : $package_size; + $mailer = new Mailer($this->transport); + + for ($i = 0; $i < $num_items; $i++) + { + // Make variables available... + extract(array_shift($queue_data[$queue_object_name]['data'])); + + if (!$this->connect()) + { + $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->get_log()); + return false; + } + + if (!$this->login()) + { + $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->get_log()); + return false; + } + + foreach ($addresses as $address) + { + if ($this->send_message($address, $msg, $subject) === false) + { + $this->error('JABBER', $this->get_log()); + continue; + } + } + } + + // No more data for this object? Unset it + if (!count($this->queue_data[$queue_object_name]['data'])) + { + unset($this->queue_data[$queue_object_name]); + } + + $this->disconnect(); + } + /** * Send jabber message out */ @@ -452,7 +520,11 @@ class jabber extends base foreach ($addresses as $address) { - $this->send_message($address, $this->msg, $this->subject); + if ($this->send_message($address, $this->msg, $this->subject) === false) + { + $this->error('JABBER', $this->get_log()); + continue; + } } $this->disconnect(); @@ -460,11 +532,11 @@ class jabber extends base else { $this->queue->init('jabber', $this->config['jab_package_size']); - $this->queue->put('jabber', array( + $this->queue->put('jabber', [ 'addresses' => $addresses, 'subject' => $this->subject, - 'msg' => $this->msg) - ); + 'msg' => $this->msg, + ]); } unset($addresses); diff --git a/phpBB/phpbb/messenger/queue.php b/phpBB/phpbb/messenger/queue.php new file mode 100644 index 0000000000..eb2406e273 --- /dev/null +++ b/phpBB/phpbb/messenger/queue.php @@ -0,0 +1,217 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\messenger; + +use phpbb\config\config; +use phpbb\event\dispatcher; +use phpbb\di\service_collection; +use phpbb\filesystem\filesystem; + +/** + * Handling messenger file queue + */ +class queue +{ + /** @var string */ + protected $cache_file; + + /** @var config */ + protected $config; + + /** @var array */ + protected $data = []; + + /** @var dispatcher */ + protected $dispatcher; + + /** @var phpbb\filesystem\filesystem_interface */ + protected $filesystem; + + /** @var service_collection */ + protected $messenger_method_collection; + + /** @var int */ + protected $package_size = 0; + + /** @var array */ + protected $queue_data = []; + + /** + * Messenger queue constructor. + * + * @param config $config + * @param dispatcher $dispatcher + * @param service_collection $messenger_method_collection + * @param string $cache_file + */ + function __construct(config $config, dispatcher $dispatcher, service_collection $messenger_method_collection, $cache_file) + { + $this->config = $config; + $this->dispatcher = $dispatcher; + $this->messenger_method_collection = $messenger_method_collection; + $this->filesystem = new filesystem(); + $this->cache_file = $cache_file; + } + + /** + * Init a queue object + * + * @param string $object Queue object type: email/jabber/etc + * @param int $package_size Size of the messenger package to send + * @return void + */ + public function init($object, $package_size) + { + $this->data[$object] = []; + $this->data[$object]['package_size'] = $package_size; + $this->data[$object]['data'] = []; + } + + /** + * Put message into the messenger file queue + * + * @param string $object Queue object type: email/jabber/etc + * @param mixed $message_data Message data to send + * @return void + */ + public function put($object, $message_data) + { + $this->data[$object]['data'][] = $message_data; + } + + /** + * Process the messenger file queue (using lock file) + * + * @return void + */ + public function process() + { + $lock = new \phpbb\lock\flock($this->cache_file); + $lock->acquire(); + + // avoid races, check file existence once + $have_cache_file = file_exists($this->cache_file); + if (!$have_cache_file || $this->config['last_queue_run'] > time() - $this->config['queue_interval']) + { + if (!$have_cache_file) + { + $this->config->set('last_queue_run', time(), false); + } + + $lock->release(); + return; + } + + $this->config->set('last_queue_run', time(), false); + + include($this->cache_file); + + $messenger_collection_iterator = $this->messenger_method_collection->getIterator(); + while ($messenger_collection_iterator->valid()) + { + $messenger_method = $messenger_collection_iterator->current(); + if (isset($this->queue_data[$messenger_method->get_queue_object_name()]) + { + $messenger_method->process_queue($this->queue_data); + } + $messenger_collection_iterator->next(); + } + + if (!count($this->queue_data)) + { + @unlink($this->cache_file); + } + else + { + if ($fp = @fopen($this->cache_file, 'wb')) + { + fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); + fclose($fp); + + if (function_exists('opcache_invalidate')) + { + @opcache_invalidate($this->cache_file); + } + + try + { + $this->filesystem->phpbb_chmod($this->cache_file, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + } + } + + $lock->release(); + } + + /** + * Save message data to the messenger file queue + * + * @return void + */ + public function save() + { + if (!count($this->data)) + { + return; + } + + $lock = new \phpbb\lock\flock($this->cache_file); + $lock->acquire(); + + if (file_exists($this->cache_file)) + { + include($this->cache_file); + + foreach ($this->queue_data as $object => $data_ary) + { + if (isset($this->data[$object]) && count($this->data[$object])) + { + $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']); + } + else + { + $this->data[$object]['data'] = $data_ary['data']; + } + } + } + + if ($fp = @fopen($this->cache_file, 'w')) + { + fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); + fclose($fp); + + if (function_exists('opcache_invalidate')) + { + @opcache_invalidate($this->cache_file); + } + + try + { + $this->filesystem->phpbb_chmod($this->cache_file, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } + + $this->data = []; + } + + $lock->release(); + } +} From f95816cbe3f331df651140c30d6f82fd3b40dba9 Mon Sep 17 00:00:00 2001 From: rxu Date: Thu, 8 Jun 2023 15:23:09 +0700 Subject: [PATCH 10/29] [ticket/17135] Refactor messenger code to services [ci skip] PHPBB3-17135 --- build/psalm_bootstrap.php | 1 - phpBB/includes/acp/acp_board.php | 18 +++---- phpBB/includes/acp/acp_email.php | 67 ++++++++++++++------------ phpBB/includes/acp/acp_inactive.php | 69 ++++++++++++--------------- phpBB/includes/acp/acp_users.php | 56 ++++++++-------------- phpBB/includes/mcp/mcp_pm_reports.php | 2 - phpBB/includes/mcp/mcp_queue.php | 7 --- phpBB/includes/mcp/mcp_reports.php | 2 - phpBB/includes/mcp/mcp_topic.php | 1 - phpBB/includes/ucp/ucp_activate.php | 32 +++++++------ phpBB/includes/ucp/ucp_profile.php | 24 ++++------ tests/email/email_parsing_test.php | 25 +++++----- 12 files changed, 137 insertions(+), 167 deletions(-) diff --git a/build/psalm_bootstrap.php b/build/psalm_bootstrap.php index 03afd6da3d..92099c77f5 100644 --- a/build/psalm_bootstrap.php +++ b/build/psalm_bootstrap.php @@ -33,7 +33,6 @@ require_once $phpbb_root_path . 'includes/functions_compress.' . $phpEx; require_once $phpbb_root_path . 'includes/functions_content.' . $phpEx; require_once $phpbb_root_path . 'includes/functions_display.' . $phpEx; require_once $phpbb_root_path . 'includes/functions_mcp.' . $phpEx; -require_once $phpbb_root_path . 'includes/functions_messenger.' . $phpEx; require_once $phpbb_root_path . 'includes/functions_module.' . $phpEx; require_once $phpbb_root_path . 'includes/functions_posting.' . $phpEx; require_once $phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx; diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 2afa79b1e6..3537b67737 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -720,17 +720,17 @@ class acp_board { if ($config['email_enable']) { - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - - $messenger = new messenger(false); - $messenger->template('test'); - $messenger->set_addresses($user->data); - $messenger->anti_abuse_headers($config, $user); - $messenger->assign_vars(array( + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template('test'); + $email->set_addresses($user->data); + $email->anti_abuse_headers($config, $user); + $email->assign_vars([ 'USERNAME' => html_entity_decode($user->data['username'], ENT_COMPAT), 'MESSAGE' => html_entity_decode($request->variable('send_test_email_text', '', true), ENT_COMPAT), - )); - $messenger->send(NOTIFY_EMAIL); + ]); + $email->send(); trigger_error($user->lang('TEST_EMAIL_SENT') . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index cddf7b3324..23f7885e53 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -182,25 +182,13 @@ class acp_email } } - // Send the messages - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - - if (!function_exists('get_group_name')) - { - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); - } - $messenger = new messenger($use_queue); - $errored = false; $email_template = 'admin_send_email'; - $template_data = array( + $template_data = [ 'CONTACT_EMAIL' => phpbb_get_board_contact($config, $phpEx), 'MESSAGE' => html_entity_decode($message, ENT_COMPAT), - ); + ]; $generate_log_entry = true; /** @@ -229,31 +217,50 @@ class acp_email ); extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); + $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger_collection_iterator = $messenger->getIterator(); for ($i = 0, $size = count($email_list); $i < $size; $i++) { $used_lang = $email_list[$i][0]['lang']; $used_method = $email_list[$i][0]['method']; - for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) + while ($messenger_collection_iterator->valid()) { - $email_row = $email_list[$i][$j]; + $messenger_method = $messenger_collection_iterator->current(); + if ($messenger_method->get_id() == $used_method || $used_method == NOTIFY_BOTH) + { + $messenger_method->set_use_queue($use_queue); + $messenger_method->template($email_template, $used_lang); + $messenger_method->subject(html_entity_decode($subject, ENT_COMPAT)); + $messenger_method->assign_vars($template_data); - $messenger->{((count($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); - $messenger->im($email_row['jabber'], $email_row['name']); - } + if ($messenger_method->get_id() == NOTIFY_EMAIL) + { + for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) + { + $email_row = $email_list[$i][$j]; + $messenger_method->{((count($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); + } - $messenger->template($email_template, $used_lang); + $messenger_method->anti_abuse_headers($config, $user); + $messenger_method->set_mail_priority($priority); + } + else if ($messenger_method->get_id() == NOTIFY_JABBER) + { + for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) + { + $email_row = $email_list[$i][$j]; + $messenger_method->to($email_row['jabber'], $email_row['name']); + } + } - $messenger->anti_abuse_headers($config, $user); - - $messenger->subject(html_entity_decode($subject, ENT_COMPAT)); - $messenger->set_mail_priority($priority); - - $messenger->assign_vars($template_data); - - if (!($messenger->send($used_method))) - { - $errored = true; + $errored = !$messenger_method->send(); + if ($use_queue) + { + $messenger_method->save_queue(); + } + } + $messenger_collection_iterator->next(); } } unset($email_list); diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 0301a53c2b..13427a8191 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -114,29 +114,20 @@ class acp_inactive if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !empty($inactive_users)) { - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - - $messenger = new messenger(false); + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); foreach ($inactive_users as $row) { - $messenger->template('admin_welcome_activated', $row['user_lang']); - - $messenger->set_addresses($row); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($row['username'], ENT_COMPAT)) - ); - - $messenger->send(NOTIFY_EMAIL); + $email->template('admin_welcome_activated', $row['user_lang']); + $email->set_addresses($row); + $email->anti_abuse_headers($config, $user); + $email->assign_vars([ + 'USERNAME' => html_entity_decode($row['username'], ENT_COMPAT), + ]); + $email->send(); } - - $messenger->save_queue(); } if (!empty($inactive_users)) @@ -207,37 +198,37 @@ class acp_inactive if ($row = $db->sql_fetchrow($result)) { // Send the messages - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - - $messenger = new messenger(); $usernames = $user_ids = array(); + $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger_collection_iterator = $messenger->getIterator(); do { - $messenger->template('user_remind_inactive', $row['user_lang']); + while ($messenger_collection_iterator->valid()) + { + $messenger_method = $messenger_collection_iterator->current(); + if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) + { + $messenger_method->template('user_remind_inactive', $row['user_lang']); + $messenger_method->set_addresses($row); + $messenger_method->anti_abuse_headers($config, $user); + $messenger_method->assign_vars([ + 'USERNAME' => html_entity_decode($row['username'], ENT_COMPAT), + 'REGISTER_DATE' => $user->format_date($row['user_regdate'], false, true), + 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey'], + ]); - $messenger->set_addresses($row); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($row['username'], ENT_COMPAT), - 'REGISTER_DATE' => $user->format_date($row['user_regdate'], false, true), - 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey']) - ); - - $messenger->send($row['user_notify_type']); + $messenger_method->send(); + $messenger_method->save_queue(); + } + $messenger_collection_iterator->next(); + } $usernames[] = $row['username']; $user_ids[] = (int) $row['user_id']; } while ($row = $db->sql_fetchrow($result)); - $messenger->save_queue(); - // Add the remind state to the database and increase activation expiration by one day $sql = 'UPDATE ' . USERS_TABLE . ' SET user_reminded = user_reminded + 1, diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 75b1cde0d8..707e6b5541 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -364,11 +364,6 @@ class acp_users if ($config['email_enable']) { - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - $server_url = generate_board_url(); $user_actkey = gen_rand_string(mt_rand(6, 10)); @@ -403,21 +398,18 @@ class acp_users $db->sql_query($sql); // Start sending email - $messenger = new messenger(false); - - $messenger->template($email_template, $user_row['user_lang']); - - $messenger->set_addresses($user_row); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template($email_template, $user_row['user_lang']); + $email->set_addresses($user_row); + $email->anti_abuse_headers($config, $user); + $email->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), - 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey") - ); - - $messenger->send(NOTIFY_EMAIL); + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey", + ]); + $email->send(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username'])); $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array( @@ -462,24 +454,16 @@ class acp_users $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - - $messenger = new messenger(false); - - $messenger->template('admin_welcome_activated', $user_row['user_lang']); - - $messenger->set_addresses($user_row); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT)) - ); - - $messenger->send(NOTIFY_EMAIL); + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $messenger->offsetGet('messenger.method.email'); + $email->set_use_queue(false); + $email->template('admin_welcome_activated', $user_row['user_lang']); + $email->set_addresses($user_row); + $email->anti_abuse_headers($config, $user); + $email->assign_vars([ + 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), + ]); + $email->send(); } } diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index 63fabb35db..afb3cb102d 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -51,8 +51,6 @@ class mcp_pm_reports { case 'close': case 'delete': - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $report_id_list = $request->variable('report_id_list', array(0)); if (!count($report_id_list)) diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index fbde670bd0..57f6d4c94b 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -50,8 +50,6 @@ class mcp_queue { case 'approve': case 'restore': - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $post_id_list = $request->variable('post_id_list', array(0)); $topic_id_list = $request->variable('topic_id_list', array(0)); @@ -113,11 +111,6 @@ class mcp_queue return; } - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } - if (!empty($topic_id_list)) { $post_visibility = ($mode == 'deleted_topics') ? ITEM_DELETED : array(ITEM_UNAPPROVED, ITEM_REAPPROVE); diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 97d1dbbfda..7843bc1efe 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -49,8 +49,6 @@ class mcp_reports { case 'close': case 'delete': - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $report_id_list = $request->variable('report_id_list', array(0)); if (!count($report_id_list)) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index cad43866fc..d19d1ad9d7 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -107,7 +107,6 @@ function mcp_topic_view($id, $mode, $action) } include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); if (!count($post_id_list)) { diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index da25425e3a..2db88c6934 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -131,21 +131,25 @@ class ucp_activate $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger_collection_iterator = $messenger->getIterator(); + while ($messenger_collection_iterator->valid()) + { + $messenger_method = $messenger_collection_iterator->current(); + if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) + { + $messenger_method->set_use_queue(false); + $messenger_method->template('admin_welcome_activated', $user_row['user_lang']); + $messenger_method->set_addresses($user_row); + $messenger_method->anti_abuse_headers($config, $user); + $messenger_method->assign_vars([ + 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), + ]); - $messenger = new messenger(false); - - $messenger->template('admin_welcome_activated', $user_row['user_lang']); - - $messenger->set_addresses($user_row); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( - 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT)) - ); - - $messenger->send($user_row['user_notify_type']); + $messenger_method->send(); + } + $messenger_collection_iterator->next(); + } $message = 'ACCOUNT_ACTIVE_ADMIN'; } diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 36ccd76156..c142a2af73 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -170,27 +170,21 @@ class ucp_profile { $message = ($config['require_activation'] == USER_ACTIVATION_SELF) ? 'ACCOUNT_EMAIL_CHANGED' : 'ACCOUNT_EMAIL_CHANGED_ADMIN'; - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $server_url = generate_board_url(); $user_actkey = gen_rand_string(mt_rand(6, 10)); - $messenger = new messenger(false); - + $messenger = $phpbb_container->get('messenger.method_collection'); + $email = $messenger->offsetGet('messenger.method.email'); $template_file = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? 'user_activate_inactive' : 'user_activate'; - $messenger->template($template_file, $user->data['user_lang']); - - $messenger->to($data['email'], $data['username']); - - $messenger->anti_abuse_headers($config, $user); - - $messenger->assign_vars(array( + $email->template($template_file, $user->data['user_lang']); + $email->to($data['email'], $data['username']); + $email->anti_abuse_headers($config, $user); + $email->assign_vars([ 'USERNAME' => html_entity_decode($data['username'], ENT_COMPAT), - 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey") - ); - - $messenger->send(NOTIFY_EMAIL); + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey", + ]); + $email->send(); if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index dd7b055ac7..ff0854be21 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -109,14 +109,17 @@ class phpbb_email_parsing_test extends phpbb_test_case $phpbb_container->setParameter('core.root_path', $phpbb_root_path); $phpbb_container->setParameter('core.php_ext', $phpEx); - if (!class_exists('messenger')) - { - include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - } + $core_cache_dir = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + $phpbb_container->setParameter('core.cache_dir', $core_cache_dir); + $core_messenger_queue_file = $core_cache_dir . 'queue.' . $phpEx; + $phpbb_container->setParameter('core.messenger_queue_file', $core_messenger_queue_file); + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + $messenger_queue = new \phpbb\messenger\queue($config, $dispatcher, $messenger_method_collection, $core_messenger_queue_file); + $phpbb_container->set('messenger.queue', $messenger_queue); + $this->email = new \phpbb\messenger\email($config, $dispatcher, $lang, $log, $request, $user, $messenger_queue); - $this->messenger = new \messenger(); - - $reflection = new ReflectionObject($this->messenger); + $reflection = new ReflectionObject($this->email); $this->reflection_template_property = $reflection->getProperty('template'); $this->reflection_template_property->setAccessible(true); } @@ -136,9 +139,9 @@ class phpbb_email_parsing_test extends phpbb_test_case { global $config, $phpEx, $user; - $this->messenger->set_addresses($user->data); + $this->email->set_addresses($user->data); - $this->messenger->assign_vars(array( + $this->email->assign_vars(array( 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . html_entity_decode($config['board_email_sig'], ENT_COMPAT)), 'SITENAME' => html_entity_decode($config['sitename'], ENT_COMPAT), @@ -150,9 +153,9 @@ class phpbb_email_parsing_test extends phpbb_test_case 'U_FORUM' => generate_board_url() . "/viewforum.{$phpEx}?f=1", 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.{$phpEx}?uid=2&f=1&unwatch=forum", )); - $this->messenger->template('newtopic_notify', $user->data['user_lang'], '', ''); + $this->email->template('newtopic_notify', $user->data['user_lang'], '', ''); - $reflection_template = $this->reflection_template_property->getValue($this->messenger); + $reflection_template = $this->reflection_template_property->getValue($this->email); $msg = trim($reflection_template->assign_display('body')); $this->assertStringContainsString($author_name, $msg); From a7b5369138d8bc479688c86d34596c28f4a712e5 Mon Sep 17 00:00:00 2001 From: rxu Date: Thu, 8 Jun 2023 21:17:01 +0700 Subject: [PATCH 11/29] [ticket/17135] Refactor messenger code to services PHPBB3-17135 --- .../default/container/services_messenger.yml | 13 +- .../container/services_install_finish.yml | 1 + phpBB/includes/ucp/ucp_register.php | 2 +- phpBB/phpbb/console/command/user/add.php | 1 + phpBB/phpbb/cron/task/core/queue.php | 9 +- .../install_finish/task/notify_user.php | 7 +- phpBB/phpbb/message/admin_form.php | 2 +- phpBB/phpbb/message/topic_form.php | 2 +- phpBB/phpbb/message/user_form.php | 2 +- phpBB/phpbb/messenger/method/base.php | 116 +++++++++++------- .../method/{email.php => phpbb_email.php} | 82 +++++-------- .../method/{jabber.php => phpbb_jabber.php} | 46 +++---- phpBB/phpbb/messenger/queue.php | 2 +- phpBB/phpbb/notification/method/email.php | 6 +- phpBB/phpbb/notification/method/jabber.php | 4 +- tests/console/user/activate_test.php | 3 +- tests/console/user/add_test.php | 3 +- tests/console/user/base.php | 5 + tests/email/email_parsing_test.php | 15 ++- tests/notification/base.php | 5 + .../notification_method_email_test.php | 8 +- tests/notification/submit_post_base.php | 6 + 22 files changed, 191 insertions(+), 149 deletions(-) rename phpBB/phpbb/messenger/method/{email.php => phpbb_email.php} (88%) rename phpBB/phpbb/messenger/method/{jabber.php => phpbb_jabber.php} (97%) diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index 83037d6427..ff7df470c4 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -20,23 +20,28 @@ services: - '@request' - '@user' - '@messenger.queue' + - '@path_helper' + - '@ext.manager' + - '@template.twig.extensions.collection' + - '@template.twig.lexer' + - '%core.template.cache_path%' messenger.method.email: - class: phpbb\messenger\method\email + class: phpbb\messenger\method\phpbb_email shared: false parent: messenger.method.base calls: - - [init, []] + - [reset, []] - [set_transport, []] tags: - { name: messenger.method } messenger.method.jabber: - class: phpbb\messenger\method\jabber + class: phpbb\messenger\method\phpbb_jabber shared: false parent: messenger.method.base calls: - - [init, []] + - [reset, []] tags: - { name: messenger.method } diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml index c9acdad025..9eb05b8a44 100644 --- a/phpBB/config/installer/container/services_install_finish.yml +++ b/phpBB/config/installer/container/services_install_finish.yml @@ -23,6 +23,7 @@ services: - '@installer.helper.container_factory' - '@installer.helper.config' - '@installer.helper.iohandler' + - '%core.root_path%' tags: - { name: install_finish, order: 3 } diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 734c83089b..92a54a37cb 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -459,7 +459,7 @@ class ucp_register if ($config['email_enable']) { $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $this->messenger->offsetGet('messenger.method.email'); + $email = $messenger->offsetGet('messenger.method.email'); $email->set_use_queue(false); $email->template($email_template, $data['lang']); $email->to($data['email'], $data['username']); diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php index 3a54cc409f..9813608034 100644 --- a/phpBB/phpbb/console/command/user/add.php +++ b/phpBB/phpbb/console/command/user/add.php @@ -325,6 +325,7 @@ class add extends command 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey", ]); $email->send(); + } /** * Get user activation key diff --git a/phpBB/phpbb/cron/task/core/queue.php b/phpBB/phpbb/cron/task/core/queue.php index 5e1f0d1be9..9395a538de 100644 --- a/phpBB/phpbb/cron/task/core/queue.php +++ b/phpBB/phpbb/cron/task/core/queue.php @@ -13,8 +13,7 @@ namespace phpbb\cron\task\core; -use \phpbb\config\config; -use \phpbb\messenger\queue; +use phpbb\config\config; /** * Queue cron task. Sends email and jabber messages queued by other scripts. @@ -24,7 +23,7 @@ class queue extends \phpbb\cron\task\base /** var config */ protected $config; - /** var queue */ + /** var \phpbb\messenger\queue */ protected $queue; /** var string */ @@ -35,9 +34,9 @@ class queue extends \phpbb\cron\task\base * * @param config $config The config * @param string $queue_cache_file The messenger file queue cache filename - * @param queue $queue The messenger file queue object + * @param \phpbb\messenger\queue $queue The messenger file queue object */ - public function __construct(config $config, queue $queue, $queue_cache_file) + public function __construct(config $config, \phpbb\messenger\queue $queue, $queue_cache_file) { $this->config = $config; $this->queue = $queue; diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index 4d3402a6f5..8c973311e5 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -42,6 +42,9 @@ class notify_user extends \phpbb\install\task_base /** @var log_interface */ protected $log; + /** @var string */ + protected $phpbb_root_path; + /** @var user */ protected $user; @@ -54,8 +57,9 @@ class notify_user extends \phpbb\install\task_base * @param container_factory $container * @param config $install_config * @param iohandler_interface $iohandler + * @param string $phpbb_root_path */ - public function __construct(container_factory $container, config $install_config, iohandler_interface $iohandler) + public function __construct(container_factory $container, config $install_config, iohandler_interface $iohandler, $phpbb_root_path) { $this->install_config = $install_config; $this->iohandler = $iohandler; @@ -64,6 +68,7 @@ class notify_user extends \phpbb\install\task_base $this->log = $container->get('log'); $this->user = $container->get('user'); $this->messenger = $container->get('messenger.method_collection'); + $this->phpbb_root_path = $phpbb_root_path; // We need to reload config for cases when it doesn't have all values /** @var \phpbb\cache\driver\driver_interface $cache */ diff --git a/phpBB/phpbb/message/admin_form.php b/phpBB/phpbb/message/admin_form.php index ae1c1d8614..2c3305dc03 100644 --- a/phpBB/phpbb/message/admin_form.php +++ b/phpBB/phpbb/message/admin_form.php @@ -85,7 +85,7 @@ class admin_form extends form /** * {inheritDoc} */ - public function submit(\messenger $messenger) + public function submit(\phpbb\di\service_collection $messenger) { if (!$this->subject) { diff --git a/phpBB/phpbb/message/topic_form.php b/phpBB/phpbb/message/topic_form.php index e8344417ef..facde9a462 100644 --- a/phpBB/phpbb/message/topic_form.php +++ b/phpBB/phpbb/message/topic_form.php @@ -108,7 +108,7 @@ class topic_form extends form /** * {inheritDoc} */ - public function submit(\messenger $messenger) + public function submit(\phpbb\di\service_collection $messenger) { if (!$this->recipient_address || !preg_match('/^' . get_preg_expression('email') . '$/i', $this->recipient_address)) { diff --git a/phpBB/phpbb/message/user_form.php b/phpBB/phpbb/message/user_form.php index 007e575407..46a012297d 100644 --- a/phpBB/phpbb/message/user_form.php +++ b/phpBB/phpbb/message/user_form.php @@ -96,7 +96,7 @@ class user_form extends form /** * {inheritDoc} */ - public function submit(\messenger $messenger) + public function submit(\phpbb\di\service_collection $messenger) { if (!$this->subject) { diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 28b9cde636..4dfbff4559 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -14,12 +14,16 @@ namespace phpbb\messenger\method; use phpbb\config\config; +use phpbb\di\service_collection; use phpbb\event\dispatcher; +use phpbb\extension\manager; use phpbb\language\language; use phpbb\log\log_interface; +use phpbb\path_helper; use phpbb\request\request; use phpbb\messenger\queue; use phpbb\template\template; +use phpbb\template\twig\lexer; use phpbb\user; /** @@ -36,6 +40,9 @@ abstract class base /** @var dispatcher */ protected $dispatcher; + /** @var manager */ + protected $ext_manager; + /** @var language */ protected $language; @@ -48,6 +55,9 @@ abstract class base /** @var queue */ protected $queue; + /** @var path_helper */ + protected $path_helper; + /** @var request */ protected $request; @@ -57,6 +67,15 @@ abstract class base /** @var template */ protected $template; + /** @var string */ + protected $template_cache_path; + + /** @var service_collection */ + protected $twig_extensions_collection; + + /** @var lexer */ + protected $twig_lexer; + /** @var bool */ protected $use_queue = true; @@ -73,8 +92,26 @@ abstract class base * @param request $request * @param user $user * @param queue $queue + * @param path_helper $path_helper + * @param manager $ext_manager + * @param service_collection $twig_extensions_collection + * @param lexer $twig_lexer + * @param string $template_cache_path */ - function __construct(config $config, dispatcher $dispatcher, language $language, log_interface $log, request $request, user $user, queue $queue) + function __construct( + config $config, + dispatcher $dispatcher, + language $language, + log_interface $log, + request $request, + user $user, + queue $queue, + path_helper $path_helper, + manager $ext_manager, + service_collection $twig_extensions_collection, + lexer $twig_lexer, + $template_cache_path + ) { $this->config = $config; $this->dispatcher = $dispatcher; @@ -83,6 +120,11 @@ abstract class base $this->request = $request; $this->user = $user; $this->queue = $queue; + $this->path_helper = $path_helper; + $this->ext_manager = $ext_manager; + $this->twig_extensions_collection = $twig_extensions_collection; + $this->twig_lexer = $twig_lexer; + $this->template_cache_path = $template_cache_path; $this->set_use_queue(); } @@ -91,19 +133,7 @@ abstract class base * Get messenger method id * @return mixed */ - abstract public function get_id() - { - return; - } - - /** - * get messenger method fie queue object name - * @return string - */ - abstract public function get_queue_object_name($user) - { - return ''; - } + abstract public function get_id(); /** * Sets the use of messenger queue flag @@ -120,13 +150,7 @@ abstract class base * * @return void */ - abstract public function reset() - { - $this->subject = $this->additional_headers = []; - $this->msg = ''; - $this->use_queue = true; - unset($this->template); - } + abstract public function reset(); /** * Set addresses for to/im as available @@ -134,9 +158,13 @@ abstract class base * @param array $user User row * @return void */ - abstract public function set_addresses($user) - { - } + abstract public function set_addresses($user); + + /** + * Get messenger method fie queue object name + * @return string + */ + abstract public function get_queue_object_name(); /** * Set up subject for mail @@ -152,8 +180,8 @@ abstract class base /** * Adds antiabuse headers * - * @param \phpbb\config\config $config Config object - * @param \phpbb\user $user User object + * @param config $config Config object + * @param user $user User object * @return void */ public function anti_abuse_headers($config, $user) @@ -185,9 +213,7 @@ abstract class base * Send out messages * @return bool */ - abstract protected function send() - { - } + abstract protected function send(); /** * Send messages from the queue @@ -195,9 +221,7 @@ abstract class base * @param array $queue_data Queue data array * @return void */ - abstract public function process_queue(&$queue_data) - { - } + abstract public function process_queue(&$queue_data); /** * Set email template to use @@ -336,8 +360,8 @@ abstract class base * Event to modify the template before parsing * * @event core.modify_notification_template - * @var string subject The message subject - * @var \phpbb\template\template template The (readonly) template object + * @var string subject The message subject + * @var template template The (readonly) template object * @since 3.2.4-RC1 * @changed 4.0.0-a1 Removed vars: method, break. */ @@ -395,11 +419,10 @@ abstract class base /** * Add error message to log * - * @param string $type Error type: EMAIL / etc * @param string $msg Error message text * @return void */ - public function error($type, $msg) + public function error($msg) { // Session doesn't exist, create it if (!isset($this->user->session_id) || $this->user->session_id === '') @@ -407,6 +430,7 @@ abstract class base $this->user->session_begin(); } + $type = strtoupper($this->get_queue_object_name()); $calling_page = html_entity_decode($this->request->server('PHP_SELF'), ENT_COMPAT); $message = '' . $type . '
' . htmlspecialchars($calling_page, ENT_COMPAT) . '

' . $msg . '
'; $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); @@ -431,32 +455,32 @@ abstract class base */ protected function setup_template() { - if ($this->template instanceof \phpbb\template\template) + if (isset($this->template) && $this->template instanceof template) { return; } $template_environment = new \phpbb\template\twig\environment( $this->config, - $this->phpbb_container->get('filesystem'), - $this->phpbb_container->get('path_helper'), - $this->phpbb_container->getParameter('core.template.cache_path'), - $this->phpbb_container->get('ext.manager'), + new \phpbb\filesystem\filesystem(), + $this->path_helper, + $this->template_cache_path, + $this->ext_manager, new \phpbb\template\twig\loader(), $this->dispatcher, [] ); - $template_environment->setLexer($this->phpbb_container->get('template.twig.lexer')); + $template_environment->setLexer($this->twig_lexer); $this->template = new \phpbb\template\twig\twig( - $this->phpbb_container->get('path_helper'), + $this->path_helper, $this->config, new \phpbb\template\context(), $template_environment, - $this->phpbb_container->getParameter('core.template.cache_path'), + $this->template_cache_path, $this->user, - $this->phpbb_container->get('template.twig.extensions.collection'), - $this->phpbb_container->get('ext.manager') + $this->twig_extensions_collection, + $this->ext_manager ); } diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/phpbb_email.php similarity index 88% rename from phpBB/phpbb/messenger/method/email.php rename to phpBB/phpbb/messenger/method/phpbb_email.php index 1968c6771e..768ba27b45 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/phpbb_email.php @@ -22,7 +22,7 @@ use Symfony\Component\Mime\Header\Headers; /** * Messenger class */ -class email extends base +class phpbb_email extends base { /** @var array */ private const PRIORITY_MAP = [ @@ -58,7 +58,7 @@ class email extends base /** @var string */ protected $from; - /** @var Symfony\Component\Mime\Header\Headers */ + /** @var Headers */ protected $headers; /** @@ -79,13 +79,11 @@ class email extends base /** @var string */ protected $replyto = ''; - /** @var Symfony\Component\Mailer\Transport */ + /** @var Transport */ protected $transport; /** - * Get messenger method id - * - * @return int + * {@inheritDoc} */ public function get_id() { @@ -93,10 +91,9 @@ class email extends base } /** - * get messenger method fie queue object name - * @return string + * {@inheritDoc} */ - abstract public function get_queue_object_name($user) + public function get_queue_object_name() { return 'email'; } @@ -111,9 +108,7 @@ class email extends base } /** - * Inits/resets the data to default - * - * @return void + * {@inheritDoc} */ public function reset() { @@ -122,7 +117,10 @@ class email extends base $this->msg = $this->replyto = $this->from = ''; $this->mail_priority = Email::PRIORITY_NORMAL; - parent::reset(); + $this->subject = $this->additional_headers = []; + $this->msg = ''; + $this->use_queue = true; + unset($this->template); } /** @@ -136,10 +134,7 @@ class email extends base } /** - * Set address as available - * - * @param array $user User row - * @return void + * {@inheritDoc} */ public function set_addresses($user) { @@ -251,8 +246,8 @@ class email extends base */ public function header($header_name, $header_value) { - $header_name = trim($header_name); - $header_value = trim($header_value); + $header_name = $header_name; + $header_value = $header_value; // addMailboxListHeader() requires value to be array if ($this->get_header_method($header_name) == 'addMailboxListHeader') @@ -295,18 +290,6 @@ class email extends base $this->email->priority($priority); } - /** - * Add error message to log - * - * @param string $msg Error message text - * @return void - */ - public function error($msg) - { - $type = 'EMAIL/' . ($this->config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()'; - parent::error($type, $msg); - } - /** * Detect proper Header class method to add header * @@ -448,15 +431,12 @@ class email extends base } /** - * Send messages from the queue - * - * @param array $queue_data Queue data array - * @return void + * {@inheritDoc} */ public function process_queue(&$queue_data) { $queue_object_name = $this->get_queue_object_name(); - $messages_count = count($queue_data[$queue_object_name]['data']; + $messages_count = count($queue_data[$queue_object_name]['data']); if (!$this->is_enabled() || !$messages_count) { @@ -480,8 +460,8 @@ class email extends base * Event to send message via external transport * * @event core.notification_message_process - * @var bool break Flag indicating if the function return after hook - * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var bool break Flag indicating if the function return after hook + * @var Email email The Symfony Email object * @since 3.2.4-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, subject, msg. */ @@ -515,7 +495,7 @@ class email extends base /** * Get mailer transport object * - * @return Symfony\Component\Mailer\Transport Symfony Mailer transport object + * @return Transport Symfony Mailer transport object */ public function get_transport() { @@ -527,7 +507,7 @@ class email extends base * * @return bool */ - protected function send() + public function send() { $this->prepare_message(); @@ -544,9 +524,9 @@ class email extends base * Event to send message via external transport * * @event core.notification_message_email - * @var string subject The message subject - * @var string msg The message text - * @var Symfony\Component\Mime\Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var Email email The Symfony Email object * @since 3.2.4-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, break */ @@ -587,10 +567,10 @@ class email extends base * Modify data before sending out emails with PHP's mail function * * @event core.phpbb_mail_before - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers + * @var Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var string headers The email headers * @since 3.3.6-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters. */ @@ -621,10 +601,10 @@ class email extends base * Execute code after sending out emails with PHP's mail function * * @event core.phpbb_mail_after - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers + * @var Email email The Symfony Email object + * @var string subject The message subject + * @var string msg The message text + * @var string headers The email headers * @since 3.3.6-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters, $result. */ diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/phpbb_jabber.php similarity index 97% rename from phpBB/phpbb/messenger/method/jabber.php rename to phpBB/phpbb/messenger/method/phpbb_jabber.php index 9661efc64a..874f28d06a 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/phpbb_jabber.php @@ -24,7 +24,7 @@ namespace phpbb\messenger\method; * Slightly modified by Acyd Burn (2006) * Refactored to a service (2023) */ -class jabber extends base +class phpbb_jabber extends base { /** @var string */ protected $connect_server; @@ -87,8 +87,8 @@ class jabber extends base * ->password($password) * ->ssl($use_ssl) * ->server($server) - * ->port($port) - * ->stream_options( + * ->port($port) + * ->stream_options( * 'verify_peer' => true, * 'verify_peer_name' => true, * 'allow_self_signed' => false, @@ -99,10 +99,10 @@ class jabber extends base public function init() { $this->username($this->config['jab_username']) - ->password($this->config['jab_password']) - ->ssl((bool) $this->config['jab_use_ssl']) - ->server($this->config['jab_host']) - ->port($this->config['jab_port']) + ->password($this->config['jab_password']) + ->ssl((bool) $this->config['jab_use_ssl']) + ->server($this->config['jab_host']) + ->port($this->config['jab_port']) ->stream_options['ssl'] = [ 'verify_peer' => $this->config['jab_verify_peer'], 'verify_peer_name' => $this->config['jab_verify_peer_name'], @@ -111,9 +111,7 @@ class jabber extends base } /** - * Get messenger method id - * - * @return int + * {@inheritDoc} */ public function get_id() { @@ -121,10 +119,9 @@ class jabber extends base } /** - * get messenger method fie queue object name - * @return string + * {@inheritDoc} */ - abstract public function get_queue_object_name($user) + public function get_queue_object_name() { return 'jabber'; } @@ -369,10 +366,7 @@ class jabber extends base } /** - * Set address as available - * - * @param array $user User row - * @return void + * {@inheritDoc} */ public function set_addresses($user) { @@ -403,16 +397,17 @@ class jabber extends base } /** - * Inits/resets the data to default - * - * @return void + * {@inheritDoc} */ public function reset() { $this->msg = ''; - $this->to = []; + $this->to = []; - parent::reset(); + $this->subject = $this->additional_headers = []; + $this->msg = ''; + $this->use_queue = true; + unset($this->template); } /** @@ -426,15 +421,12 @@ class jabber extends base } /** - * Send messages from the queue - * - * @param array $queue_data Queue data array - * @return void + * {@inheritDoc} */ public function process_queue(&$queue_data) { $queue_object_name = $this->get_queue_object_name(); - $messages_count = count($queue_data[$queue_object_name]['data']; + $messages_count = count($queue_data[$queue_object_name]['data']); if (!$this->is_enabled() || !$messages_count) { diff --git a/phpBB/phpbb/messenger/queue.php b/phpBB/phpbb/messenger/queue.php index eb2406e273..6245642dd7 100644 --- a/phpBB/phpbb/messenger/queue.php +++ b/phpBB/phpbb/messenger/queue.php @@ -121,7 +121,7 @@ class queue while ($messenger_collection_iterator->valid()) { $messenger_method = $messenger_collection_iterator->current(); - if (isset($this->queue_data[$messenger_method->get_queue_object_name()]) + if (isset($this->queue_data[$messenger_method->get_queue_object_name()])) { $messenger_method->process_queue($this->queue_data); } diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index dd181ac5a3..2c612367cc 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -27,13 +27,13 @@ use phpbb\di\service_collection; class email extends \phpbb\notification\method\messenger_base { - /** @var \phpbb\user */ + /** @var user */ protected $user; - /** @var \phpbb\config\config */ + /** @var config */ protected $config; - /** @var \phpbb\db\driver\driver_interface */ + /** @var driver_interface */ protected $db; /** @var string Notification emails table */ diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php index 5765152139..4a0e52fc62 100644 --- a/phpBB/phpbb/notification/method/jabber.php +++ b/phpBB/phpbb/notification/method/jabber.php @@ -26,10 +26,10 @@ use phpbb\di\service_collection; class jabber extends \phpbb\notification\method\messenger_base { - /** @var \phpbb\user */ + /** @var user */ protected $user; - /** @var \phpbb\config\config */ + /** @var config */ protected $config; /** @var service_collection */ diff --git a/tests/console/user/activate_test.php b/tests/console/user/activate_test.php index 8eaaa4e4fc..5df59a3711 100644 --- a/tests/console/user/activate_test.php +++ b/tests/console/user/activate_test.php @@ -41,7 +41,8 @@ class phpbb_console_user_activate_test extends phpbb_console_user_base $this->notifications, $this->user_loader, $this->phpbb_root_path, - $this->php_ext + $this->php_ext, + $this->messenger_method_collection )); $command = $application->find('user:activate'); diff --git a/tests/console/user/add_test.php b/tests/console/user/add_test.php index 67f1c84e72..3e2d2cfedf 100644 --- a/tests/console/user/add_test.php +++ b/tests/console/user/add_test.php @@ -32,7 +32,8 @@ class phpbb_console_user_add_test extends phpbb_console_user_base $this->language, $this->passwords_manager, $this->phpbb_root_path, - $this->php_ext + $this->php_ext, + $this->messenger_method_collection )); $command = $application->find('user:add'); diff --git a/tests/console/user/base.php b/tests/console/user/base.php index 008ac23d05..7d14b9a664 100644 --- a/tests/console/user/base.php +++ b/tests/console/user/base.php @@ -105,6 +105,11 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); + $this->messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $this->messenger_method_collection->add('messenger.method.email'); + $this->messenger_method_collection->add('messenger.method.jabber'); + $phpbb_container->set('messenger.method_collection', $this->messenger_method_collection); + parent::setUp(); } diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index ff0854be21..8e536fcd7a 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -95,7 +95,8 @@ class phpbb_email_parsing_test extends phpbb_test_case $phpbb_container->set('template.twig.extensions.collection', $twig_extensions_collection); $twig->addExtension($twig_extension); - $phpbb_container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); + $twig_lexer = new \phpbb\template\twig\lexer($twig); + $phpbb_container->set('template.twig.lexer', $twig_lexer); $phpbb_container->set('dispatcher', $dispatcher); $phpbb_container->set('language', $lang); $phpbb_container->set('request', $request); @@ -111,13 +112,23 @@ class phpbb_email_parsing_test extends phpbb_test_case $core_cache_dir = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; $phpbb_container->setParameter('core.cache_dir', $core_cache_dir); + $core_messenger_queue_file = $core_cache_dir . 'queue.' . $phpEx; $phpbb_container->setParameter('core.messenger_queue_file', $core_messenger_queue_file); + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $messenger_method_collection->add('messenger.method.email'); $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + $messenger_queue = new \phpbb\messenger\queue($config, $dispatcher, $messenger_method_collection, $core_messenger_queue_file); $phpbb_container->set('messenger.queue', $messenger_queue); - $this->email = new \phpbb\messenger\email($config, $dispatcher, $lang, $log, $request, $user, $messenger_queue); + + $this->email = new \phpbb\messenger\method\phpbb_email( + $config, $dispatcher, $lang, $log, $request, $user, $messenger_queue, + $phpbb_path_helper, $extension_manager, $twig_extensions_collection, $twig_lexer, + $cache_path + ); + $phpbb_container->set('messenger.method.email', $this->email); $reflection = new ReflectionObject($this->email); $this->reflection_template_property = $reflection->getProperty('template'); diff --git a/tests/notification/base.php b/tests/notification/base.php index 8e6f67c219..07fef3a1c5 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -146,6 +146,11 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case $phpbb_container->addCompilerPass(new phpbb\di\pass\markpublic_pass()); + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $messenger_method_collection->add('messenger.method.email'); + $messenger_method_collection->add('messenger.method.jabber'); + $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + $phpbb_container->compile(); $this->notifications->setDependencies($this->auth, $this->config); diff --git a/tests/notification/notification_method_email_test.php b/tests/notification/notification_method_email_test.php index 6b464b1c42..15811cc968 100644 --- a/tests/notification/notification_method_email_test.php +++ b/tests/notification/notification_method_email_test.php @@ -105,6 +105,11 @@ class notification_method_email_test extends phpbb_tests_notification_base ) ); + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $messenger_method_collection->add('messenger.method.email'); + $messenger_method_collection->add('messenger.method.jabber'); + $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + $this->notification_method_email = $this->getMockBuilder('\phpbb\notification\method\email') ->setConstructorArgs([ $phpbb_container->get('user_loader'), @@ -113,7 +118,8 @@ class notification_method_email_test extends phpbb_tests_notification_base $phpbb_container->get('dbal.conn'), $phpbb_root_path, $phpEx, - $phpbb_container->getParameter('tables.notification_emails') + $phpbb_container->getParameter('tables.notification_emails'), + $phpbb_container->get('messenger.method_collection') ]) ->setMethods(['notify_using_messenger']) ->getMock(); diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 124ac4d1b4..57b1242509 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -158,6 +158,12 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c $phpbb_container->setParameter('tables.notification_push', 'phpbb_notification_push'); $phpbb_container->setParameter('tables.push_subscriptions', 'phpbb_push_subscriptions'); $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); + + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $messenger_method_collection->add('messenger.method.email'); + $messenger_method_collection->add('messenger.method.jabber'); + $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + $phpbb_container->addCompilerPass(new phpbb\di\pass\markpublic_pass()); $phpbb_container->compile(); From 83294fed8464c2ff3edae9cbdfa7f707bec90393 Mon Sep 17 00:00:00 2001 From: rxu Date: Fri, 9 Jun 2023 11:56:32 +0700 Subject: [PATCH 12/29] [ticket/17135] Fix Psalm and other issues PHPBB3-17135 --- .../default/container/services_messenger.yml | 1 + phpBB/phpbb/message/message.php | 1 + phpBB/phpbb/messenger/method/base.php | 31 ++++++---- phpBB/phpbb/messenger/method/phpbb_email.php | 59 +++++++++++-------- phpBB/phpbb/messenger/method/phpbb_jabber.php | 52 ++++++++-------- phpBB/phpbb/messenger/queue.php | 3 +- .../notification/method/messenger_base.php | 1 + tests/email/email_parsing_test.php | 2 +- 8 files changed, 84 insertions(+), 66 deletions(-) diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index ff7df470c4..c28789f6c5 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -25,6 +25,7 @@ services: - '@template.twig.extensions.collection' - '@template.twig.lexer' - '%core.template.cache_path%' + - '%core.php_ext%' messenger.method.email: class: phpbb\messenger\method\phpbb_email diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 2a750c1f21..0fed6fb7a5 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -245,6 +245,7 @@ class message foreach ($this->recipients as $recipient) { + /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $messenger->getIterator(); while ($messenger_collection_iterator->valid()) { diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 4dfbff4559..8bf7b0cee3 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -22,7 +22,6 @@ use phpbb\log\log_interface; use phpbb\path_helper; use phpbb\request\request; use phpbb\messenger\queue; -use phpbb\template\template; use phpbb\template\twig\lexer; use phpbb\user; @@ -58,13 +57,16 @@ abstract class base /** @var path_helper */ protected $path_helper; + /** @var string */ + protected $root_path; + /** @var request */ protected $request; /** @var string */ protected $subject = ''; - /** @var template */ + /** @var \phpbb\template\template */ protected $template; /** @var string */ @@ -97,6 +99,7 @@ abstract class base * @param service_collection $twig_extensions_collection * @param lexer $twig_lexer * @param string $template_cache_path + * @param string $phpbb_root_path */ function __construct( config $config, @@ -110,7 +113,8 @@ abstract class base manager $ext_manager, service_collection $twig_extensions_collection, lexer $twig_lexer, - $template_cache_path + $template_cache_path, + $phpbb_root_path ) { $this->config = $config; @@ -125,6 +129,7 @@ abstract class base $this->twig_extensions_collection = $twig_extensions_collection; $this->twig_lexer = $twig_lexer; $this->template_cache_path = $template_cache_path; + $this->root_path = $phpbb_root_path; $this->set_use_queue(); } @@ -135,6 +140,12 @@ abstract class base */ abstract public function get_id(); + /** + * Check if the messenger method is enabled + * @return bool + */ + abstract public function is_enabled(); + /** * Sets the use of messenger queue flag * @@ -360,8 +371,8 @@ abstract class base * Event to modify the template before parsing * * @event core.modify_notification_template - * @var string subject The message subject - * @var template template The (readonly) template object + * @var string subject The message subject + * @var string template The (readonly) template object * @since 3.2.4-RC1 * @changed 4.0.0-a1 Removed vars: method, break. */ @@ -375,8 +386,8 @@ abstract class base * Event to modify notification message text after parsing * * @event core.modify_notification_message - * @var string message The message text - * @var string subject The message subject + * @var string message The message text + * @var string subject The message subject * @since 3.1.11-RC1 * @changed 4.0.0-a1 Removed vars: method, break. */ @@ -455,7 +466,7 @@ abstract class base */ protected function setup_template() { - if (isset($this->template) && $this->template instanceof template) + if (isset($this->template) && $this->template instanceof \phpbb\template\template) { return; } @@ -487,8 +498,8 @@ abstract class base /** * Set template paths to load * - * @param string $path_name Email template path name - * @param string $paths Email template paths + * @param string|array $path_name Email template path name + * @param string|array $paths Email template paths * @return void */ protected function set_template_paths($path_name, $paths) diff --git a/phpBB/phpbb/messenger/method/phpbb_email.php b/phpBB/phpbb/messenger/method/phpbb_email.php index 768ba27b45..98d7497e70 100644 --- a/phpBB/phpbb/messenger/method/phpbb_email.php +++ b/phpBB/phpbb/messenger/method/phpbb_email.php @@ -17,7 +17,13 @@ use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\DateHeader; use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\IdentificationHeader; +use Symfony\Component\Mime\Header\MailboxHeader; +use Symfony\Component\Mime\Header\MailboxListHeader; +use Symfony\Component\Mime\Header\PathHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; /** * Messenger class @@ -55,7 +61,10 @@ class phpbb_email extends base */ protected $dsn = ''; - /** @var string */ + /** @var Email */ + protected $email; + + /** @var Address */ protected $from; /** @var Headers */ @@ -73,13 +82,13 @@ class phpbb_email extends base */ protected $mail_priority = Email::PRIORITY_NORMAL; - /** @var queue */ + /** @var \phpbb\messenger\queue */ protected $queue; - /** @var string */ - protected $replyto = ''; + /** @var Address */ + protected $replyto; - /** @var Transport */ + /** @var \Symfony\Component\Mailer\Transport\AbstractTransport */ protected $transport; /** @@ -99,8 +108,7 @@ class phpbb_email extends base } /** - * Check if the messenger method is enabled - * @return void + * {@inheritDoc} */ public function is_enabled() { @@ -114,13 +122,12 @@ class phpbb_email extends base { $this->email = new Email(); $this->headers = $this->email->getHeaders(); - $this->msg = $this->replyto = $this->from = ''; + $this->subject = $this->msg = ''; $this->mail_priority = Email::PRIORITY_NORMAL; - $this->subject = $this->additional_headers = []; - $this->msg = ''; + $this->additional_headers = []; $this->use_queue = true; - unset($this->template); + unset($this->template, $this->replyto, $this->from); } /** @@ -180,7 +187,7 @@ class phpbb_email extends base } $cc = new Address($address, trim($realname)); - $this->email->getCc() ? $this->email->addCc($to) : $this->email->cc($to); + $this->email->getCc() ? $this->email->addCc($cc) : $this->email->cc($cc); } /** @@ -198,7 +205,7 @@ class phpbb_email extends base } $bcc = new Address($address, trim($realname)); - $this->email->getBcc() ? $this->email->addBcc($to) : $this->email->bcc($to); + $this->email->getBcc() ? $this->email->addBcc($bcc) : $this->email->bcc($bcc); } /** @@ -397,7 +404,7 @@ class phpbb_email extends base /** * Get Symfony Mailer transport DSN * - * @return void + * @return string */ public function get_dsn() { @@ -418,7 +425,7 @@ class phpbb_email extends base $this->transport = Transport::fromDsn($this->dsn); - if ($this->config['smtp_delivery'] && !in_array($this->dsn, ['null://null', 'sendmail://default'])) + if ($this->config['smtp_delivery'] && method_exists($this->transport, 'getStream')) { // Set ssl context options, see http://php.net/manual/en/context.ssl.php $options['ssl'] = [ @@ -460,8 +467,8 @@ class phpbb_email extends base * Event to send message via external transport * * @event core.notification_message_process - * @var bool break Flag indicating if the function return after hook - * @var Email email The Symfony Email object + * @var string break Flag indicating if the function return after hook + * @var string email The Symfony Email object * @since 3.2.4-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, subject, msg. */ @@ -477,25 +484,25 @@ class phpbb_email extends base { $mailer->send($email); } - catch (TransportExceptionInterface $e) + catch (\Symfony\Component\Mailer\Exception\TransportExceptionInterface $e) { - $this->error('EMAIL', $e->getDebug()); + $this->error($e->getDebug()); continue; } } } // No more data for this object? Unset it - if (!count($this->queue_data[$queue_object_name]['data'])) + if (!count($queue_data[$queue_object_name]['data'])) { - unset($this->queue_data[$queue_object_name]); + unset($queue_data[$queue_object_name]); } } /** * Get mailer transport object * - * @return Transport Symfony Mailer transport object + * @return \Symfony\Component\Mailer\Transport\TransportInterface Symfony Mailer transport object */ public function get_transport() { @@ -526,7 +533,7 @@ class phpbb_email extends base * @event core.notification_message_email * @var string subject The message subject * @var string msg The message text - * @var Email email The Symfony Email object + * @var string email The Symfony Email object * @since 3.2.4-RC1 * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, break */ @@ -567,7 +574,7 @@ class phpbb_email extends base * Modify data before sending out emails with PHP's mail function * * @event core.phpbb_mail_before - * @var Email email The Symfony Email object + * @var string email The Symfony Email object * @var string subject The message subject * @var string msg The message text * @var string headers The email headers @@ -591,7 +598,7 @@ class phpbb_email extends base { $mailer->send($this->email); } - catch (TransportExceptionInterface $e) + catch (\Symfony\Component\Mailer\Exception\TransportExceptionInterface $e) { $this->error($e->getDebug()); return false; @@ -601,7 +608,7 @@ class phpbb_email extends base * Execute code after sending out emails with PHP's mail function * * @event core.phpbb_mail_after - * @var Email email The Symfony Email object + * @var string email The Symfony Email object * @var string subject The message subject * @var string msg The message text * @var string headers The email headers diff --git a/phpBB/phpbb/messenger/method/phpbb_jabber.php b/phpBB/phpbb/messenger/method/phpbb_jabber.php index 874f28d06a..1bf212a25f 100644 --- a/phpBB/phpbb/messenger/method/phpbb_jabber.php +++ b/phpBB/phpbb/messenger/method/phpbb_jabber.php @@ -29,7 +29,7 @@ class phpbb_jabber extends base /** @var string */ protected $connect_server; - /** @var resource */ + /** @var resource|null */ protected $connection = null; /** @var bool */ @@ -47,7 +47,7 @@ class phpbb_jabber extends base /** @var string */ protected $password; - /** @var string */ + /** @var int */ protected $port; /** @var string */ @@ -127,8 +127,7 @@ class phpbb_jabber extends base } /** - * Check if the messenger method is enabled - * @return void + * {@inheritDoc} */ public function is_enabled() { @@ -187,10 +186,10 @@ class phpbb_jabber extends base * Set port to connect to server * use_ssl flag should be set first * - * @param string $port Port to connect to server + * @param int $port Port to connect to server * @return $this */ - public function port($port = '') + public function port($port = 5222) { $this->port = ($port) ? $port : 5222; @@ -334,6 +333,7 @@ class phpbb_jabber extends base } $this->session = []; + /** @psalm-suppress InvalidPropertyAssignmentValue */ return fclose($this->connection); } @@ -352,7 +352,7 @@ class phpbb_jabber extends base /** * Initiates login (using data from contructor, after calling connect()) * - * @return bool + * @return bool|void */ public function login() { @@ -401,11 +401,8 @@ class phpbb_jabber extends base */ public function reset() { - $this->msg = ''; - $this->to = []; - - $this->subject = $this->additional_headers = []; - $this->msg = ''; + $this->subject = $this->msg = ''; + $this->additional_headers = $this->to = []; $this->use_queue = true; unset($this->template); } @@ -438,7 +435,6 @@ class phpbb_jabber extends base $package_size = $queue_data[$queue_object_name]['package_size'] ?? 0; $num_items = (!$package_size || $messages_count < $package_size) ? $messages_count : $package_size; - $mailer = new Mailer($this->transport); for ($i = 0; $i < $num_items; $i++) { @@ -447,30 +443,30 @@ class phpbb_jabber extends base if (!$this->connect()) { - $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->get_log()); - return false; + $this->error($this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->get_log()); + return; } if (!$this->login()) { - $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->get_log()); - return false; + $this->error($this->user->lang['ERR_JAB_AUTH'] . '
' . $this->get_log()); + return; } foreach ($addresses as $address) { if ($this->send_message($address, $msg, $subject) === false) { - $this->error('JABBER', $this->get_log()); + $this->error($this->get_log()); continue; } } } // No more data for this object? Unset it - if (!count($this->queue_data[$queue_object_name]['data'])) + if (!count($queue_data[$queue_object_name]['data'])) { - unset($this->queue_data[$queue_object_name]); + unset($queue_data[$queue_object_name]); } $this->disconnect(); @@ -500,13 +496,13 @@ class phpbb_jabber extends base { if (!$this->connect()) { - $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->get_log()); + $this->error($this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->get_log()); return false; } if (!$this->login()) { - $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->get_log()); + $this->error($this->user->lang['ERR_JAB_AUTH'] . '
' . $this->get_log()); return false; } @@ -514,7 +510,7 @@ class phpbb_jabber extends base { if ($this->send_message($address, $this->msg, $this->subject) === false) { - $this->error('JABBER', $this->get_log()); + $this->error($this->get_log()); continue; } } @@ -542,7 +538,7 @@ class phpbb_jabber extends base * * @param string $xml * - * @return bool + * @return int|bool */ public function send_xml($xml) { @@ -655,7 +651,7 @@ class phpbb_jabber extends base /** * Initiates account registration (based on data used for contructor) * - * @return bool + * @return bool|void */ public function register() { @@ -676,7 +672,7 @@ class phpbb_jabber extends base * @param string $type dnd, away, chat, xa or nothing * @param bool $unavailable set this to true if you want to become unavailable * - * @return bool + * @return int|bool */ function send_presence($message = '', $type = '', $unavailable = false) { @@ -702,7 +698,7 @@ class phpbb_jabber extends base * * @param array $xml * - * @return bool + * @return bool|void */ function response($xml) { @@ -1021,7 +1017,7 @@ class phpbb_jabber extends base * @param string $subject Message subject * @param string $type Message type * - * @return string + * @return int|bool */ public function send_message($to, $text, $subject = '', $type = 'normal') { diff --git a/phpBB/phpbb/messenger/queue.php b/phpBB/phpbb/messenger/queue.php index 6245642dd7..2206834269 100644 --- a/phpBB/phpbb/messenger/queue.php +++ b/phpBB/phpbb/messenger/queue.php @@ -35,7 +35,7 @@ class queue /** @var dispatcher */ protected $dispatcher; - /** @var phpbb\filesystem\filesystem_interface */ + /** @var \phpbb\filesystem\filesystem_interface */ protected $filesystem; /** @var service_collection */ @@ -117,6 +117,7 @@ class queue include($this->cache_file); + /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger_method_collection->getIterator(); while ($messenger_collection_iterator->valid()) { diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 0d9b3c163b..38e48944f0 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -112,6 +112,7 @@ abstract class messenger_base extends \phpbb\notification\method\base continue; } + /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger->getIterator(); while ($messenger_collection_iterator->valid()) { diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index 8e536fcd7a..76770c789a 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -126,7 +126,7 @@ class phpbb_email_parsing_test extends phpbb_test_case $this->email = new \phpbb\messenger\method\phpbb_email( $config, $dispatcher, $lang, $log, $request, $user, $messenger_queue, $phpbb_path_helper, $extension_manager, $twig_extensions_collection, $twig_lexer, - $cache_path + $cache_path, $phpbb_root_path ); $phpbb_container->set('messenger.method.email', $this->email); From b57f1f7751cbbf22a65895c3318450c0ace1e72f Mon Sep 17 00:00:00 2001 From: rxu Date: Fri, 9 Jun 2023 21:35:25 +0700 Subject: [PATCH 13/29] [ticket/17135] Suppress psalm UndefinedFunction invalid annotations in tests PHPBB3-17135 --- phpBB/phpbb/template/twig/extension.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index 7fde9e2cac..fa9fca0705 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -164,6 +164,7 @@ class extension extends \Twig\Extension\AbstractExtension // We always include the last element (this was the past design) $end = ($end == -1 || $end === null) ? null : $end + 1; + /** @psalm-suppress UndefinedFunction */ return twig_slice($env, $item, $start, $end, $preserveKeys); } @@ -213,6 +214,7 @@ class extension extends \Twig\Extension\AbstractExtension { $args = func_get_args(); + /** @psalm-suppress UndefinedFunction */ return twig_escape_filter($this->environment, call_user_func_array([$this, 'lang'], $args), 'js'); } From 068987eba6347850c09141ca8b6bc040f035bc56 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 5 Nov 2023 23:12:13 +0700 Subject: [PATCH 14/29] [ticket/17135] Rebase to reflect upgrading to Symfony 6.3 PHPBB3-17135 --- phpBB/composer.json | 1 + phpBB/composer.lock | 224 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) diff --git a/phpBB/composer.json b/phpBB/composer.json index 1d43e78ad9..c77ab77819 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -51,6 +51,7 @@ "symfony/http-foundation": "^6.3", "symfony/http-kernel": "^6.3", "symfony/polyfill-mbstring": "^1.23", + "symfony/mailer": "^6.3", "symfony/mime": "^6.3", "symfony/process": "^6.3", "symfony/proxy-manager-bridge": "^6.3", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 47607417ab..ba6cff7047 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -1417,6 +1417,150 @@ ], "time": "2022-10-12T20:51:15+00:00" }, + { + "name": "doctrine/lexer", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "84a527db05647743d50373e0ec53a152f2cde568" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", + "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-15T16:57:16+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2023-10-06T06:47:41+00:00" + }, { "name": "friendsofphp/proxy-manager-lts", "version": "v1.0.18", @@ -4342,6 +4486,86 @@ ], "time": "2024-11-27T12:49:36+00:00" }, + { + "name": "symfony/mailer", + "version": "v6.3.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/d89611a7830d51b5e118bca38e390dea92f9ea06", + "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/mime": "^6.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/messenger": "^6.2", + "symfony/twig-bridge": "^6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.3.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-09-06T09:47:15+00:00" + }, { "name": "symfony/mime", "version": "v6.4.13", From 51fae82718c3f09945b16dda469086e0727f541e Mon Sep 17 00:00:00 2001 From: rxu Date: Wed, 5 Jun 2024 10:16:05 +0700 Subject: [PATCH 15/29] [ticket/17135] Fix rebasing issues PHPBB-17135 --- phpBB/config/default/container/services_messenger.yml | 1 + phpBB/phpbb/messenger/method/base.php | 8 ++++++++ tests/email/email_parsing_test.php | 2 +- tests/notification/notification_method_webpush_test.php | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index c28789f6c5..d6625430ef 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -13,6 +13,7 @@ services: class: phpbb\messenger\method\base shared: false arguments: + - '@assets.bag' - '@config' - '@dispatcher' - '@language' diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 8bf7b0cee3..809d2b2854 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -22,6 +22,7 @@ use phpbb\log\log_interface; use phpbb\path_helper; use phpbb\request\request; use phpbb\messenger\queue; +use phpbb\template\assets_bag; use phpbb\template\twig\lexer; use phpbb\user; @@ -33,6 +34,9 @@ abstract class base /** @var array */ protected $additional_headers = []; + /** @var assets_bag */ + protected $assets_bag; + /** @var config */ protected $config; @@ -87,6 +91,7 @@ abstract class base /** * Messenger base class constructor * + * @param assets_bag $assets_bag * @param config $config * @param dispatcher $dispatcher * @param language $language @@ -102,6 +107,7 @@ abstract class base * @param string $phpbb_root_path */ function __construct( + assets_bag $assets_bag, config $config, dispatcher $dispatcher, language $language, @@ -117,6 +123,7 @@ abstract class base $phpbb_root_path ) { + $this->assets_bag = $assets_bag; $this->config = $config; $this->dispatcher = $dispatcher; $this->language = $language; @@ -472,6 +479,7 @@ abstract class base } $template_environment = new \phpbb\template\twig\environment( + $this->assets_bag, $this->config, new \phpbb\filesystem\filesystem(), $this->path_helper, diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index 76770c789a..1a464e86aa 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -124,7 +124,7 @@ class phpbb_email_parsing_test extends phpbb_test_case $phpbb_container->set('messenger.queue', $messenger_queue); $this->email = new \phpbb\messenger\method\phpbb_email( - $config, $dispatcher, $lang, $log, $request, $user, $messenger_queue, + $assets_bag, $config, $dispatcher, $lang, $log, $request, $user, $messenger_queue, $phpbb_path_helper, $extension_manager, $twig_extensions_collection, $twig_lexer, $cache_path, $phpbb_root_path ); diff --git a/tests/notification/notification_method_webpush_test.php b/tests/notification/notification_method_webpush_test.php index 1116a62c6f..e52bf9a7ac 100644 --- a/tests/notification/notification_method_webpush_test.php +++ b/tests/notification/notification_method_webpush_test.php @@ -180,7 +180,7 @@ class notification_method_webpush_test extends phpbb_tests_notification_base $phpbb_root_path, $phpEx, $phpbb_container->getParameter('tables.notification_push'), - $phpbb_container->getParameter('tables.push_subscriptions') + $phpbb_container->getParameter('tables.push_subscriptions'), ); $phpbb_container->set('notification.method.webpush', $this->notification_method_webpush); From 499464e1d397dbcd494d88762210e400c9fc0fb4 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 23 Jun 2024 13:26:43 +0700 Subject: [PATCH 16/29] [ticket/17135] Fix code review issues PHPBB-17135 --- .../default/container/services_console.yml | 4 +- .../default/container/services_messenger.yml | 16 +- .../config/default/container/services_ucp.yml | 2 +- phpBB/includes/acp/acp_board.php | 15 +- phpBB/includes/acp/acp_email.php | 6 +- phpBB/includes/acp/acp_inactive.php | 21 +- phpBB/includes/acp/acp_users.php | 30 +- phpBB/includes/functions_messenger.php | 1366 ----------------- phpBB/includes/ucp/ucp_activate.php | 6 +- phpBB/includes/ucp/ucp_profile.php | 13 +- phpBB/includes/ucp/ucp_register.php | 17 +- phpBB/includes/ucp/ucp_resend.php | 21 +- phpBB/memberlist.php | 5 +- phpBB/phpbb/console/command/user/activate.php | 26 +- phpBB/phpbb/console/command/user/add.php | 26 +- .../data/v400/remove_smtp_auth_method.php | 7 + .../install_finish/task/notify_user.php | 14 +- phpBB/phpbb/message/message.php | 6 +- phpBB/phpbb/messenger/method/base.php | 96 +- .../method/{phpbb_email.php => email.php} | 214 +-- .../method/{phpbb_jabber.php => jabber.php} | 172 ++- phpBB/phpbb/messenger/queue.php | 19 +- .../notification/method/messenger_base.php | 4 +- phpBB/phpbb/ucp/controller/reset_password.php | 29 +- 24 files changed, 353 insertions(+), 1782 deletions(-) delete mode 100644 phpBB/includes/functions_messenger.php rename phpBB/phpbb/messenger/method/{phpbb_email.php => email.php} (72%) rename phpBB/phpbb/messenger/method/{phpbb_jabber.php => jabber.php} (88%) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 704c122d59..ba6658f889 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -327,11 +327,11 @@ services: - '@config' - '@language' - '@log' + - '@messenger.method_collection' - '@notification_manager' - '@user_loader' - '%core.root_path%' - '%core.php_ext%' - - '@messenger.method_collection' tags: - { name: console.command } @@ -342,10 +342,10 @@ services: - '@dbal.conn' - '@config' - '@language' + - '@messenger.method_collection' - '@passwords.manager' - '%core.root_path%' - '%core.php_ext%' - - '@messenger.method_collection' tags: - { name: console.command } diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index d6625430ef..c2ff6fa679 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -16,34 +16,34 @@ services: - '@assets.bag' - '@config' - '@dispatcher' + - '@ext.manager' - '@language' - '@log' - - '@request' - - '@user' - '@messenger.queue' - '@path_helper' - - '@ext.manager' + - '@request' - '@template.twig.extensions.collection' - '@template.twig.lexer' + - '@user' + - '%core.root_path%' - '%core.template.cache_path%' - - '%core.php_ext%' messenger.method.email: - class: phpbb\messenger\method\phpbb_email + class: phpbb\messenger\method\email shared: false parent: messenger.method.base calls: - - [reset, []] + - [init, []] - [set_transport, []] tags: - { name: messenger.method } messenger.method.jabber: - class: phpbb\messenger\method\phpbb_jabber + class: phpbb\messenger\method\jabber shared: false parent: messenger.method.base calls: - - [reset, []] + - [init, []] tags: - { name: messenger.method } diff --git a/phpBB/config/default/container/services_ucp.yml b/phpBB/config/default/container/services_ucp.yml index 6321e431db..bbe5d35f2b 100644 --- a/phpBB/config/default/container/services_ucp.yml +++ b/phpBB/config/default/container/services_ucp.yml @@ -19,6 +19,7 @@ services: - '@controller.helper' - '@language' - '@log' + - '@messenger.method.email' - '@passwords.manager' - '@request' - '@template' @@ -26,7 +27,6 @@ services: - '%tables.users%' - '%core.root_path%' - '%core.php_ext%' - - '@messenger.method_collection' phpbb.ucp.controller.webpush: class: phpbb\ucp\controller\webpush diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 3537b67737..b20d0d9753 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -720,17 +720,16 @@ class acp_board { if ($config['email_enable']) { - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('test'); - $email->set_addresses($user->data); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('test'); + $email_method->set_addresses($user->data); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($user->data['username'], ENT_COMPAT), 'MESSAGE' => html_entity_decode($request->variable('send_test_email_text', '', true), ENT_COMPAT), ]); - $email->send(); + $email_method->send(); trigger_error($user->lang('TEST_EMAIL_SENT') . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 23f7885e53..630b1bcb14 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -217,16 +217,15 @@ class acp_email ); extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); for ($i = 0, $size = count($email_list); $i < $size; $i++) { $used_lang = $email_list[$i][0]['lang']; $used_method = $email_list[$i][0]['method']; - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $used_method || $used_method == NOTIFY_BOTH) { $messenger_method->set_use_queue($use_queue); @@ -260,7 +259,6 @@ class acp_email $messenger_method->save_queue(); } } - $messenger_collection_iterator->next(); } } unset($email_list); diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 13427a8191..9d5d730348 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -114,19 +114,18 @@ class acp_inactive if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !empty($inactive_users)) { - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); foreach ($inactive_users as $row) { - $email->template('admin_welcome_activated', $row['user_lang']); - $email->set_addresses($row); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method->template('admin_welcome_activated', $row['user_lang']); + $email_method->set_addresses($row); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($row['username'], ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } } @@ -199,14 +198,13 @@ class acp_inactive { // Send the messages $usernames = $user_ids = array(); - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); do { - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) { $messenger_method->template('user_remind_inactive', $row['user_lang']); @@ -221,7 +219,6 @@ class acp_inactive $messenger_method->send(); $messenger_method->save_queue(); } - $messenger_collection_iterator->next(); } $usernames[] = $row['username']; diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 707e6b5541..d88d050387 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -398,18 +398,17 @@ class acp_users $db->sql_query($sql); // Start sending email - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template($email_template, $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template($email_template, $user_row['user_lang']); + $email_method->set_addresses($user_row); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey", ]); - $email->send(); + $email_method->send(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username'])); $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array( @@ -454,16 +453,15 @@ class acp_users $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('admin_welcome_activated', $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('admin_welcome_activated', $user_row['user_lang']); + $email_method->set_addresses($user_row); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } } diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php deleted file mode 100644 index 323ab31999..0000000000 --- a/phpBB/includes/functions_messenger.php +++ /dev/null @@ -1,1366 +0,0 @@ - - * @license GNU General Public License, version 2 (GPL-2.0) - * - * For full copyright and license information, please see - * the docs/CREDITS.txt file. - * - */ - -use Symfony\Component\Mailer\Transport; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; -use Symfony\Component\Mime\Header\Headers; - -/** - * @ignore - */ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** - * Messenger class - */ -class messenger -{ - /** @var array */ - private const PRIORITY_MAP = [ - Email::PRIORITY_HIGHEST => 'Highest', - Email::PRIORITY_HIGH => 'High', - Email::PRIORITY_NORMAL => 'Normal', - Email::PRIORITY_LOW => 'Low', - Email::PRIORITY_LOWEST => 'Lowest', - ]; - - /** @var array */ - private const HEADER_CLASS_MAP = [ - 'date' => DateHeader::class, - 'from' => MailboxListHeader::class, - 'sender' => MailboxHeader::class, - 'reply-to' => MailboxListHeader::class, - 'to' => MailboxListHeader::class, - 'cc' => MailboxListHeader::class, - 'bcc' => MailboxListHeader::class, - 'message-id' => IdentificationHeader::class, - 'in-reply-to' => UnstructuredHeader::class, - 'references' => UnstructuredHeader::class, - 'return-path' => PathHeader::class, - ]; - - /** @var array */ - protected $additional_headers = []; - - /** @var array */ - protected $addresses = []; - - /** @var \phpbb\config\config */ - protected $config; - - /** @var \phpbb\event\dispatcher */ - protected $dispatcher; - - /** - * @var string - * - * Symfony Mailer transport DSN - */ - protected $dsn = ''; - - /** @var string */ - protected $from; - - /** @var Symfony\Component\Mime\Header\Headers */ - protected $headers; - - /** @var \phpbb\language\language */ - protected $language; - - /** @var \phpbb\log\log_interface */ - protected $log; - - /** - * @var int - * - * Possible values are: - * Email::PRIORITY_HIGHEST - * Email::PRIORITY_HIGH - * Email::PRIORITY_NORMAL - * Email::PRIORITY_LOW - * Email::PRIORITY_LOWEST - */ - protected $mail_priority = Email::PRIORITY_NORMAL; - - /** @var string */ - protected $msg; - - /** @var string */ - protected $php_ext; - - /** @var queue */ - protected $queue; - - /** @var string */ - protected $replyto; - - /** @var \phpbb\request\request */ - protected $request; - - /** @var string */ - protected $root_path; - - /** @var string */ - protected $subject; - - /** @var \phpbb\template\template */ - protected $template; - - /** @var Symfony\Component\Mailer\Transport */ - protected $transport; - - /** @var bool */ - protected $use_queue = true; - - /** @var phpbb\user */ - protected $user; - - /** - * Messenger class constructor - * - * @param bool $use_queue Flag to switch the use of the messenger file queue - */ - function __construct($use_queue = true) - { - global $phpbb_container; - - $this->phpbb_container = $phpbb_container; - $this->config = $this->phpbb_container->get('config'); - $this->dispatcher = $this->phpbb_container->get('dispatcher'); - $this->language = $this->phpbb_container->get('language'); - $this->log = $this->phpbb_container->get('log'); - $this->request = $this->phpbb_container->get('request'); - $this->user = $this->phpbb_container->get('user'); - $this->email = new Email(); - $this->headers = $this->email->getHeaders(); - $this->use_queue = (!$this->config['email_package_size']) ? false : $use_queue; - $this->subject = ''; - $this->php_ext = $this->phpbb_container->getParameter('core.php_ext'); - $this->root_path = $this->phpbb_container->getParameter('core.root_path'); - $this->set_transport(); - } - - /** - * Resets all the data (address, template file, etc etc) to default - * - * @return void - */ - public function reset() - { - $this->addresses = []; - $this->msg = $this->replyto = $this->from = ''; - $this->mail_priority = Email::PRIORITY_NORMAL; - } - - /** - * Set addresses for to/im as available - * - * @param array $user User row - * @return void - */ - public function set_addresses($user) - { - if (isset($user['user_email']) && $user['user_email']) - { - $this->to($user['user_email'], $user['username'] ?: ''); - } - - if (isset($user['user_jabber']) && $user['user_jabber']) - { - $this->im($user['user_jabber'], $user['username'] ?: ''); - } - } - - /** - * Sets email address to send to - * - * @param string $address Email "To" recipient address - * @param string $realname Email "To" recipient name - * @return void - */ - public function to($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - // If empty sendmail_path on windows, PHP changes the to line - $windows_empty_sendmail_path = !$this->config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\'; - - $to = new Address(trim($address), $windows_empty_sendmail_path ? '' : trim($realname)); - $this->email->getTo() ? $this->email->addTo($to) : $this->email->to($to); - } - - /** - * Sets cc address to send to - * - * @param string $address Email carbon copy recipient address - * @param string $realname Email carbon copy recipient name - * @return void - */ - public function cc($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $cc = new Address(trim($address), trim($realname)); - $this->email->getCc() ? $this->email->addCc($to) : $this->email->cc($to); - } - - /** - * Sets bcc address to send to - * - * @param string $address Email black carbon copy recipient address - * @param string $realname Email black carbon copy recipient name - * @return void - */ - public function bcc($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $bcc = new Address(trim($address), trim($realname)); - $this->email->getBcc() ? $this->email->addBcc($to) : $this->email->bcc($to); - } - - /** - * Sets a im contact to send to - * - * @param string $address Jabber recipient address - * @param string $realname Jabber recipient name - * @return void - */ - public function im($address, $realname = '') - { - // IM-Addresses could be empty - if (!trim($address)) - { - return; - } - - $pos = isset($this->addresses['im']) ? count($this->addresses['im']) : 0; - $this->addresses['im'][$pos]['uid'] = trim($address); - $this->addresses['im'][$pos]['name'] = trim($realname); - } - - /** - * Set the reply to address - * - * @param string $address Email "Reply to" address - * @return void - */ - public function replyto($address) - { - $this->replyto = new Address(trim($address)); - $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); - } - - /** - * Set the from address - * - * @param string $address Email "from" address - * @return void - */ - public function from($address) - { - $this->from = new Address(trim($address)); - $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); - } - - /** - * Set up subject for mail - * - * @param string $subject Email subject - * @return void - */ - public function subject($subject = '') - { - $this->subject = $subject; - $this->email->subject(trim($this->subject)); - } - - /** - * Set up extra mail headers - * - * @param string $header_name Email header name - * @param string $header_value Email header body - * @return void - */ - public function header($header_name, $header_value) - { - $header_name = trim($header_name); - $header_value = trim($header_value); - - // addMailboxListHeader() requires value to be array - if ($this->get_header_method($header_name) == 'addMailboxListHeader') - { - $header_value = [$header_value]; - } - $this->headers->addHeader($header_name, $header_value); - } - - /** - * Adds X-AntiAbuse headers - * - * @param \phpbb\config\config $config Config object - * @param \phpbb\user $user User object - * @return void - */ - public function anti_abuse_headers($config, $user) - { - $this->header('X-AntiAbuse', 'Board servername - ' . $config['server_name']); - $this->header('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); - $this->header('X-AntiAbuse', 'Username - ' . $user->data['username']); - $this->header('X-AntiAbuse', 'User IP - ' . $user->ip); - } - - /** - * Set the email priority - * - * Possible values are: - * Email::PRIORITY_HIGHEST = 1 - * Email::PRIORITY_HIGH = 2 - * Email::PRIORITY_NORMAL = 3 - * Email::PRIORITY_LOW = 4 - * Email::PRIORITY_LOWEST = 5 - * - * @param int $priority Email priority level - * @return void - */ - public function set_mail_priority($priority = Email::PRIORITY_NORMAL) - { - $this->email->priority($priority); - } - - /** - * Set email template to use - * - * @param string $template_file Email template file name - * @param string $template_lang Email template language - * @param string $template_path Email template path - * @param string $template_dir_prefix Email template directory prefix - * - * @return bool - */ - public function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') - { - $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; - - $this->setup_template(); - - if (!trim($template_file)) - { - trigger_error('No template file for emailing set.', E_USER_ERROR); - } - - if (!trim($template_lang)) - { - // fall back to board default language if the user's language is - // missing $template_file. If this does not exist either, - // $this->template->set_filenames will do a trigger_error - $template_lang = basename($this->config['default_lang']); - } - - $ext_template_paths = [ - [ - 'name' => $template_lang . '_email', - 'ext_path' => 'language/' . $template_lang . '/email' . $template_dir_prefix, - ], - ]; - - if ($template_path) - { - $template_paths = [ - $template_path . $template_dir_prefix, - ]; - } - else - { - $template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; - $template_path .= $template_lang . '/email'; - - $template_paths = [ - $template_path . $template_dir_prefix, - ]; - - $board_language = basename($this->config['default_lang']); - - // we can only specify default language fallback when the path is not a custom one for which we - // do not know the default language alternative - if ($template_lang !== $board_language) - { - $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; - $fallback_template_path .= $board_language . '/email'; - - $template_paths[] = $fallback_template_path . $template_dir_prefix; - - $ext_template_paths[] = [ - 'name' => $board_language . '_email', - 'ext_path' => 'language/' . $board_language . '/email' . $template_dir_prefix, - ]; - } - // If everything fails just fall back to en template - if ($template_lang !== 'en' && $board_language !== 'en') - { - $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; - $fallback_template_path .= 'en/email'; - - $template_paths[] = $fallback_template_path . $template_dir_prefix; - - $ext_template_paths[] = [ - 'name' => 'en_email', - 'ext_path' => 'language/en/email' . $template_dir_prefix, - ]; - } - } - - $this->set_template_paths($ext_template_paths, $template_paths); - - $this->template->set_filenames([ - 'body' => $template_file . '.txt', - ]); - - return true; - } - - /** - * Assign variables to email template - * - * @param array $vars Array of VAR => VALUE to assign to email template - * @return void - */ - public function assign_vars($vars) - { - $this->setup_template(); - - $this->template->assign_vars($vars); - } - - /** - * Assign block of variables to email template - * - * @param string $blockname Template block name - * @param array $vars Array of VAR => VALUE to assign to email template block - * @return void - */ - public function assign_block_vars($blockname, $vars) - { - $this->setup_template(); - - $this->template->assign_block_vars($blockname, $vars); - } - - /** - * Prepare message before sending out to the recipients - * - * @return void - */ - public function prepare_message() - { - // We add some standard variables we always use, no need to specify them always - $this->assign_vars([ - 'U_BOARD' => generate_board_url(), - 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . html_entity_decode($this->config['board_email_sig'], ENT_COMPAT)), - 'SITENAME' => html_entity_decode($this->config['sitename'], ENT_COMPAT), - ]); - - $email = $this->email; - $subject = $this->email->getSubject(); - $template = $this->template; - /** - * Event to modify the template before parsing - * - * @event core.modify_notification_template - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var \phpbb\template\template template The (readonly) template object - * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. - */ - $vars = ['email', 'subject', 'template']; - extract($this->dispatcher->trigger_event('core.modify_notification_template', compact($vars))); - - // Parse message through template - $message = trim($this->template->assign_display('body')); - - /** - * Event to modify notification message text after parsing - * - * @event core.modify_notification_message - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string message The message text - * @var string subject The message subject - * @since 3.1.11-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. - */ - $vars = ['email', 'message', 'subject']; - extract($this->dispatcher->trigger_event('core.modify_notification_message', compact($vars))); - - $this->email = $email; - $this->subject = $subject; - $this->msg = $message; - unset($email, $subject, $message, $template); - - // Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding - $this->msg = str_replace("\r\n", "\n", $this->msg); - - // We now try and pull a subject from the email body ... if it exists, - // do this here because the subject may contain a variable - $drop_header = ''; - $match = []; - if (preg_match('#^(Subject):(.*?)$#m', $this->msg, $match)) - { - $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); - $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); - } - else - { - $this->subject = (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); - } - - if (preg_match('#^(List-Unsubscribe):(.*?)$#m', $this->msg, $match)) - { - $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); - $this->additional_headers[$match[1]] = trim($match[2]); - } - - if ($drop_header) - { - $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); - } - } - - /** - * Send the mail out to the recipients - * - * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH - * @param bool $break Flag indicating if the function only formats the subject - * and the message without sending it - * @return bool - */ - public function send($method = NOTIFY_EMAIL, $break = false) - { - $this->prepare_message(); - if ($break) - { - return true; - } - - switch ($method) - { - case NOTIFY_EMAIL: - $result = $this->msg_email(); - break; - - case NOTIFY_IM: - $result = $this->msg_jabber(); - break; - - case NOTIFY_BOTH: - $result = $this->msg_email(); - $this->msg_jabber(); - break; - } - - $this->reset(); - return $result; - } - - /** - * Add error message to log - * - * @param string $type Error type: EMAIL / etc - * @param string $msg Error message text - * @return void - */ - public function error($type, $msg) - { - // Session doesn't exist, create it - if (!isset($this->user->session_id) || $this->user->session_id === '') - { - $this->user->session_begin(); - } - - $calling_page = html_entity_decode($this->request->server('REQUEST_URI'), ENT_COMPAT); - - switch ($type) - { - case 'EMAIL': - $message = 'EMAIL/' . (($this->config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()') . ''; - break; - - default: - $message = "$type"; - break; - } - - $message .= '
' . htmlspecialchars($calling_page, ENT_COMPAT) . '

' . $msg . '
'; - $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); - } - - /** - * Save message data to the messemger file queue - * @return void - */ - public function save_queue() - { - if ($this->config['email_package_size'] && $this->use_queue && !empty($this->queue)) - { - $this->queue->save(); - return; - } - } - - /** - * Detect proper Header class method to add header - * - * @param string $name Email header name - * @return string - */ - protected function get_header_method(string $name) - { - $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); - $method = 'add'.ucfirst(array_pop($parts)); - if ('addUnstructuredHeader' === $method) - { - $method = 'addTextHeader'; - } - else if ('addIdentificationHeader' === $method) - { - $method = 'addIdHeader'; - } - - return $method; - } - - /** - * Set email headers - * - * @return bool - */ - protected function build_header() - { - $headers = []; - - $board_contact = $this->config['board_contact']; - if (empty($this->email->getReplyTo())) - { - $this->replyto($board_contact); - $headers['Reply-To'] = $this->replyto; - } - - if (empty($this->email->getFrom())) - { - $this->from($board_contact); - $headers['From'] = $this->from; - } - - $headers['Return-Path'] = new Address($this->config['board_email']); - $headers['Sender'] = new Address($this->config['board_email']); - $headers['X-Priority'] = sprintf('%d (%s)', $this->mail_priority, self::PRIORITY_MAP[$this->mail_priority]); - $headers['X-MSMail-Priority'] = self::PRIORITY_MAP[$this->mail_priority]; - $headers['X-Mailer'] = 'phpBB3'; - $headers['X-MimeOLE'] = 'phpBB3'; - $headers['X-phpBB-Origin'] = 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()); - - /** - * Event to modify email header entries - * - * @event core.modify_email_headers - * @var array headers Array containing email header entries - * @since 3.1.11-RC1 - */ - $vars = ['headers']; - extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - - foreach ($headers as $header => $value) - { - $this->header($header, $value); - } - - return true; - } - - /** - * Generates valid DSN for Symfony Mailer transport - * - * @param string $dsn Symfony Mailer transport DSN - * @return void - */ - public function set_dsn($dsn = '') - { - if (!empty($dsn)) - { - $this->dsn = $dsn; - } - else if ($this->config['smtp_delivery']) - { - if (empty($this->config['smtp_host'])) - { - $this->dsn = 'null://null'; - } - else - { - $user = urlencode($this->config['smtp_username']); - $password = urlencode($this->config['smtp_password']); - $smtp_host = urlencode($this->config['smtp_host']); - $smtp_port = $this->config['smtp_port']; - - $this->dsn = "smtp://$user:$password@$smtp_host:$smtp_port"; - } - } - else - { - $this->dsn = 'sendmail://default'; - } - } - - /** - * Get Symfony Mailer transport DSN - * - * @return void - */ - public function get_dsn() - { - return $this->dsn; - } - - /** - * Generates a valid transport to send email - * - * @return void - */ - public function set_transport() - { - if (empty($this->dsn)) - { - $this->set_dsn(); - } - - $this->transport = Transport::fromDsn($this->dsn); - - if ($this->config['smtp_delivery'] && !in_array($this->dsn, ['null://null', 'sendmail://default'])) - { - // Set ssl context options, see http://php.net/manual/en/context.ssl.php - $options['ssl'] = [ - 'verify_peer' => (bool) $this->config['smtp_verify_peer'], - 'verify_peer_name' => (bool) $this->config['smtp_verify_peer_name'], - 'allow_self_signed' => (bool) $this->config['smtp_allow_self_signed'], - ]; - $this->transport->getStream()->setStreamOptions($options); - } - } - - /** - * Get mailer transport object - * - * @return Symfony\Component\Mailer\Transport Symfony Mailer transport object - */ - public function get_transport() - { - return $this->transport; - } - - /** - * Send out emails - * - * @return bool - */ - protected function msg_email() - { - if (empty($this->config['email_enable'])) - { - return false; - } - - // Addresses to send to? - if (empty($this->email->getTo())) - { - // Send was successful. ;) - return true; - } - - $use_queue = false; - if ($this->config['email_package_size'] && $this->use_queue) - { - if (empty($this->queue)) - { - $this->queue = new queue(); - $this->queue->init('email', $this->config['email_package_size']); - } - $use_queue = true; - } - - $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); - $board_contact = $this->config['board_contact']; - - $this->email->subject($this->subject); - $this->email->text($this->msg); - - $break = false; - $subject = $this->subject; - $msg = $this->msg; - $email = $this->email; - /** - * Event to send message via external transport - * - * @event core.notification_message_email - * @var bool break Flag indicating if the function return after hook - * @var string subject The message subject - * @var string msg The message text - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses - */ - $vars = [ - 'break', - 'subject', - 'msg', - 'email', - ]; - extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); - - $this->addresses = $addresses; - $this->subject = $subject; - $this->msg = $msg; - unset($addresses, $subject, $msg); - - if ($break) - { - return true; - } - - if (empty($this->email->getReplyto())) - { - $this->replyto($board_contact); - } - - if (empty($this->email->getFrom())) - { - $this->from($board_contact); - } - - // Build header - foreach ($this->additional_headers as $header_name => $header_value) - { - $this->header($header_name, $header_value); - } - $this->build_header(); - - // Send message ... - if (!$use_queue) - { - $mailer = new Mailer($this->transport); - - $subject = $this->subject; - $msg = $this->msg; - $headers = $this->headers; - $email = $this->email; - /** - * Modify data before sending out emails with PHP's mail function - * - * @event core.phpbb_mail_before - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers - * @since 3.3.6-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters. - */ - $vars = [ - 'email', - 'subject', - 'msg', - 'headers', - ]; - extract($this->dispatcher->trigger_event('core.phpbb_mail_before', compact($vars))); - - $this->subject = $subject; - $this->msg = $msg; - $this->headers = $headers; - $this->email = $email; - - try - { - $mailer->send($this->email); - } - catch (TransportExceptionInterface $e) - { - $this->error('EMAIL', $e->getDebug()); - return false; - } - - /** - * Execute code after sending out emails with PHP's mail function - * - * @event core.phpbb_mail_after - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers - * @since 3.3.6-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters, $result. - */ - $vars = [ - 'email', - 'subject', - 'msg', - 'headers', - ]; - extract($this->dispatcher->trigger_event('core.phpbb_mail_after', compact($vars))); - } - else - { - $this->queue->put('email', [ - 'email' => $this->email, - ]); - } - - return true; - } - - /** - * Send jabber message out - * - * @return bool - */ - protected function msg_jabber() - { - if (empty($this->config['jab_enable']) || empty($this->config['jab_host']) || empty($this->config['jab_username']) || empty($this->config['jab_password'])) - { - return false; - } - - if (empty($this->addresses['im'])) - { - // Send was successful. ;) - return true; - } - - $use_queue = false; - if ($this->config['jab_package_size'] && $this->use_queue) - { - if (empty($this->queue)) - { - $this->queue = new queue(); - $this->queue->init('jabber', $this->config['jab_package_size']); - } - $use_queue = true; - } - - $addresses = []; - foreach ($this->addresses['im'] as $type => $uid_ary) - { - $addresses[] = $uid_ary['uid']; - } - $addresses = array_unique($addresses); - - if (!$use_queue) - { - include_once($this->root_path . 'includes/functions_jabber.' . $this->php_ext); - $this->jabber = new jabber($this->config['jab_host'], $this->config['jab_port'], $this->config['jab_username'], html_entity_decode($this->config['jab_password'], ENT_COMPAT), $this->config['jab_use_ssl'], $this->config['jab_verify_peer'], $this->config['jab_verify_peer_name'], $this->config['jab_allow_self_signed']); - - if (!$this->jabber->connect()) - { - $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->jabber->get_log()); - return false; - } - - if (!$this->jabber->login()) - { - $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->jabber->get_log()); - return false; - } - - foreach ($addresses as $address) - { - $this->jabber->send_message($address, $this->msg, $this->subject); - } - - $this->jabber->disconnect(); - } - else - { - $this->queue->put('jabber', [ - 'addresses' => $addresses, - 'subject' => $this->subject, - 'msg' => $this->msg - ]); - } - unset($addresses); - return true; - } - - /** - * Setup template engine - * - * @return void - */ - protected function setup_template() - { - if ($this->template instanceof \phpbb\template\template) - { - return; - } - - $template_environment = new \phpbb\template\twig\environment( - $phpbb_container->get('assets.bag'), - $phpbb_container->get('config'), - $phpbb_container->get('filesystem'), - $phpbb_container->get('path_helper'), - $phpbb_container->getParameter('core.template.cache_path'), - $phpbb_container->get('ext.manager'), - new \phpbb\template\twig\loader(), - $this->dispatcher, - [] - ); - $template_environment->setLexer($this->phpbb_container->get('template.twig.lexer')); - - $this->template = new \phpbb\template\twig\twig( - $this->phpbb_container->get('path_helper'), - $this->config, - new \phpbb\template\context(), - $template_environment, - $this->phpbb_container->getParameter('core.template.cache_path'), - $this->user, - $this->phpbb_container->get('template.twig.extensions.collection'), - $this->phpbb_container->get('ext.manager') - ); - } - - /** - * Set template paths to load - * - * @param string $path_name Email template path name - * @param string $paths Email template paths - * @return void - */ - protected function set_template_paths($path_name, $paths) - { - $this->setup_template(); - - $this->template->set_custom_style($path_name, $paths); - } -} - -/** - * Handling messenger file queue - */ -class queue -{ - /** @var array */ - protected $data = []; - - /** @var array */ - protected $queue_data = []; - - /** @var string */ - protected $cache_file = ''; - - /** - * @var \phpbb\filesystem\filesystem_interface - */ - protected $filesystem; - - /** - * Messenger file queue class constructor - */ - function __construct() - { - global $phpbb_container; - - $this->phpbb_container = $phpbb_container; - $this->php_ext = $this->phpbb_container->getParameter('core.php_ext'); - $this->root_path = $this->phpbb_container->getParameter('core.root_path'); - $this->cache_file = $this->phpbb_container->getParameter('core.cache_dir') . "queue.{$this->php_ext}"; - $this->filesystem = $this->phpbb_container->get('filesystem'); - $this->config = $this->phpbb_container->get('config'); - $this->dispatcher = $this->phpbb_container->get('dispatcher'); - } - - /** - * Init a queue object - * - * @param string $object Queue object type: email/jabber/etc - * @param int $package_size Size of the messenger package to send - * @return void - */ - public function init($object, $package_size) - { - $this->data[$object] = []; - $this->data[$object]['package_size'] = $package_size; - $this->data[$object]['data'] = []; - } - - /** - * Put message into the messenger file queue - * - * @param string $object Queue object type: email/jabber/etc - * @param mixed $message_data Message data to send - * @return void - */ - public function put($object, $message_data) - { - $this->data[$object]['data'][] = $message_data; - } - - /** - * Process the messemger file queue (using lock file) - * - * @return void - */ - public function process() - { - $lock = new \phpbb\lock\flock($this->cache_file); - $lock->acquire(); - - // avoid races, check file existence once - $have_cache_file = file_exists($this->cache_file); - if (!$have_cache_file || $this->config['last_queue_run'] > time() - $this->config['queue_interval']) - { - if (!$have_cache_file) - { - $this->config->set('last_queue_run', time(), false); - } - - $lock->release(); - return; - } - - $this->config->set('last_queue_run', time(), false); - - include($this->cache_file); - - foreach ($this->queue_data as $object => $data_ary) - { - @set_time_limit(0); - - if (!isset($data_ary['package_size'])) - { - $data_ary['package_size'] = 0; - } - - $package_size = $data_ary['package_size']; - $num_items = (!$package_size || count($data_ary['data']) < $package_size) ? count($data_ary['data']) : $package_size; - - switch ($object) - { - case 'email': - // Delete the email queued objects if mailing is disabled - if (!$this->config['email_enable']) - { - unset($this->queue_data['email']); - continue 2; - } - break; - - case 'jabber': - if (!$this->config['jab_enable']) - { - unset($this->queue_data['jabber']); - continue 2; - } - - include_once($this->root_path . 'includes/functions_jabber.' . $this->php_ext); - $this->jabber = new jabber($this->config['jab_host'], $this->config['jab_port'], $this->config['jab_username'], html_entity_decode($this->config['jab_password'], ENT_COMPAT), $this->config['jab_use_ssl'], $this->config['jab_verify_peer'], $this->config['jab_verify_peer_name'], $this->config['jab_allow_self_signed']); - - if (!$this->jabber->connect()) - { - $messenger = new messenger(); - $messenger->error('JABBER', $this->user->lang['ERR_JAB_CONNECT']); - continue 2; - } - - if (!$this->jabber->login()) - { - $messenger = new messenger(); - $messenger->error('JABBER', $this->user->lang['ERR_JAB_AUTH']); - continue 2; - } - - break; - - default: - $lock->release(); - return; - } - - for ($i = 0; $i < $num_items; $i++) - { - // Make variables available... - extract(array_shift($this->queue_data[$object]['data'])); - - switch ($object) - { - case 'email': - $break = false; - /** - * Event to send message via external transport - * - * @event core.notification_message_process - * @var bool break Flag indicating if the function return after hook - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, subject, msg. - */ - $vars = [ - 'break', - 'email', - ]; - extract($this->dispatcher->trigger_event('core.notification_message_process', compact($vars))); - - if (!$break) - { - $messenger = new messenger(); - $mailer = new Mailer($messenger->get_transport()); - - try - { - $mailer->send($email); - } - catch (TransportExceptionInterface $e) - { - $messenger->error('EMAIL', $e->getDebug()); - continue 2; - } - } - break; - - case 'jabber': - foreach ($addresses as $address) - { - if ($this->jabber->send_message($address, $msg, $subject) === false) - { - $messenger = new messenger(); - $messenger->error('JABBER', $this->jabber->get_log()); - continue 3; - } - } - break; - } - } - - // No more data for this object? Unset it - if (!count($this->queue_data[$object]['data'])) - { - unset($this->queue_data[$object]); - } - - // Post-object processing - switch ($object) - { - case 'jabber': - // Hang about a couple of secs to ensure the messages are - // handled, then disconnect - $this->jabber->disconnect(); - break; - } - } - - if (!count($this->queue_data)) - { - @unlink($this->cache_file); - } - else - { - if ($fp = @fopen($this->cache_file, 'wb')) - { - fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); - fclose($fp); - - if (function_exists('opcache_invalidate')) - { - @opcache_invalidate($this->cache_file); - } - - try - { - $this->filesystem->phpbb_chmod($this->cache_file, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - } - } - - $lock->release(); - } - - /** - * Save message data to the messenger file queue - * - * @return void - */ - public function save() - { - if (!count($this->data)) - { - return; - } - - $lock = new \phpbb\lock\flock($this->cache_file); - $lock->acquire(); - - if (file_exists($this->cache_file)) - { - include($this->cache_file); - - foreach ($this->queue_data as $object => $data_ary) - { - if (isset($this->data[$object]) && count($this->data[$object])) - { - $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']); - } - else - { - $this->data[$object]['data'] = $data_ary['data']; - } - } - } - - if ($fp = @fopen($this->cache_file, 'w')) - { - fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); - fclose($fp); - - if (function_exists('opcache_invalidate')) - { - @opcache_invalidate($this->cache_file); - } - - try - { - $this->filesystem->phpbb_chmod($this->cache_file, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - - $this->data = []; - } - - $lock->release(); - } -} diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 2db88c6934..b8867fcdb3 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -131,11 +131,10 @@ class ucp_activate $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) { $messenger_method->set_use_queue(false); @@ -148,7 +147,6 @@ class ucp_activate $messenger_method->send(); } - $messenger_collection_iterator->next(); } $message = 'ACCOUNT_ACTIVE_ADMIN'; diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index c142a2af73..0b34598e14 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -174,17 +174,16 @@ class ucp_profile $user_actkey = gen_rand_string(mt_rand(6, 10)); - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); + $email_method = $phpbb_container->get('messenger.method.email'); $template_file = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? 'user_activate_inactive' : 'user_activate'; - $email->template($template_file, $user->data['user_lang']); - $email->to($data['email'], $data['username']); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method->template($template_file, $user->data['user_lang']); + $email_method->to($data['email'], $data['username']); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($data['username'], ENT_COMPAT), 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey", ]); - $email->send(); + $email_method->send(); if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 92a54a37cb..6736ea25f0 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -458,13 +458,12 @@ class ucp_register if ($config['email_enable']) { - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template($email_template, $data['lang']); - $email->to($data['email'], $data['username']); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template($email_template, $data['lang']); + $email_method->to($data['email'], $data['username']); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($data['new_password'], ENT_COMPAT), @@ -473,7 +472,7 @@ class ucp_register if ($coppa) { - $email->assign_vars([ + $email_method->assign_vars([ 'FAX_INFO' => $config['coppa_fax'], 'MAIL_INFO' => $config['coppa_mail'], 'EMAIL_ADDRESS' => $data['email'], @@ -506,7 +505,7 @@ class ucp_register ); extract($phpbb_dispatcher->trigger_event('core.ucp_register_welcome_email_before', compact($vars))); - $email->send(); + $email_method->send(); } if ($config['require_activation'] == USER_ACTIVATION_ADMIN) diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 122aeeca37..ab108bc15d 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -94,18 +94,17 @@ class ucp_resend $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false; - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa) { - $email->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); - $email->set_addresses($user_row); + $email_method->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); + $email_method->set_addresses($user_row); - $email->anti_abuse_headers($config, $user); + $email_method->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", @@ -113,14 +112,14 @@ class ucp_resend if ($coppa) { - $email->assign_vars([ + $email_method->assign_vars([ 'FAX_INFO' => $config['coppa_fax'], 'MAIL_INFO' => $config['coppa_mail'], 'EMAIL_ADDRESS' => $user_row['user_email'], ]); } - $email->send(); + $email_method->send(); } if ($config['require_activation'] == USER_ACTIVATION_ADMIN) @@ -136,9 +135,8 @@ class ucp_resend $messenger_collection_iterator = $messenger->getIterator(); while ($row = $db->sql_fetchrow($result)) { - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); $messenger_method->set_use_queue(false); if ($messenger_method->get_id() == $row['user_notify_type'] || $row['user_notify_type'] == NOTIFY_BOTH) { @@ -156,7 +154,6 @@ class ucp_resend // Save the queue in the messenger method class (has to be called or these messages could be lost) $messenger_method->save_queue(); } - $messenger_collection_iterator->next(); } } $db->sql_freeresult($result); diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index f61fd21502..be4b467a5f 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -436,8 +436,7 @@ switch ($mode) trigger_error('EMPTY_MESSAGE_IM'); } - $messenger = $phpbb_container->get('messenger.method_collection'); - $jabber = $messenger->offsetGet('messenger.method.jabber'); + $jabber = $phpbb_container->get('messenger.method.jabber'); $jabber->set_use_queue(false); $jabber->template('profile_send_im', $row['user_lang']); @@ -901,7 +900,7 @@ switch ($mode) case 'contactadmin': case 'email': - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $user_id = $request->variable('u', 0); $topic_id = $request->variable('t', 0); diff --git a/phpBB/phpbb/console/command/user/activate.php b/phpBB/phpbb/console/command/user/activate.php index 9157206e0a..23f1b390e3 100644 --- a/phpBB/phpbb/console/command/user/activate.php +++ b/phpBB/phpbb/console/command/user/activate.php @@ -39,6 +39,9 @@ class activate extends command /** @var log_interface */ protected $log; + /** @var service_collection */ + protected $messenger; + /** @var manager */ protected $notifications; @@ -59,9 +62,6 @@ class activate extends command */ protected $php_ext; - /** @var service_collection */ - protected $messenger; - /** * Construct method * @@ -69,22 +69,22 @@ class activate extends command * @param config $config * @param language $language * @param log_interface $log + * @param service_collection $messenger * @param manager $notifications * @param user_loader $user_loader * @param string $phpbb_root_path * @param string $php_ext - * @param service_collection $messenger */ - public function __construct(user $user, config $config, language $language, log_interface $log, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext, service_collection $messenger) + public function __construct(user $user, config $config, language $language, log_interface $log, service_collection $messenger, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext) { $this->config = $config; $this->language = $language; $this->log = $log; + $this->messenger = $messenger; $this->notifications = $notifications; $this->user_loader = $user_loader; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $this->messenger = $messenger; $this->language->add_lang('acp/users'); parent::__construct($user); @@ -200,15 +200,15 @@ class activate extends command if ($input->getOption('send-email')) { - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('admin_welcome_activated', $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $email_method = $this->messenger->offsetGet('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('admin_welcome_activated', $user_row['user_lang']); + $email_method->set_addresses($user_row); + $email_method->anti_abuse_headers($this->config, $this->user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } } } diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php index 9813608034..1ad3770c76 100644 --- a/phpBB/phpbb/console/command/user/add.php +++ b/phpBB/phpbb/console/command/user/add.php @@ -43,6 +43,9 @@ class add extends command /** @var language */ protected $language; + /** @var service_collection */ + protected $messenger; + /** @var manager */ protected $password_manager; @@ -60,9 +63,6 @@ class add extends command */ protected $php_ext; - /** @var service_collection */ - protected $messenger; - /** * Construct method * @@ -70,20 +70,20 @@ class add extends command * @param driver_interface $db * @param config $config * @param language $language + * @param service_collection $messenger * @param manager $password_manager * @param string $phpbb_root_path * @param string $php_ext - * @param service_collection $messenger */ - public function __construct(user $user, driver_interface $db, config $config, language $language, manager $password_manager, $phpbb_root_path, $php_ext, service_collection $messenger) + public function __construct(user $user, driver_interface $db, config $config, language $language, service_collection $messenger, manager $password_manager, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; $this->language = $language; + $this->messenger = $messenger; $this->password_manager = $password_manager; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $this->messenger = $messenger; $this->language->add_lang('ucp'); parent::__construct($user); @@ -313,18 +313,18 @@ class add extends command $user_actkey = $this->get_activation_key($user_id); - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template($email_template, $this->user->lang_name); - $email->to($this->data['email'], $this->data['username']); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $email_method = $this->messenger->offsetGet('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template($email_template, $this->user->lang_name); + $email_method->to($this->data['email'], $this->data['username']); + $email_method->anti_abuse_headers($this->config, $this->user); + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode($this->language->lang('WELCOME_SUBJECT', $this->config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($this->data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->data['new_password'], ENT_COMPAT), 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey", ]); - $email->send(); + $email_method->send(); } /** diff --git a/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php b/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php index eed17067b7..830307c1e8 100644 --- a/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php +++ b/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php @@ -35,4 +35,11 @@ class remove_smtp_auth_method extends migration ['config.remove', ['smtp_auth_method']], ]; } + + public function revert_data() + { + return [ + ['config.add', ['smtp_auth_method', 'PLAIN']], + ]; + } } diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index 8c973311e5..3f2c439bdd 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -97,16 +97,16 @@ class notify_user extends \phpbb\install\task_base if ($this->config['email_enable']) { - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('installed', $this->install_config->get('user_language', 'en')); - $email->to($this->config['board_email'], $this->install_config->get('admin_name')); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $email_method = $this->messenger->offsetGet('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('installed', $this->install_config->get('user_language', 'en')); + $email_method->to($this->config['board_email'], $this->install_config->get('admin_name')); + $email_method->anti_abuse_headers($this->config, $this->user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($this->install_config->get('admin_name'), ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->install_config->get('admin_passwd'), ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } // Login admin diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 0fed6fb7a5..34295d1a02 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -247,15 +247,14 @@ class message { /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $messenger->getIterator(); - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); $messenger_method->set_use_queue(false); if ($messenger_method->get_id() == $recipient['notify_type'] || $recipient['notify_type'] == NOTIFY_BOTH) { $messenger_method->template($this->template, $recipient['lang']); $messenger_method->set_addresses($recipient); - $messenger_method->replyto($this->sender_address); + $messenger_method->reply_to($this->sender_address); $messenger_method->header('X-AntiAbuse', 'Board servername - ' . $this->server_name); $messenger_method->header('X-AntiAbuse', 'User IP - ' . $this->sender_ip); @@ -284,7 +283,6 @@ class message $messenger_method->send(); } - $messenger_collection_iterator->next(); } } } diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 809d2b2854..1d6e23ad29 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -61,12 +61,12 @@ abstract class base /** @var path_helper */ protected $path_helper; - /** @var string */ - protected $root_path; - /** @var request */ protected $request; + /** @var string */ + protected $root_path; + /** @var string */ protected $subject = ''; @@ -94,95 +94,98 @@ abstract class base * @param assets_bag $assets_bag * @param config $config * @param dispatcher $dispatcher + * @param manager $ext_manager * @param language $language * @param log_interface $log - * @param request $request - * @param user $user * @param queue $queue * @param path_helper $path_helper - * @param manager $ext_manager + * @param request $request * @param service_collection $twig_extensions_collection * @param lexer $twig_lexer - * @param string $template_cache_path + * @param user $user * @param string $phpbb_root_path + * @param string $template_cache_path */ - function __construct( + public function __construct( assets_bag $assets_bag, config $config, dispatcher $dispatcher, + manager $ext_manager, language $language, log_interface $log, - request $request, - user $user, queue $queue, path_helper $path_helper, - manager $ext_manager, + request $request, service_collection $twig_extensions_collection, lexer $twig_lexer, - $template_cache_path, - $phpbb_root_path + user $user, + $phpbb_root_path, + $template_cache_path ) { $this->assets_bag = $assets_bag; $this->config = $config; $this->dispatcher = $dispatcher; + $this->ext_manager = $ext_manager; $this->language = $language; $this->log = $log; - $this->request = $request; - $this->user = $user; $this->queue = $queue; $this->path_helper = $path_helper; - $this->ext_manager = $ext_manager; + $this->request = $request; $this->twig_extensions_collection = $twig_extensions_collection; $this->twig_lexer = $twig_lexer; - $this->template_cache_path = $template_cache_path; + $this->user = $user; $this->root_path = $phpbb_root_path; + $this->template_cache_path = $template_cache_path; $this->set_use_queue(); } /** * Get messenger method id - * @return mixed + * + * @return int */ - abstract public function get_id(); + abstract public function get_id(): int; /** * Check if the messenger method is enabled + * * @return bool */ - abstract public function is_enabled(); + abstract public function is_enabled(): bool; /** * Sets the use of messenger queue flag * * @return void */ - public function set_use_queue($use_queue = true) + public function set_use_queue(bool $use_queue = true): void { $this->use_queue = $use_queue; } /** - * Resets all the data (address, template file, etc etc) to default + * Initializes all the data (address, template file, etc) or resets to default * * @return void */ - abstract public function reset(); + abstract public function init(): void; /** * Set addresses for to/im as available * - * @param array $user User row + * @param array $user_row User row * @return void */ - abstract public function set_addresses($user); + abstract public function set_addresses(array $user_row): void; /** * Get messenger method fie queue object name + * * @return string */ - abstract public function get_queue_object_name(); + abstract public function get_queue_object_name(): string; /** * Set up subject for mail @@ -190,7 +193,7 @@ abstract class base * @param string $subject Email subject * @return void */ - public function subject($subject = '') + public function subject(string $subject = ''): void { $this->subject = $subject; } @@ -202,9 +205,7 @@ abstract class base * @param user $user User object * @return void */ - public function anti_abuse_headers($config, $user) - { - } + abstract public function anti_abuse_headers(config $config, user $user): void; /** * Set up extra headers @@ -213,9 +214,7 @@ abstract class base * @param string $header_value Email header body * @return void */ - public function header($header_name, $header_value) - { - } + abstract public function header(string $header_name, string $header_value): void; /** * Set the reply to address @@ -223,15 +222,14 @@ abstract class base * @param string $address Email "Reply to" address * @return void */ - public function replyto($address) - { - } + abstract public function reply_to($address): void; /** * Send out messages + * * @return bool */ - abstract protected function send(); + abstract protected function send(): bool; /** * Send messages from the queue @@ -239,7 +237,7 @@ abstract class base * @param array $queue_data Queue data array * @return void */ - abstract public function process_queue(&$queue_data); + abstract public function process_queue(array &$queue_data): void; /** * Set email template to use @@ -251,17 +249,12 @@ abstract class base * * @return bool */ - public function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') + public function template(string $template_file, string $template_lang = '', string $template_path = '', string $template_dir_prefix = ''): bool { $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; $this->setup_template(); - if (!trim($template_file)) - { - trigger_error('No template file for emailing set.', E_USER_ERROR); - } - if (!trim($template_lang)) { // fall back to board default language if the user's language is @@ -338,7 +331,7 @@ abstract class base * @param array $vars Array of VAR => VALUE to assign to email template * @return void */ - public function assign_vars($vars) + public function assign_vars(array $vars): void { $this->setup_template(); $this->template->assign_vars($vars); @@ -351,7 +344,7 @@ abstract class base * @param array $vars Array of VAR => VALUE to assign to email template block * @return void */ - public function assign_block_vars($blockname, $vars) + public function assign_block_vars(string $blockname, array $vars): void { $this->setup_template(); @@ -363,7 +356,7 @@ abstract class base * * @return void */ - public function prepare_message() + public function prepare_message(): void { // We add some standard variables we always use, no need to specify them always $this->assign_vars([ @@ -440,7 +433,7 @@ abstract class base * @param string $msg Error message text * @return void */ - public function error($msg) + public function error(string $msg): void { // Session doesn't exist, create it if (!isset($this->user->session_id) || $this->user->session_id === '') @@ -458,7 +451,7 @@ abstract class base * Save message data to the messenger file queue * @return void */ - public function save_queue() + public function save_queue(): void { if ($this->use_queue && !empty($this->queue)) { @@ -469,9 +462,10 @@ abstract class base /** * Setup template engine + * * @return void */ - protected function setup_template() + protected function setup_template(): void { if (isset($this->template) && $this->template instanceof \phpbb\template\template) { @@ -510,7 +504,7 @@ abstract class base * @param string|array $paths Email template paths * @return void */ - protected function set_template_paths($path_name, $paths) + protected function set_template_paths(string|array $path_name, string|array $paths): void { $this->setup_template(); $this->template->set_custom_style($path_name, $paths); diff --git a/phpBB/phpbb/messenger/method/phpbb_email.php b/phpBB/phpbb/messenger/method/email.php similarity index 72% rename from phpBB/phpbb/messenger/method/phpbb_email.php rename to phpBB/phpbb/messenger/method/email.php index 98d7497e70..d3642b263d 100644 --- a/phpBB/phpbb/messenger/method/phpbb_email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -16,7 +16,7 @@ namespace phpbb\messenger\method; use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Email as symfony_email; use Symfony\Component\Mime\Header\DateHeader; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\Header\IdentificationHeader; @@ -28,7 +28,7 @@ use Symfony\Component\Mime\Header\UnstructuredHeader; /** * Messenger class */ -class phpbb_email extends base +class email extends base { /** @var array */ private const PRIORITY_MAP = [ @@ -39,21 +39,6 @@ class phpbb_email extends base Email::PRIORITY_LOWEST => 'Lowest', ]; - /** @var array */ - private const HEADER_CLASS_MAP = [ - 'date' => DateHeader::class, - 'from' => MailboxListHeader::class, - 'sender' => MailboxHeader::class, - 'reply-to' => MailboxListHeader::class, - 'to' => MailboxListHeader::class, - 'cc' => MailboxListHeader::class, - 'bcc' => MailboxListHeader::class, - 'message-id' => IdentificationHeader::class, - 'in-reply-to' => UnstructuredHeader::class, - 'references' => UnstructuredHeader::class, - 'return-path' => PathHeader::class, - ]; - /** * @var string * @@ -86,7 +71,7 @@ class phpbb_email extends base protected $queue; /** @var Address */ - protected $replyto; + protected $reply_to; /** @var \Symfony\Component\Mailer\Transport\AbstractTransport */ protected $transport; @@ -94,7 +79,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function get_id() + public function get_id(): int { return NOTIFY_EMAIL; } @@ -102,7 +87,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function get_queue_object_name() + public function get_queue_object_name(): string { return 'email'; } @@ -110,7 +95,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function is_enabled() + public function is_enabled(): bool { return (bool) $this->config['email_enable']; } @@ -118,16 +103,16 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function reset() + public function init(): void { - $this->email = new Email(); + $this->email = new symfony_email(); $this->headers = $this->email->getHeaders(); $this->subject = $this->msg = ''; $this->mail_priority = Email::PRIORITY_NORMAL; $this->additional_headers = []; $this->use_queue = true; - unset($this->template, $this->replyto, $this->from); + unset($this->template, $this->reply_to, $this->from); } /** @@ -135,7 +120,7 @@ class phpbb_email extends base * * @return void */ - public function set_use_queue($use_queue = true) + public function set_use_queue(bool $use_queue = true): void { $this->use_queue = !$this->config['email_package_size'] ? false : $use_queue; } @@ -143,11 +128,11 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function set_addresses($user) + public function set_addresses(array $user_row): void { - if (isset($user['user_email']) && $user['user_email']) + if (isset($user_row['user_email']) && $user_row['user_email']) { - $this->to($user['user_email'], $user['username'] ?: ''); + $this->to($user_row['user_email'], $user_row['username'] ?: ''); } } @@ -158,7 +143,7 @@ class phpbb_email extends base * @param string $realname Email "To" recipient name * @return void */ - public function to($address, $realname = '') + public function to(string $address, string $realname = ''): void { if (!$address = trim($address)) { @@ -179,7 +164,7 @@ class phpbb_email extends base * @param string $realname Email carbon copy recipient name * @return void */ - public function cc($address, $realname = '') + public function cc(string $address, string $realname = ''): void { if (!$address = trim($address)) { @@ -197,7 +182,7 @@ class phpbb_email extends base * @param string $realname Email black carbon copy recipient name * @return void */ - public function bcc($address, $realname = '') + public function bcc(string $address, string $realname = ''): void { if (!$address = trim($address)) { @@ -212,23 +197,35 @@ class phpbb_email extends base * Set the reply to address * * @param string $address Email "Reply to" address + * @param string $realname Email "Reply to" recipient name * @return void */ - public function replyto($address) + public function reply_to(string $address, string $realname = ''): void { - $this->replyto = new Address(trim($address)); - $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); + if (!$address = trim($address)) + { + return; + } + + $this->reply_to = new Address($address, trim($realname)); + $this->email->getReplyTo() ? $this->email->addReplyTo($this->reply_to) : $this->email->replyTo($this->reply_to); } /** * Set the from address * * @param string $address Email "from" address + * @param string $realname Email "from" recipient name * @return void */ - public function from($address) + public function from(string $address, string $realname = ''): void { - $this->from = new Address(trim($address)); + if (!$address = trim($address)) + { + return; + } + + $this->from = new Address($address, trim($realname)); $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); } @@ -238,32 +235,12 @@ class phpbb_email extends base * @param string $subject Email subject * @return void */ - public function subject($subject = '') + public function subject(string $subject = ''): void { parent::subject(trim($subject)); $this->email->subject($this->subject); } - /** - * Set up extra mail headers - * - * @param string $header_name Email header name - * @param string $header_value Email header body - * @return void - */ - public function header($header_name, $header_value) - { - $header_name = $header_name; - $header_value = $header_value; - - // addMailboxListHeader() requires value to be array - if ($this->get_header_method($header_name) == 'addMailboxListHeader') - { - $header_value = [$header_value]; - } - $this->headers->addHeader($header_name, $header_value); - } - /** * Adds X-AntiAbuse headers * @@ -271,12 +248,12 @@ class phpbb_email extends base * @param \phpbb\user $user User object * @return void */ - public function anti_abuse_headers($config, $user) + public function anti_abuse_headers(\phpbb\config\config $config, \phpbb\user $user): void { - $this->header('X-AntiAbuse', 'Board servername - ' . $config['server_name']); - $this->header('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); - $this->header('X-AntiAbuse', 'Username - ' . $user->data['username']); - $this->header('X-AntiAbuse', 'User IP - ' . $user->ip); + $this->headers->addHeader('X-AntiAbuse', 'Board servername - ' . $config['server_name']); + $this->headers->addHeader('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); + $this->headers->addHeader('X-AntiAbuse', 'Username - ' . $user->data['username']); + $this->headers->addHeader('X-AntiAbuse', 'User IP - ' . $user->ip); } /** @@ -292,79 +269,63 @@ class phpbb_email extends base * @param int $priority Email priority level * @return void */ - public function set_mail_priority($priority = Email::PRIORITY_NORMAL) + public function set_mail_priority(int $priority = Email::PRIORITY_NORMAL): void { $this->email->priority($priority); } - /** - * Detect proper Header class method to add header - * - * @param string $name Email header name - * @return string - */ - protected function get_header_method(string $name) - { - $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); - $method = 'add'.ucfirst(array_pop($parts)); - if ('addUnstructuredHeader' === $method) - { - $method = 'addTextHeader'; - } - else if ('addIdentificationHeader' === $method) - { - $method = 'addIdHeader'; - } - - return $method; - } - /** * Set email headers * - * @return bool + * @return void */ - protected function build_header() + protected function build_headers(): void { - $headers = []; - $board_contact = $this->config['board_contact']; + $board_contact = trim($this->config['board_contact']); + $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); + if (empty($this->email->getReplyTo())) { - $this->replyto($board_contact); - $headers['Reply-To'] = $this->replyto; + $this->reply_to($board_contact, $contact_name); } if (empty($this->email->getFrom())) { - $this->from($board_contact); - $headers['From'] = $this->from; + $this->from($board_contact, $contact_name); } - $headers['Return-Path'] = new Address($this->config['board_email']); - $headers['Sender'] = new Address($this->config['board_email']); - $headers['X-Priority'] = sprintf('%d (%s)', $this->mail_priority, self::PRIORITY_MAP[$this->mail_priority]); - $headers['X-MSMail-Priority'] = self::PRIORITY_MAP[$this->mail_priority]; - $headers['X-Mailer'] = 'phpBB3'; - $headers['X-MimeOLE'] = 'phpBB3'; - $headers['X-phpBB-Origin'] = 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()); + $this->email->priority($this->mail_priority); + $phpbb_headers = [ + 'Return-Path' => new Address($this->config['board_email']), + 'Sender' => new Address($this->config['board_email']), + 'X-MSMail-Priority' => self::PRIORITY_MAP[$this->mail_priority], + 'X-Mailer' => 'phpBB3', + 'X-MimeOLE' => 'phpBB3', + 'X-phpBB-Origin' => 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()), + ]; + + // Add additional headers + $phpbb_headers = array_merge($phpbb_headers, $this->additional_headers); + + foreach ($phpbb_headers as $header => $value) + { + $this->headers->addHeader($header, $value); + } + + $headers = $this->headers; /** * Event to modify email header entries * * @event core.modify_email_headers - * @var array headers Array containing email header entries + * @var Headers headers Array containing email header entries * @since 3.1.11-RC1 + * @changed 4.0.0-a1 'headers' var type changed from array to \Symfony\Component\Mime\Header\Headers */ $vars = ['headers']; extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - - foreach ($headers as $header => $value) - { - $this->header($header, $value); - } - - return true; + $this->headers = $headers; } /** @@ -373,7 +334,7 @@ class phpbb_email extends base * @param string $dsn Symfony Mailer transport DSN * @return void */ - public function set_dsn($dsn = '') + public function set_dsn(string $dsn = ''): void { if (!empty($dsn)) { @@ -406,7 +367,7 @@ class phpbb_email extends base * * @return string */ - public function get_dsn() + public function get_dsn(): string { return $this->dsn; } @@ -416,7 +377,7 @@ class phpbb_email extends base * * @return void */ - public function set_transport() + public function set_transport(): void { if (empty($this->dsn)) { @@ -440,7 +401,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function process_queue(&$queue_data) + public function process_queue(array &$queue_data): void { $queue_object_name = $this->get_queue_object_name(); $messages_count = count($queue_data[$queue_object_name]['data']); @@ -504,23 +465,18 @@ class phpbb_email extends base * * @return \Symfony\Component\Mailer\Transport\TransportInterface Symfony Mailer transport object */ - public function get_transport() + public function get_transport(): \Symfony\Component\Mailer\Transport\TransportInterface { return $this->transport; } /** - * Send out emails - * - * @return bool + * {@inheritDoc} */ - public function send() + public function send(): bool { $this->prepare_message(); - $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); - $board_contact = trim($this->config['board_contact']); - $this->email->subject($this->subject); $this->email->text($this->msg); @@ -543,23 +499,9 @@ class phpbb_email extends base 'email', ]; extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); + $this->email = $email; - if (empty($this->email->getReplyto())) - { - $this->replyto($board_contact); - } - - if (empty($this->email->getFrom())) - { - $this->from($board_contact); - } - - // Build headers - foreach ($this->additional_headers as $header_name => $header_value) - { - $this->header($header_name, $header_value); - } - $this->build_header(); + $this->build_headers(); // Send message ... if (!$this->use_queue) diff --git a/phpBB/phpbb/messenger/method/phpbb_jabber.php b/phpBB/phpbb/messenger/method/jabber.php similarity index 88% rename from phpBB/phpbb/messenger/method/phpbb_jabber.php rename to phpBB/phpbb/messenger/method/jabber.php index 1bf212a25f..5e174c135b 100644 --- a/phpBB/phpbb/messenger/method/phpbb_jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -22,9 +22,9 @@ namespace phpbb\messenger\method; * @author Florian Schmitz (floele) * * Slightly modified by Acyd Burn (2006) - * Refactored to a service (2023) + * Refactored to a service (2024) */ -class phpbb_jabber extends base +class jabber extends base { /** @var string */ protected $connect_server; @@ -96,7 +96,7 @@ class phpbb_jabber extends base * * @return void */ - public function init() + public function init(): void { $this->username($this->config['jab_username']) ->password($this->config['jab_password']) @@ -113,7 +113,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function get_id() + public function get_id(): int { return NOTIFY_IM; } @@ -121,7 +121,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function get_queue_object_name() + public function get_queue_object_name(): string { return 'jabber'; } @@ -129,7 +129,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function is_enabled() + public function is_enabled(): bool { return !empty($this->config['jab_enable']) && @@ -143,9 +143,9 @@ class phpbb_jabber extends base * See http://php.net/manual/en/context.ssl.php * * @param array $options SSL context options array - * @return $this + * @return self */ - public function stream_options($options = []) + public function stream_options(array $options = []): self { if ($this->use_ssl) { @@ -160,9 +160,9 @@ class phpbb_jabber extends base * Set password to connect to server * * @param string $password Password to connect to server - * @return $this + * @return self */ - public function password($password = '') + public function password(string $password = ''): self { $this->password = html_entity_decode($password, ENT_COMPAT); @@ -173,9 +173,9 @@ class phpbb_jabber extends base * Set use of ssl to connect to server * * @param bool $use_ssl Flag indicating use of ssl to connect to server - * @return $this + * @return self */ - public function ssl($use_ssl = false) + public function ssl(bool $use_ssl = false): self { $this->use_ssl = $use_ssl && self::can_use_ssl(); @@ -187,9 +187,9 @@ class phpbb_jabber extends base * use_ssl flag should be set first * * @param int $port Port to connect to server - * @return $this + * @return self */ - public function port($port = 5222) + public function port(int $port = 5222): self { $this->port = ($port) ? $port : 5222; @@ -206,9 +206,9 @@ class phpbb_jabber extends base * Set username to connect to server * * @param string $username Username to connect to server - * @return $this + * @return self */ - public function username($username = '') + public function username(string $username = ''): self { if (strpos($username, '@') === false) { @@ -228,9 +228,9 @@ class phpbb_jabber extends base * Username should be set first * * @param string $server Server to connect - * @return $this + * @return self */ - public function server($server = '') + public function server(string $server = ''): self { $this->connect_server = ($server) ? $server : 'localhost'; $this->server = $this->jid[1] ?? $this->connect_server; @@ -239,17 +239,21 @@ class phpbb_jabber extends base } /** - * Able to use the SSL functionality? + * Check if it's possible to use the SSL functionality + * + * @return bool */ - public static function can_use_ssl() + public static function can_use_ssl(): bool { return @extension_loaded('openssl'); } /** - * Able to use TLS? + * Check if it's possible to use TLS functionality + * + * @return bool */ - public static function can_use_tls() + public static function can_use_tls(): bool { if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('stream_set_blocking') || !function_exists('stream_get_wrappers')) { @@ -272,19 +276,22 @@ class phpbb_jabber extends base } /** - * Sets the resource which is used. No validation is done here, only escaping. + * Sets the resource which is used. No validation is done here, only escaping + * * @param string $name - * @access public + * @return void */ - public function set_resource($name) + public function set_resource(string $name): void { $this->resource = $name; } /** - * Connect + * Connect to the server + * + * @return bool */ - public function connect() + public function connect(): bool { /* if (!$this->check_jid($this->username . '@' . $this->server)) { @@ -311,9 +318,11 @@ class phpbb_jabber extends base } /** - * Disconnect + * Disconnect from the server + * + * @return bool */ - public function disconnect() + public function disconnect(): bool { if ($this->connected()) { @@ -341,9 +350,11 @@ class phpbb_jabber extends base } /** - * Connected? + * Check if it's still connected to the server + * + * @return bool */ - public function connected() + public function connected(): bool { return is_resource($this->connection) && !feof($this->connection); } @@ -354,7 +365,7 @@ class phpbb_jabber extends base * * @return bool|void */ - public function login() + public function login(): bool|void { if (empty($this->features)) { @@ -368,11 +379,11 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function set_addresses($user) + public function set_addresses(array $user_row): void { - if (isset($user['user_jabber']) && $user['user_jabber']) + if (isset($user_row['user_jabber']) && $user_row['user_jabber']) { - $this->to($user['user_jabber'], (isset($user['username']) ? $user['username'] : '')); + $this->to($user_row['user_jabber'], (isset($user_row['username']) ? $user_row['username'] : '')); } } @@ -383,7 +394,7 @@ class phpbb_jabber extends base * @param string $realname Jabber "To" recipient name * @return void */ - public function to($address, $realname = '') + public function to(string $address, string $realname = ''): void { // IM-Addresses could be empty if (!trim($address)) @@ -399,7 +410,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function reset() + public function init(): void { $this->subject = $this->msg = ''; $this->additional_headers = $this->to = []; @@ -408,11 +419,9 @@ class phpbb_jabber extends base } /** - * Sets the use of messenger queue flag - * - * @return void + * {@inheritDoc} */ - public function set_use_queue($use_queue = true) + public function set_use_queue(bool $use_queue = true): void { $this->use_queue = !$this->config['jab_package_size'] ? false : $use_queue; } @@ -420,7 +429,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function process_queue(&$queue_data) + public function process_queue(array &$queue_data): void { $queue_object_name = $this->get_queue_object_name(); $messages_count = count($queue_data[$queue_object_name]['data']); @@ -473,9 +482,9 @@ class phpbb_jabber extends base } /** - * Send jabber message out - */ - public function send() + * {@inheritDoc} + */ + public function send(): void { $this->prepare_message(); @@ -537,10 +546,9 @@ class phpbb_jabber extends base * Send data to the Jabber server * * @param string $xml - * * @return int|bool */ - public function send_xml($xml) + public function send_xml(string $xml): int|bool { if ($this->connected()) { @@ -555,14 +563,14 @@ class phpbb_jabber extends base } /** - * OpenSocket + * Open socket * - * @param string $server host to connect to - * @param int $port port number + * @param string $server Host to connect to + * @param int $port Port number * * @return bool */ - public function open_socket($server, $port) + public function open_socket(string $server, int $port): bool { if (@function_exists('dns_get_record')) { @@ -590,9 +598,11 @@ class phpbb_jabber extends base } /** - * Return log + * Get connection log + * + * @return string */ - public function get_log() + public function get_log(): string { if ($this->enable_logging && count($this->log_array)) { @@ -604,8 +614,11 @@ class phpbb_jabber extends base /** * Add information to log + * + * @param string $string Log entry + * @return void */ - protected function add_to_log($string) + protected function add_to_log(string $string): void { if ($this->enable_logging) { @@ -617,9 +630,11 @@ class phpbb_jabber extends base * Listens to the connection until it gets data or the timeout is reached. * Thus, it should only be called if data is expected to be received. * - * @return mixed either false for timeout or an array with the received data + * @param int $timeout Connection timeout + * @param bool $wait Flag indicating if it should wait for the responce until timeout + * @return bool|array Either false for timeout or an array with the received data */ - public function listen($timeout = 10, $wait = false) + public function listen(int $timeout = 10, bool $wait = false): bool|array { if (!$this->connected()) { @@ -653,7 +668,7 @@ class phpbb_jabber extends base * * @return bool|void */ - public function register() + public function register(): bool|void { if (!isset($this->session['id']) || isset($this->session['jid'])) { @@ -668,13 +683,12 @@ class phpbb_jabber extends base /** * Sets account presence. No additional info required (default is "online" status) * - * @param string $message online, offline... - * @param string $type dnd, away, chat, xa or nothing - * @param bool $unavailable set this to true if you want to become unavailable - * + * @param string $message Account status (online, offline) + * @param string $type Status type (dnd, away, chat, xa or nothing) + * @param bool $unavailable Set to true to make unavailable status * @return int|bool */ - function send_presence($message = '', $type = '', $unavailable = false) + function send_presence(string $message = '', string $type = '', bool $unavailable = false): int|bool { if (!isset($this->session['jid'])) { @@ -697,10 +711,9 @@ class phpbb_jabber extends base * This handles all the different XML elements * * @param array $xml - * * @return bool|void */ - function response($xml) + function response(array $xml): bool|void { if (!is_array($xml) || !count($xml)) { @@ -1019,7 +1032,7 @@ class phpbb_jabber extends base * * @return int|bool */ - public function send_message($to, $text, $subject = '', $type = 'normal') + public function send_message(string $to, string $text, string $subject = '', string $type = 'normal'): int|bool { if (!isset($this->session['jid'])) { @@ -1042,10 +1055,9 @@ class phpbb_jabber extends base * Encrypts a password as in RFC 2831 * * @param array $data Needs data from the client-server connection - * * @return string */ - public function encrypt_password($data) + public function encrypt_password(array $data): string { // let's me think about again... foreach (array('realm', 'cnonce', 'digest-uri') as $key) @@ -1074,12 +1086,12 @@ class phpbb_jabber extends base } /** - * parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,... - * @param string $data + * Parse data string like a="b",c="d",... or like a="a, b", c, d="e", f=g,... * + * @param string $data * @return array a => b ... */ - public function parse_data($data) + public function parse_data(string $data): array { $data = explode(',', $data); $pairs = array(); @@ -1106,13 +1118,12 @@ class phpbb_jabber extends base } /** - * opposite of jabber::parse_data() - * - * @param array $data + * The opposite of jabber::parse_data() * + * @param array $data Data array * @return string */ - public function implode_data($data) + public function implode_data(arary $data): string { $return = array(); foreach ($data as $key => $value) @@ -1126,8 +1137,13 @@ class phpbb_jabber extends base * xmlize() * @author Hans Anderson * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ + * + * @param string $data Data string + * @param string|int|bool $skip_white New XML parser option value + * @param string $encoding Encoding value + * @return string */ - function xmlize($data, $skip_white = 1, $encoding = 'UTF-8') + function xmlize(string $data, string|int|bool $skip_white = 1, string $encoding = 'UTF-8'): array { $data = trim($data); @@ -1162,8 +1178,12 @@ class phpbb_jabber extends base * _xml_depth() * @author Hans Anderson * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ + * + * @param array $vals XML data array + * @param int $i XML tags depth level + * @return array */ - function _xml_depth($vals, &$i) + function _xml_depth(array $vals, int &$i): array { $children = array(); diff --git a/phpBB/phpbb/messenger/queue.php b/phpBB/phpbb/messenger/queue.php index 2206834269..abcc29c1bd 100644 --- a/phpBB/phpbb/messenger/queue.php +++ b/phpBB/phpbb/messenger/queue.php @@ -41,9 +41,6 @@ class queue /** @var service_collection */ protected $messenger_method_collection; - /** @var int */ - protected $package_size = 0; - /** @var array */ protected $queue_data = []; @@ -55,7 +52,7 @@ class queue * @param service_collection $messenger_method_collection * @param string $cache_file */ - function __construct(config $config, dispatcher $dispatcher, service_collection $messenger_method_collection, $cache_file) + public function __construct(config $config, dispatcher $dispatcher, service_collection $messenger_method_collection, $cache_file) { $this->config = $config; $this->dispatcher = $dispatcher; @@ -71,7 +68,7 @@ class queue * @param int $package_size Size of the messenger package to send * @return void */ - public function init($object, $package_size) + public function init(string $object, int $package_size): void { $this->data[$object] = []; $this->data[$object]['package_size'] = $package_size; @@ -82,10 +79,10 @@ class queue * Put message into the messenger file queue * * @param string $object Queue object type: email/jabber/etc - * @param mixed $message_data Message data to send + * @param array $message_data Message data to send * @return void */ - public function put($object, $message_data) + public function put(string $object, array $message_data): void { $this->data[$object]['data'][] = $message_data; } @@ -95,7 +92,7 @@ class queue * * @return void */ - public function process() + public function process(): void { $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); @@ -119,14 +116,12 @@ class queue /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger_method_collection->getIterator(); - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if (isset($this->queue_data[$messenger_method->get_queue_object_name()])) { $messenger_method->process_queue($this->queue_data); } - $messenger_collection_iterator->next(); } if (!count($this->queue_data)) @@ -164,7 +159,7 @@ class queue * * @return void */ - public function save() + public function save(): void { if (!count($this->data)) { diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 38e48944f0..7cbc532390 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -114,9 +114,8 @@ abstract class messenger_base extends \phpbb\notification\method\base /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger->getIterator(); - while ($messenger_collection_iterator->valid()) + while ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $notify_method || $notify_method == NOTIFY_BOTH) { $messenger_method->template($notification->get_email_template(), $user['user_lang'], '', $template_dir_prefix); @@ -131,7 +130,6 @@ abstract class messenger_base extends \phpbb\notification\method\base // Save the queue in the messenger method class (has to be called or these messages could be lost) $messenger_method->save_queue(); } - $messenger_collection_iterator->next(); } } diff --git a/phpBB/phpbb/ucp/controller/reset_password.php b/phpBB/phpbb/ucp/controller/reset_password.php index ae01972d7f..95a2a82b12 100644 --- a/phpBB/phpbb/ucp/controller/reset_password.php +++ b/phpBB/phpbb/ucp/controller/reset_password.php @@ -25,7 +25,7 @@ use phpbb\passwords\manager; use phpbb\request\request; use phpbb\template\template; use phpbb\user; -use phpbb\di\service_collection; +use phpbb\messenger\method\email; use Symfony\Component\HttpFoundation\Response; /** @@ -51,6 +51,9 @@ class reset_password /** @var log_interface */ protected $log; + /** @var email */ + protected $email_method; + /** @var manager */ protected $passwords_manager; @@ -72,9 +75,6 @@ class reset_password /** @var string PHP extension */ protected $php_ext; - /** @var service_collection */ - protected $messenger; - /** * Reset password controller constructor. * @@ -84,6 +84,7 @@ class reset_password * @param helper $helper * @param language $language * @param log_interface $log + * @param email $email_method * @param manager $passwords_manager * @param request $request * @param template $template @@ -91,12 +92,11 @@ class reset_password * @param string $users_table * @param string $root_path * @param string $php_ext - * @param service_collection $messenger */ public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, helper $helper, - language $language, log_interface $log, manager $passwords_manager, + language $language, log_interface $log, email $email_method, manager $passwords_manager, request $request, template $template, user $user, string $users_table, - string $root_path, string $php_ext, service_collection $messenger) + string $root_path, string $php_ext) { $this->config = $config; $this->db = $db; @@ -104,6 +104,7 @@ class reset_password $this->helper = $helper; $this->language = $language; $this->log = $log; + $this->email_method = $email_method; $this->passwords_manager = $passwords_manager; $this->request = $request; $this->template = $template; @@ -111,7 +112,6 @@ class reset_password $this->users_table = $users_table; $this->root_path = $root_path; $this->php_ext = $php_ext; - $this->messenger = $messenger; } /** @@ -256,19 +256,18 @@ class reset_password WHERE user_id = ' . $user_row['user_id']; $this->db->sql_query($sql); - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('user_forgot_password', $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $this->email_method->set_use_queue(false); + $this->email_method->template('user_forgot_password', $user_row['user_lang']); + $this->email_method->set_addresses($user_row); + $this->email_method->anti_abuse_headers($this->config, $this->user); + $this->email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), 'U_RESET_PASSWORD' => generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [ 'u' => $user_row['user_id'], 'token' => $reset_token, ], false) ]); - $email->send(); + $this->email_method->send(); return $this->helper->message($message); } From 3fddff240c6f86bafcdb3cd56692195daf780f8f Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 23 Jun 2024 14:29:17 +0700 Subject: [PATCH 17/29] [ticket/17135] Use email method instead of service collection where appropriate PHPBB-17135 --- .../default/container/services_console.yml | 4 +- phpBB/config/installer/container/services.yml | 1 + phpBB/phpbb/console/command/user/activate.php | 27 +++--- phpBB/phpbb/console/command/user/add.php | 27 +++--- .../install_finish/task/notify_user.php | 23 +++-- phpBB/phpbb/messenger/method/email.php | 8 +- tests/console/user/activate_test.php | 4 +- tests/console/user/add_test.php | 4 +- tests/console/user/base.php | 83 ++++++++++++++++++- 9 files changed, 124 insertions(+), 57 deletions(-) diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index ba6658f889..81bc0f51b6 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -327,7 +327,7 @@ services: - '@config' - '@language' - '@log' - - '@messenger.method_collection' + - '@messenger.method.email' - '@notification_manager' - '@user_loader' - '%core.root_path%' @@ -342,7 +342,7 @@ services: - '@dbal.conn' - '@config' - '@language' - - '@messenger.method_collection' + - '@messenger.method.email' - '@passwords.manager' - '%core.root_path%' - '%core.php_ext%' diff --git a/phpBB/config/installer/container/services.yml b/phpBB/config/installer/container/services.yml index 70fb0ee308..7ef423afb1 100644 --- a/phpBB/config/installer/container/services.yml +++ b/phpBB/config/installer/container/services.yml @@ -5,6 +5,7 @@ imports: - { resource: ../../default/container/services_filesystem.yml } - { resource: ../../default/container/services_http.yml } - { resource: ../../default/container/services_language.yml } + - { resource: ../../default/container/services_messenger.yml } - { resource: ../../default/container/services_php.yml } - { resource: ../../default/container/services_routing.yml } - { resource: ../../default/container/services_twig.yml } diff --git a/phpBB/phpbb/console/command/user/activate.php b/phpBB/phpbb/console/command/user/activate.php index 23f1b390e3..9fa0f4182b 100644 --- a/phpBB/phpbb/console/command/user/activate.php +++ b/phpBB/phpbb/console/command/user/activate.php @@ -17,10 +17,10 @@ use phpbb\config\config; use phpbb\console\command\command; use phpbb\language\language; use phpbb\log\log_interface; +use phpbb\messenger\method\email; use phpbb\notification\manager; use phpbb\user; use phpbb\user_loader; -use phpbb\di\service_collection; use Symfony\Component\Console\Command\Command as symfony_command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -33,15 +33,15 @@ class activate extends command /** @var config */ protected $config; + /** @var email */ + protected $email_method; + /** @var language */ protected $language; /** @var log_interface */ protected $log; - /** @var service_collection */ - protected $messenger; - /** @var manager */ protected $notifications; @@ -69,18 +69,18 @@ class activate extends command * @param config $config * @param language $language * @param log_interface $log - * @param service_collection $messenger + * @param email $email_method * @param manager $notifications * @param user_loader $user_loader * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(user $user, config $config, language $language, log_interface $log, service_collection $messenger, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext) + public function __construct(user $user, config $config, language $language, log_interface $log, email $email_method, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext) { $this->config = $config; + $this->email_method = $email_method; $this->language = $language; $this->log = $log; - $this->messenger = $messenger; $this->notifications = $notifications; $this->user_loader = $user_loader; $this->phpbb_root_path = $phpbb_root_path; @@ -200,15 +200,14 @@ class activate extends command if ($input->getOption('send-email')) { - $email_method = $this->messenger->offsetGet('messenger.method.email'); - $email_method->set_use_queue(false); - $email_method->template('admin_welcome_activated', $user_row['user_lang']); - $email_method->set_addresses($user_row); - $email_method->anti_abuse_headers($this->config, $this->user); - $email_method->assign_vars([ + $this->email_method->set_use_queue(false); + $this->email_method->template('admin_welcome_activated', $user_row['user_lang']); + $this->email_method->set_addresses($user_row); + $this->email_method->anti_abuse_headers($this->config, $this->user); + $this->email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), ]); - $email_method->send(); + $this->email_method->send(); } } } diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php index 1ad3770c76..aeb0ee87eb 100644 --- a/phpBB/phpbb/console/command/user/add.php +++ b/phpBB/phpbb/console/command/user/add.php @@ -18,9 +18,9 @@ use phpbb\console\command\command; use phpbb\db\driver\driver_interface; use phpbb\exception\runtime_exception; use phpbb\language\language; +use phpbb\messenger\method\email; use phpbb\passwords\manager; use phpbb\user; -use phpbb\di\service_collection; use Symfony\Component\Console\Command\Command as symfony_command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; @@ -40,12 +40,12 @@ class add extends command /** @var config */ protected $config; + /** @var email */ + protected $email_method; + /** @var language */ protected $language; - /** @var service_collection */ - protected $messenger; - /** @var manager */ protected $password_manager; @@ -75,12 +75,12 @@ class add extends command * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(user $user, driver_interface $db, config $config, language $language, service_collection $messenger, manager $password_manager, $phpbb_root_path, $php_ext) + public function __construct(user $user, driver_interface $db, config $config, language $language, email $email_method, manager $password_manager, $phpbb_root_path, $php_ext) { - $this->db = $db; $this->config = $config; + $this->db = $db; + $this->email_method = $email_method; $this->language = $language; - $this->messenger = $messenger; $this->password_manager = $password_manager; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -313,18 +313,17 @@ class add extends command $user_actkey = $this->get_activation_key($user_id); - $email_method = $this->messenger->offsetGet('messenger.method.email'); - $email_method->set_use_queue(false); - $email_method->template($email_template, $this->user->lang_name); - $email_method->to($this->data['email'], $this->data['username']); - $email_method->anti_abuse_headers($this->config, $this->user); - $email_method->assign_vars([ + $this->email_method->set_use_queue(false); + $this->email_method->template($email_template, $this->user->lang_name); + $this->email_method->to($this->data['email'], $this->data['username']); + $this->email_method->anti_abuse_headers($this->config, $this->user); + $this->email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode($this->language->lang('WELCOME_SUBJECT', $this->config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($this->data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->data['new_password'], ENT_COMPAT), 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey", ]); - $email_method->send(); + $this->email_method->send(); } /** diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index 3f2c439bdd..ff575130a4 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -20,7 +20,7 @@ use phpbb\auth\auth; use phpbb\log\log_interface; use phpbb\user; use phpbb\install\helper\container_factory; -use phpbb\di\service_collection; +use phpbb\messenger\method\email; /** * Logs installation and sends an email to the admin @@ -39,6 +39,9 @@ class notify_user extends \phpbb\install\task_base /** @var db */ protected $config; + /** @var email */ + protected $email_method; + /** @var log_interface */ protected $log; @@ -48,9 +51,6 @@ class notify_user extends \phpbb\install\task_base /** @var user */ protected $user; - /** @var service_collection */ - protected $messenger; - /** * Constructor * @@ -67,7 +67,7 @@ class notify_user extends \phpbb\install\task_base $this->auth = $container->get('auth'); $this->log = $container->get('log'); $this->user = $container->get('user'); - $this->messenger = $container->get('messenger.method_collection'); + $this->email_method = $container->get('messenger.method.email'); $this->phpbb_root_path = $phpbb_root_path; // We need to reload config for cases when it doesn't have all values @@ -97,16 +97,15 @@ class notify_user extends \phpbb\install\task_base if ($this->config['email_enable']) { - $email_method = $this->messenger->offsetGet('messenger.method.email'); - $email_method->set_use_queue(false); - $email_method->template('installed', $this->install_config->get('user_language', 'en')); - $email_method->to($this->config['board_email'], $this->install_config->get('admin_name')); - $email_method->anti_abuse_headers($this->config, $this->user); - $email_method->assign_vars([ + $this->email_method->set_use_queue(false); + $this->email_method->template('installed', $this->install_config->get('user_language', 'en')); + $this->email_method->to($this->config['board_email'], $this->install_config->get('admin_name')); + $this->email_method->anti_abuse_headers($this->config, $this->user); + $this->email_method->assign_vars([ 'USERNAME' => html_entity_decode($this->install_config->get('admin_name'), ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->install_config->get('admin_passwd'), ENT_COMPAT), ]); - $email_method->send(); + $this->email_method->send(); } // Login admin diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index d3642b263d..187f869ce0 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -17,13 +17,7 @@ use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email as symfony_email; -use Symfony\Component\Mime\Header\DateHeader; use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\Header\IdentificationHeader; -use Symfony\Component\Mime\Header\MailboxHeader; -use Symfony\Component\Mime\Header\MailboxListHeader; -use Symfony\Component\Mime\Header\PathHeader; -use Symfony\Component\Mime\Header\UnstructuredHeader; /** * Messenger class @@ -308,7 +302,7 @@ class email extends base // Add additional headers $phpbb_headers = array_merge($phpbb_headers, $this->additional_headers); - + foreach ($phpbb_headers as $header => $value) { $this->headers->addHeader($header, $value); diff --git a/tests/console/user/activate_test.php b/tests/console/user/activate_test.php index 5df59a3711..2ff65c3e3b 100644 --- a/tests/console/user/activate_test.php +++ b/tests/console/user/activate_test.php @@ -38,11 +38,11 @@ class phpbb_console_user_activate_test extends phpbb_console_user_base $this->config, $this->language, $this->log, + $this->email, $this->notifications, $this->user_loader, $this->phpbb_root_path, - $this->php_ext, - $this->messenger_method_collection + $this->php_ext )); $command = $application->find('user:activate'); diff --git a/tests/console/user/add_test.php b/tests/console/user/add_test.php index 3e2d2cfedf..fb2618787e 100644 --- a/tests/console/user/add_test.php +++ b/tests/console/user/add_test.php @@ -30,10 +30,10 @@ class phpbb_console_user_add_test extends phpbb_console_user_base $this->db, $this->config, $this->language, + $this->email, $this->passwords_manager, $this->phpbb_root_path, - $this->php_ext, - $this->messenger_method_collection + $this->php_ext )); $command = $application->find('user:add'); diff --git a/tests/console/user/base.php b/tests/console/user/base.php index 7d14b9a664..610e72f491 100644 --- a/tests/console/user/base.php +++ b/tests/console/user/base.php @@ -105,10 +105,85 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); - $this->messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); - $this->messenger_method_collection->add('messenger.method.email'); - $this->messenger_method_collection->add('messenger.method.jabber'); - $phpbb_container->set('messenger.method_collection', $this->messenger_method_collection); + $assets_bag = new \phpbb\template\assets_bag(); + $phpbb_container->set('assets.bag', $assets_bag); + + $dispatcher = new \phpbb\event\dispatcher(); + $phpbb_container->set('dispatcher', $dispatcher); + + $core_cache_dir = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + $phpbb_container->setParameter('core.cache_dir', $core_cache_dir); + + $core_messenger_queue_file = $core_cache_dir . 'queue.' . $phpEx; + $phpbb_container->setParameter('core.messenger_queue_file', $core_messenger_queue_file); + + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $messenger_method_collection->add('messenger.method.email'); + $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + + $messenger_queue = new \phpbb\messenger\queue($config, $dispatcher, $messenger_method_collection, $core_messenger_queue_file); + $phpbb_container->set('messenger.queue', $messenger_queue); + + $request = new phpbb_mock_request; + $phpbb_container->set('request', $request); + + $symfony_request = new \phpbb\symfony_request( + $request + ); + + $phpbb_path_helper = new \phpbb\path_helper( + $symfony_request, + $request, + $phpbb_root_path, + $phpEx + ); + $phpbb_container->set('path_helper', $phpbb_path_helper); + + $extension_manager = new phpbb_mock_extension_manager( + __DIR__ . '/', + [] + ); + $phpbb_container->set('ext.manager', $extension_manager); + + $context = new \phpbb\template\context(); + $cache_path = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/twig'; + $phpbb_container->setParameter('core.template.cache_path', $cache_path); + $filesystem = new \phpbb\filesystem\filesystem(); + $phpbb_container->set('filesystem', $filesystem); + + $twig = new \phpbb\template\twig\environment( + $assets_bag, + $this->config, + $filesystem, + $phpbb_path_helper, + $cache_path, + null, + new \phpbb\template\twig\loader(''), + $dispatcher, + [ + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ] + ); + $twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang); + $phpbb_container->set('template.twig.extensions.phpbb', $twig_extension); + + $twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container); + $twig_extensions_collection->add('template.twig.extensions.phpbb'); + $phpbb_container->set('template.twig.extensions.collection', $twig_extensions_collection); + + $twig->addExtension($twig_extension); + $twig_lexer = new \phpbb\template\twig\lexer($twig); + $phpbb_container->set('template.twig.lexer', $twig_lexer); + + $this->email = new \phpbb\messenger\method\phpbb_email( + $assets_bag, $this->config, $dispatcher, $this->language, $log, $request, $user, $messenger_queue, + $phpbb_path_helper, $extension_manager, $twig_extensions_collection, $twig_lexer, + $cache_path, $phpbb_root_path + ); + $phpbb_container->set('messenger.method.email', $this->email); parent::setUp(); } From 0c720eaf7ccd7b95c3576016717a2e2629f50b99 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 23 Jun 2024 14:55:01 +0700 Subject: [PATCH 18/29] [ticket/17135] Fix code flaws PHPBB-17135 --- .../default/container/services_messenger.yml | 4 +- phpBB/includes/acp/acp_email.php | 3 +- phpBB/includes/acp/acp_inactive.php | 4 +- phpBB/includes/ucp/ucp_activate.php | 2 +- phpBB/includes/ucp/ucp_register.php | 6 +- phpBB/memberlist.php | 2 +- phpBB/phpbb/messenger/method/base.php | 41 ++---- phpBB/phpbb/messenger/method/email.php | 62 ++++----- phpBB/phpbb/messenger/method/jabber.php | 35 +++--- .../notification/method/messenger_base.php | 2 +- tests/console/user/base.php | 58 +++++++-- tests/email/email_parsing_test.php | 19 ++- .../phpbb_functional_test_case.php | 118 ++++++++++++++++++ 13 files changed, 249 insertions(+), 107 deletions(-) diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index c2ff6fa679..8645d2f17c 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -16,9 +16,7 @@ services: - '@assets.bag' - '@config' - '@dispatcher' - - '@ext.manager' - '@language' - - '@log' - '@messenger.queue' - '@path_helper' - '@request' @@ -27,6 +25,8 @@ services: - '@user' - '%core.root_path%' - '%core.template.cache_path%' + - '@?ext.manager' + - '@?log' messenger.method.email: class: phpbb\messenger\method\email diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 630b1bcb14..677cea26b5 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -217,7 +217,8 @@ class acp_email ); extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); - $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); + /** @var \phpbb\di\service_collection */ + $messenger = $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); for ($i = 0, $size = count($email_list); $i < $size; $i++) { diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 9d5d730348..fa9ad8fa52 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -198,7 +198,9 @@ class acp_inactive { // Send the messages $usernames = $user_ids = array(); - $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); + + /** @var \phpbb\di\service_collection */ + $messenger = $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); do diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index b8867fcdb3..dcb2801fff 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -131,7 +131,7 @@ class ucp_activate $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); + $messenger = $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); foreach ($messenger_collection_iterator as $messenger_method) { diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 6736ea25f0..e5319f1dbb 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -458,6 +458,7 @@ class ucp_register if ($config['email_enable']) { + /** var \phpbb\messenger\method\email */ $email_method = $phpbb_container->get('messenger.method.email'); $email_method->set_use_queue(false); $email_method->template($email_template, $data['lang']); @@ -490,8 +491,9 @@ class ucp_register * @var string server_url Server URL * @var int user_id New user ID * @var string user_actkey User activation key - * @var messenger messenger phpBB Messenger + * @var \phpbb\messenger\method\email email_method phpBB email notification method * @since 3.2.4-RC1 + * @changed 4.0.0-a1 Added vars: email_method. Removed vars: messenger. */ $vars = array( 'user_row', @@ -501,7 +503,7 @@ class ucp_register 'server_url', 'user_id', 'user_actkey', - 'messenger', + 'email_method', ); extract($phpbb_dispatcher->trigger_event('core.ucp_register_welcome_email_before', compact($vars))); diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index be4b467a5f..aa15cdd6be 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -900,7 +900,7 @@ switch ($mode) case 'contactadmin': case 'email': - $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); + $messenger = $phpbb_container->get('messenger.method_collection'); $user_id = $request->variable('u', 0); $topic_id = $request->variable('t', 0); diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 1d6e23ad29..8b12128d43 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -94,9 +94,7 @@ abstract class base * @param assets_bag $assets_bag * @param config $config * @param dispatcher $dispatcher - * @param manager $ext_manager * @param language $language - * @param log_interface $log * @param queue $queue * @param path_helper $path_helper * @param request $request @@ -105,14 +103,14 @@ abstract class base * @param user $user * @param string $phpbb_root_path * @param string $template_cache_path + * @param manager $ext_manager + * @param log_interface $log */ public function __construct( assets_bag $assets_bag, config $config, dispatcher $dispatcher, - manager $ext_manager, language $language, - log_interface $log, queue $queue, path_helper $path_helper, request $request, @@ -120,7 +118,9 @@ abstract class base lexer $twig_lexer, user $user, $phpbb_root_path, - $template_cache_path + $template_cache_path, + ?manager $ext_manager = null, + ?log_interface $log = null ) { $this->assets_bag = $assets_bag; @@ -198,32 +198,6 @@ abstract class base $this->subject = $subject; } - /** - * Adds antiabuse headers - * - * @param config $config Config object - * @param user $user User object - * @return void - */ - abstract public function anti_abuse_headers(config $config, user $user): void; - - /** - * Set up extra headers - * - * @param string $header_name Email header name - * @param string $header_value Email header body - * @return void - */ - abstract public function header(string $header_name, string $header_value): void; - - /** - * Set the reply to address - * - * @param string $address Email "Reply to" address - * @return void - */ - abstract public function reply_to($address): void; - /** * Send out messages * @@ -444,7 +418,10 @@ abstract class base $type = strtoupper($this->get_queue_object_name()); $calling_page = html_entity_decode($this->request->server('PHP_SELF'), ENT_COMPAT); $message = '' . $type . '
' . htmlspecialchars($calling_page, ENT_COMPAT) . '

' . $msg . '
'; - $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); + if ($this->log) + { + $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); + } } /** diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index 187f869ce0..c33f048fcc 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -26,11 +26,11 @@ class email extends base { /** @var array */ private const PRIORITY_MAP = [ - Email::PRIORITY_HIGHEST => 'Highest', - Email::PRIORITY_HIGH => 'High', - Email::PRIORITY_NORMAL => 'Normal', - Email::PRIORITY_LOW => 'Low', - Email::PRIORITY_LOWEST => 'Lowest', + symfony_email::PRIORITY_HIGHEST => 'Highest', + symfony_email::PRIORITY_HIGH => 'High', + symfony_email::PRIORITY_NORMAL => 'Normal', + symfony_email::PRIORITY_LOW => 'Low', + symfony_email::PRIORITY_LOWEST => 'Lowest', ]; /** @@ -40,7 +40,7 @@ class email extends base */ protected $dsn = ''; - /** @var Email */ + /** @var symfony_email */ protected $email; /** @var Address */ @@ -53,13 +53,13 @@ class email extends base * @var int * * Possible values are: - * Email::PRIORITY_HIGHEST - * Email::PRIORITY_HIGH - * Email::PRIORITY_NORMAL - * Email::PRIORITY_LOW - * Email::PRIORITY_LOWEST + * symfony_email::PRIORITY_HIGHEST + * symfony_email::PRIORITY_HIGH + * symfony_email::PRIORITY_NORMAL + * symfony_email::PRIORITY_LOW + * symfony_email::PRIORITY_LOWEST */ - protected $mail_priority = Email::PRIORITY_NORMAL; + protected $mail_priority = symfony_email::PRIORITY_NORMAL; /** @var \phpbb\messenger\queue */ protected $queue; @@ -102,7 +102,7 @@ class email extends base $this->email = new symfony_email(); $this->headers = $this->email->getHeaders(); $this->subject = $this->msg = ''; - $this->mail_priority = Email::PRIORITY_NORMAL; + $this->mail_priority = symfony_email::PRIORITY_NORMAL; $this->additional_headers = []; $this->use_queue = true; @@ -254,16 +254,16 @@ class email extends base * Set the email priority * * Possible values are: - * Email::PRIORITY_HIGHEST = 1 - * Email::PRIORITY_HIGH = 2 - * Email::PRIORITY_NORMAL = 3 - * Email::PRIORITY_LOW = 4 - * Email::PRIORITY_LOWEST = 5 + * symfony_email::PRIORITY_HIGHEST = 1 + * symfony_email::PRIORITY_HIGH = 2 + * symfony_email::PRIORITY_NORMAL = 3 + * symfony_email::PRIORITY_LOW = 4 + * symfony_email::PRIORITY_LOWEST = 5 * * @param int $priority Email priority level * @return void */ - public function set_mail_priority(int $priority = Email::PRIORITY_NORMAL): void + public function set_mail_priority(int $priority = symfony_email::PRIORITY_NORMAL): void { $this->email->priority($priority); } @@ -291,7 +291,7 @@ class email extends base $this->email->priority($this->mail_priority); - $phpbb_headers = [ + $headers = [ 'Return-Path' => new Address($this->config['board_email']), 'Sender' => new Address($this->config['board_email']), 'X-MSMail-Priority' => self::PRIORITY_MAP[$this->mail_priority], @@ -301,25 +301,23 @@ class email extends base ]; // Add additional headers - $phpbb_headers = array_merge($phpbb_headers, $this->additional_headers); + $headers = array_merge($headers, $this->additional_headers); - foreach ($phpbb_headers as $header => $value) - { - $this->headers->addHeader($header, $value); - } - - $headers = $this->headers; /** * Event to modify email header entries * * @event core.modify_email_headers - * @var Headers headers Array containing email header entries + * @var array headers Array containing email header entries * @since 3.1.11-RC1 - * @changed 4.0.0-a1 'headers' var type changed from array to \Symfony\Component\Mime\Header\Headers */ $vars = ['headers']; extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - $this->headers = $headers; + + foreach ($headers as $header => $value) + { + $this->headers->addHeader($header, $value); + } + } /** @@ -566,7 +564,9 @@ class email extends base 'email' => $this->email, ]); } - $this->reset(); + + // Reset the object + $this->init(); return true; } diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index 5e174c135b..8e5e0a4e88 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -359,13 +359,12 @@ class jabber extends base return is_resource($this->connection) && !feof($this->connection); } - /** * Initiates login (using data from contructor, after calling connect()) * - * @return bool|void + * @return bool|null */ - public function login(): bool|void + public function login(): bool|null { if (empty($this->features)) { @@ -410,7 +409,7 @@ class jabber extends base /** * {@inheritDoc} */ - public function init(): void + public function reset(): void { $this->subject = $this->msg = ''; $this->additional_headers = $this->to = []; @@ -484,7 +483,7 @@ class jabber extends base /** * {@inheritDoc} */ - public function send(): void + public function send(): bool { $this->prepare_message(); @@ -666,9 +665,9 @@ class jabber extends base /** * Initiates account registration (based on data used for contructor) * - * @return bool|void + * @return bool|null */ - public function register(): bool|void + public function register(): bool|null { if (!isset($this->session['id']) || isset($this->session['jid'])) { @@ -711,9 +710,9 @@ class jabber extends base * This handles all the different XML elements * * @param array $xml - * @return bool|void + * @return bool|null */ - function response(array $xml): bool|void + function response(array $xml): bool|null { if (!is_array($xml) || !count($xml)) { @@ -728,20 +727,17 @@ class jabber extends base { $this->response(array($key => $value)); } - return; + return true; } - else + else if (is_array(reset($xml)) && count(reset($xml)) > 1) { // or even multiple elements of the same type? // array('message' => array(0 => ..., 1 => ...)) - if (is_array(reset($xml)) && count(reset($xml)) > 1) + foreach (reset($xml) as $value) { - foreach (reset($xml) as $value) - { - $this->response(array(key($xml) => array(0 => $value))); - } - return; + $this->response(array(key($xml) => array(0 => $value))); } + return true; } switch (key($xml)) @@ -1012,6 +1008,7 @@ class jabber extends base $message['subject'] = $xml['message'][0]['#']['subject'][0]['#']; } $this->session['messages'][] = $message; + return true; break; default: @@ -1123,7 +1120,7 @@ class jabber extends base * @param array $data Data array * @return string */ - public function implode_data(arary $data): string + public function implode_data(array $data): string { $return = array(); foreach ($data as $key => $value) @@ -1141,7 +1138,7 @@ class jabber extends base * @param string $data Data string * @param string|int|bool $skip_white New XML parser option value * @param string $encoding Encoding value - * @return string + * @return array */ function xmlize(string $data, string|int|bool $skip_white = 1, string $encoding = 'UTF-8'): array { diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 7cbc532390..97994f84af 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -114,7 +114,7 @@ abstract class messenger_base extends \phpbb\notification\method\base /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger->getIterator(); - while ($messenger_collection_iterator as $messenger_method) + foreach ($messenger_collection_iterator as $messenger_method) { if ($messenger_method->get_id() == $notify_method || $notify_method == NOTIFY_BOTH) { diff --git a/tests/console/user/base.php b/tests/console/user/base.php index 610e72f491..511cfff9a3 100644 --- a/tests/console/user/base.php +++ b/tests/console/user/base.php @@ -34,7 +34,7 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case { global $auth, $db, $cache, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path, $phpEx; - $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + $phpbb_dispatcher = new \phpbb\event\dispatcher(); $phpbb_container = new phpbb_mock_container_builder(); $phpbb_container->set('cache.driver', new phpbb_mock_cache()); $phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); @@ -108,8 +108,7 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case $assets_bag = new \phpbb\template\assets_bag(); $phpbb_container->set('assets.bag', $assets_bag); - $dispatcher = new \phpbb\event\dispatcher(); - $phpbb_container->set('dispatcher', $dispatcher); + $phpbb_container->set('dispatcher', $phpbb_dispatcher); $core_cache_dir = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; $phpbb_container->setParameter('core.cache_dir', $core_cache_dir); @@ -121,7 +120,7 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case $messenger_method_collection->add('messenger.method.email'); $phpbb_container->set('messenger.method_collection', $messenger_method_collection); - $messenger_queue = new \phpbb\messenger\queue($config, $dispatcher, $messenger_method_collection, $core_messenger_queue_file); + $messenger_queue = new \phpbb\messenger\queue($config, $phpbb_dispatcher, $messenger_method_collection, $core_messenger_queue_file); $phpbb_container->set('messenger.queue', $messenger_queue); $request = new phpbb_mock_request; @@ -139,9 +138,33 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case ); $phpbb_container->set('path_helper', $phpbb_path_helper); - $extension_manager = new phpbb_mock_extension_manager( + $factory = new \phpbb\db\tools\factory(); + $db_doctrine = $this->new_doctrine_dbal(); + $db_tools = $factory->get($db_doctrine); + $migrator = new \phpbb\db\migrator( + $phpbb_container, + $config, + $db, + $db_tools, + 'phpbb_migrations', + $phpbb_root_path, + $this->php_ext, + 'phpbb_', + self::get_core_tables(), + [], + new \phpbb\db\migration\helper() + ); + $phpbb_container->set('migrator', $migrator); + + $finder_factory = new \phpbb\finder\factory(null, false, $phpbb_root_path, $this->php_ext); + $extension_manager = new \phpbb\extension\manager( + $phpbb_container, + $db, + $config, + $finder_factory, + 'phpbb_ext', __DIR__ . '/', - [] + new \phpbb\cache\service(new phpbb_mock_cache(), $config, $db, $phpbb_dispatcher, $phpbb_root_path, $this->php_ext) ); $phpbb_container->set('ext.manager', $extension_manager); @@ -159,7 +182,7 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case $cache_path, null, new \phpbb\template\twig\loader(''), - $dispatcher, + $phpbb_dispatcher, [ 'cache' => false, 'debug' => false, @@ -167,7 +190,7 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case 'autoescape' => false, ] ); - $twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang); + $twig_extension = new \phpbb\template\twig\extension($context, $twig, $this->language); $phpbb_container->set('template.twig.extensions.phpbb', $twig_extension); $twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container); @@ -178,10 +201,21 @@ abstract class phpbb_console_user_base extends phpbb_database_test_case $twig_lexer = new \phpbb\template\twig\lexer($twig); $phpbb_container->set('template.twig.lexer', $twig_lexer); - $this->email = new \phpbb\messenger\method\phpbb_email( - $assets_bag, $this->config, $dispatcher, $this->language, $log, $request, $user, $messenger_queue, - $phpbb_path_helper, $extension_manager, $twig_extensions_collection, $twig_lexer, - $cache_path, $phpbb_root_path + $this->email = new \phpbb\messenger\method\email( + $assets_bag, + $this->config, + $phpbb_dispatcher, + $this->language, + $messenger_queue, + $phpbb_path_helper, + $request, + $twig_extensions_collection, + $twig_lexer, + $user, + $phpbb_root_path, + $cache_path, + $extension_manager, + $this->log ); $phpbb_container->set('messenger.method.email', $this->email); diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php index 1a464e86aa..fc1d1ef3be 100644 --- a/tests/email/email_parsing_test.php +++ b/tests/email/email_parsing_test.php @@ -123,10 +123,21 @@ class phpbb_email_parsing_test extends phpbb_test_case $messenger_queue = new \phpbb\messenger\queue($config, $dispatcher, $messenger_method_collection, $core_messenger_queue_file); $phpbb_container->set('messenger.queue', $messenger_queue); - $this->email = new \phpbb\messenger\method\phpbb_email( - $assets_bag, $config, $dispatcher, $lang, $log, $request, $user, $messenger_queue, - $phpbb_path_helper, $extension_manager, $twig_extensions_collection, $twig_lexer, - $cache_path, $phpbb_root_path + $this->email = new \phpbb\messenger\method\email( + $assets_bag, + $config, + $dispatcher, + $lang, + $messenger_queue, + $phpbb_path_helper, + $request, + $twig_extensions_collection, + $twig_lexer, + $user, + $phpbb_root_path, + $cache_path, + $extension_manager, + $log ); $phpbb_container->set('messenger.method.email', $this->email); diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 3e9b654b0e..79e76fd1ae 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -324,6 +324,123 @@ class phpbb_functional_test_case extends phpbb_test_case return $extension_manager; } + protected static function get_messenger_method_email($container) + { + global $phpbb_root_path, $phpEx; + + $config = new \phpbb\config\config( + [ + 'version' => PHPBB_VERSION, + 'email_enable' => false, + 'email_package_size' => 0, + 'smtp_delivery' => 0, + 'default_lang' => 'en', + ] + ); + + $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); + $lang = new \phpbb\language\language($lang_loader); + $user = new \phpbb\user($lang, '\phpbb\datetime'); + $container->set('user', $user); + $container->set('language', $lang); + + $assets_bag = new \phpbb\template\assets_bag(); + $container->set('assets.bag', $assets_bag); + + $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + $container->set('dispatcher', $phpbb_dispatcher); + + $core_cache_dir = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'; + $container->setParameter('core.cache_dir', $core_cache_dir); + + $core_messenger_queue_file = $core_cache_dir . 'queue.' . $phpEx; + $container->setParameter('core.messenger_queue_file', $core_messenger_queue_file); + + $messenger_method_collection = new \phpbb\di\service_collection($container); + $messenger_method_collection->add('messenger.method.email'); + $container->set('messenger.method_collection', $messenger_method_collection); + + $messenger_queue = new \phpbb\messenger\queue($config, $phpbb_dispatcher, $messenger_method_collection, $core_messenger_queue_file); + $container->set('messenger.queue', $messenger_queue); + + $request = new phpbb_mock_request; + $container->set('request', $request); + + $symfony_request = new \phpbb\symfony_request( + $request + ); + + $phpbb_path_helper = new \phpbb\path_helper( + $symfony_request, + $request, + $phpbb_root_path, + $phpEx + ); + $container->set('path_helper', $phpbb_path_helper); + + $dbms = self::$config['dbms']; + $db = new $dbms(); + $db->sql_connect(self::$config['dbhost'], self::$config['dbuser'], self::$config['dbpasswd'], self::$config['dbname'], self::$config['dbport']); + + $extension_manager = new phpbb_mock_extension_manager($phpbb_root_path, [], $container); + $container->set('ext.manager', $extension_manager); + + $context = new \phpbb\template\context(); + $cache_path = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/twig'; + $container->setParameter('core.template.cache_path', $cache_path); + $filesystem = new \phpbb\filesystem\filesystem(); + $container->set('filesystem', $filesystem); + + $twig = new \phpbb\template\twig\environment( + $assets_bag, + $config, + $filesystem, + $phpbb_path_helper, + $cache_path, + null, + new \phpbb\template\twig\loader(''), + $phpbb_dispatcher, + [ + 'cache' => false, + 'debug' => false, + 'auto_reload' => true, + 'autoescape' => false, + ] + ); + $twig_extension = new \phpbb\template\twig\extension($context, $twig, $lang); + $container->set('template.twig.extensions.phpbb', $twig_extension); + + $twig_extensions_collection = new \phpbb\di\service_collection($container); + $twig_extensions_collection->add('template.twig.extensions.phpbb'); + $container->set('template.twig.extensions.collection', $twig_extensions_collection); + + $twig->addExtension($twig_extension); + $twig_lexer = new \phpbb\template\twig\lexer($twig); + $container->set('template.twig.lexer', $twig_lexer); + + $auth = new \phpbb\auth\auth(); + $log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); + $container->set('log', $log); + + $email_method = new \phpbb\messenger\method\email( + $assets_bag, + $config, + $phpbb_dispatcher, + $lang, + $messenger_queue, + $phpbb_path_helper, + $request, + $twig_extensions_collection, + $twig_lexer, + $user, + $phpbb_root_path, + $cache_path, + $extension_manager, + $log + ); + $container->set('messenger.method.email', $email_method); + } + protected static function install_board() { global $phpbb_root_path, $phpEx; @@ -374,6 +491,7 @@ class phpbb_functional_test_case extends phpbb_test_case $container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task()); $container->register('installer.install_finish.install_extensions')->setSynthetic(true); $container->set('installer.install_finish.install_extensions', new phpbb_mock_null_installer_task()); + self::get_messenger_method_email($container); $container->compile(); $language = $container->get('language'); From e3ed54f0b5d9346eda1dc6d0194e7dc5659bb0d9 Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 24 Jun 2024 20:47:42 +0700 Subject: [PATCH 19/29] [ticket/17135] Attempt to fix Psalm issues PHPBB-17135 --- phpBB/phpbb/messenger/method/jabber.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index 8e5e0a4e88..199adcd65a 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -362,9 +362,9 @@ class jabber extends base /** * Initiates login (using data from contructor, after calling connect()) * - * @return bool|null + * @return bool */ - public function login(): bool|null + public function login(): bool { if (empty($this->features)) { @@ -710,9 +710,9 @@ class jabber extends base * This handles all the different XML elements * * @param array $xml - * @return bool|null + * @return bool */ - function response(array $xml): bool|null + function response(array $xml): bool { if (!is_array($xml) || !count($xml)) { @@ -769,6 +769,7 @@ class jabber extends base { return $this->response($this->features); } + return false; break; case 'stream:features': From e8cf35c583d96fa84b1433312daecb5e2845c930 Mon Sep 17 00:00:00 2001 From: rxu Date: Thu, 3 Oct 2024 22:04:05 +0700 Subject: [PATCH 20/29] [ticket/17135] Update Symfony mailer PHPBB-17135 --- tests/notification/notification_method_webpush_test.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/notification/notification_method_webpush_test.php b/tests/notification/notification_method_webpush_test.php index e52bf9a7ac..7967a0f7c6 100644 --- a/tests/notification/notification_method_webpush_test.php +++ b/tests/notification/notification_method_webpush_test.php @@ -171,6 +171,9 @@ class notification_method_webpush_test extends phpbb_tests_notification_base $ban_manager = new \phpbb\ban\manager($collection, new \phpbb\cache\driver\dummy(), $this->db, $this->language, $this->log, $user, 'phpbb_bans', 'phpbb_users'); $phpbb_container->set('ban.manager', $ban_manager); + $messenger_method_collection = new \phpbb\di\service_collection($phpbb_container); + $phpbb_container->set('messenger.method_collection', $messenger_method_collection); + $this->notification_method_webpush = new \phpbb\notification\method\webpush( $phpbb_container->get('config'), $phpbb_container->get('dbal.conn'), @@ -180,7 +183,7 @@ class notification_method_webpush_test extends phpbb_tests_notification_base $phpbb_root_path, $phpEx, $phpbb_container->getParameter('tables.notification_push'), - $phpbb_container->getParameter('tables.push_subscriptions'), + $phpbb_container->getParameter('tables.push_subscriptions') ); $phpbb_container->set('notification.method.webpush', $this->notification_method_webpush); From 50e408bdea795be1915e664e10edb65dbc5478b2 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 8 Dec 2024 18:29:58 +0700 Subject: [PATCH 21/29] [ticket/17135] Add messenger method interface class PHPBB-17135 --- phpBB/phpbb/messenger/method/base.php | 32 ++++------ .../messenger/method/messenger_interface.php | 59 +++++++++++++++++++ 2 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 phpBB/phpbb/messenger/method/messenger_interface.php diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 8b12128d43..15fa782d18 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -29,7 +29,7 @@ use phpbb\user; /** * Messenger base class */ -abstract class base +abstract class base implements messenger_interface { /** @var array */ protected $additional_headers = []; @@ -142,16 +142,12 @@ abstract class base } /** - * Get messenger method id - * - * @return int + * {@inheritdoc} */ abstract public function get_id(): int; /** - * Check if the messenger method is enabled - * - * @return bool + * {@inheritdoc} */ abstract public function is_enabled(): bool; @@ -176,6 +172,7 @@ abstract class base * Set addresses for to/im as available * * @param array $user_row User row + * * @return void */ abstract public function set_addresses(array $user_row): void; @@ -188,10 +185,7 @@ abstract class base abstract public function get_queue_object_name(): string; /** - * Set up subject for mail - * - * @param string $subject Email subject - * @return void + * {@inheritdoc} */ public function subject(string $subject = ''): void { @@ -199,16 +193,15 @@ abstract class base } /** - * Send out messages - * - * @return bool + * {@inheritdoc} */ - abstract protected function send(): bool; + abstract public function send(): bool; /** * Send messages from the queue * * @param array $queue_data Queue data array + * * @return void */ abstract public function process_queue(array &$queue_data): void; @@ -303,6 +296,7 @@ abstract class base * Assign variables to email template * * @param array $vars Array of VAR => VALUE to assign to email template + * * @return void */ public function assign_vars(array $vars): void @@ -316,6 +310,7 @@ abstract class base * * @param string $blockname Template block name * @param array $vars Array of VAR => VALUE to assign to email template block + * * @return void */ public function assign_block_vars(string $blockname, array $vars): void @@ -402,10 +397,7 @@ abstract class base } /** - * Add error message to log - * - * @param string $msg Error message text - * @return void + * {@inheritdoc} */ public function error(string $msg): void { @@ -426,6 +418,7 @@ abstract class base /** * Save message data to the messenger file queue + * * @return void */ public function save_queue(): void @@ -479,6 +472,7 @@ abstract class base * * @param string|array $path_name Email template path name * @param string|array $paths Email template paths + * * @return void */ protected function set_template_paths(string|array $path_name, string|array $paths): void diff --git a/phpBB/phpbb/messenger/method/messenger_interface.php b/phpBB/phpbb/messenger/method/messenger_interface.php new file mode 100644 index 0000000000..980cd06a22 --- /dev/null +++ b/phpBB/phpbb/messenger/method/messenger_interface.php @@ -0,0 +1,59 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\messenger\method; + +/** + * Messenger method interface class + */ +interface messenger_interface +{ + /** + * Get messenger method id + * + * @return int + */ + public function get_id(): int; + + /** + * Check if the messenger method is enabled + * + * @return bool + */ + public function is_enabled(): bool; + + /** + * Set up subject for the message + * + * @param string $subject Email subject + * + * @return void + */ + public function subject(string $subject = ''): void; + + /** + * Send out messages + * + * @return bool + */ + public function send(): bool; + + /** + * Add error message to log + * + * @param string $msg Error message text + * + * @return void + */ + public function error(string $msg): void; +} From 2f6ec7fc65192f0491482258d82fe3689c4d0fcc Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 5 Jan 2025 16:01:06 +0700 Subject: [PATCH 22/29] [ticket/17135] Update Symfony mailer PHPBB-17135 --- phpBB/composer.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/phpBB/composer.lock b/phpBB/composer.lock index ba6cff7047..bf9ac175e9 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f6e182dafa1a6e6a60136e35d5379532", + "content-hash": "2ce7bc4e8f61d065ff471afa38f12394", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -4488,16 +4488,16 @@ }, { "name": "symfony/mailer", - "version": "v6.3.5", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06" + "reference": "c2f7e0d8d7ac8fe25faccf5d8cac462805db2663" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/d89611a7830d51b5e118bca38e390dea92f9ea06", - "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06", + "url": "https://api.github.com/repos/symfony/mailer/zipball/c2f7e0d8d7ac8fe25faccf5d8cac462805db2663", + "reference": "c2f7e0d8d7ac8fe25faccf5d8cac462805db2663", "shasum": "" }, "require": { @@ -4505,8 +4505,8 @@ "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^6.2", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -4517,10 +4517,10 @@ "symfony/twig-bridge": "<6.2.1" }, "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/messenger": "^6.2", - "symfony/twig-bridge": "^6.2" + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" }, "type": "library", "autoload": { @@ -4548,7 +4548,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.3.5" + "source": "https://github.com/symfony/mailer/tree/v6.4.13" }, "funding": [ { @@ -4564,7 +4564,7 @@ "type": "tidelift" } ], - "time": "2023-09-06T09:47:15+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/mime", From 28d5534d069c65f260400cdfbe295a19c44c1e1f Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 6 Jan 2025 18:24:32 +0700 Subject: [PATCH 23/29] [ticket/17135] Address review issues but constants PHPBB-17135 --- phpBB/includes/acp/acp_email.php | 19 +++++++++++++----- phpBB/includes/ucp/ucp_resend.php | 7 ++++--- phpBB/phpbb/messenger/method/base.php | 7 ++++--- phpBB/phpbb/messenger/method/email.php | 20 ++++++++++++------- phpBB/phpbb/messenger/method/jabber.php | 20 +++++++++---------- .../notification/method/messenger_base.php | 1 - phpBB/phpbb/template/twig/extension.php | 9 +++++---- 7 files changed, 50 insertions(+), 33 deletions(-) diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 677cea26b5..9d8657a294 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -227,25 +227,34 @@ class acp_email foreach ($messenger_collection_iterator as $messenger_method) { - if ($messenger_method->get_id() == $used_method || $used_method == NOTIFY_BOTH) + $notify_method = $messenger_method->get_id(); + if ($notify_method == $used_method || $used_method == NOTIFY_BOTH) { $messenger_method->set_use_queue($use_queue); $messenger_method->template($email_template, $used_lang); $messenger_method->subject(html_entity_decode($subject, ENT_COMPAT)); $messenger_method->assign_vars($template_data); - if ($messenger_method->get_id() == NOTIFY_EMAIL) + if ($notify_method == NOTIFY_EMAIL) { for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) { $email_row = $email_list[$i][$j]; - $messenger_method->{((count($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); + if (count($email_list[$i]) == 1) + { + $messenger_method->to($email_row['email'], $email_row['name']); + + } + else + { + $messenger_method->bcc($email_row['email'], $email_row['name']); + } } $messenger_method->anti_abuse_headers($config, $user); $messenger_method->set_mail_priority($priority); } - else if ($messenger_method->get_id() == NOTIFY_JABBER) + else if ($notify_method == NOTIFY_IM) { for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) { @@ -254,7 +263,7 @@ class acp_email } } - $errored = !$messenger_method->send(); + $errored = !$messenger_method->send() || $errored; if ($use_queue) { $messenger_method->save_queue(); diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index ab108bc15d..278c086a8b 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -92,6 +92,7 @@ class ucp_resend trigger_error('NO_GROUP'); } + $board_url = generate_board_url(); $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false; $email_method = $phpbb_container->get('messenger.method.email'); @@ -107,7 +108,7 @@ class ucp_resend $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), - 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", + 'U_ACTIVATE' => $board_url . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", ]); if ($coppa) @@ -145,8 +146,8 @@ class ucp_resend $messenger_method->anti_abuse_headers($config, $user); $messenger_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), - 'U_USER_DETAILS' => generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$user_row['user_id']}", - 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", + 'U_USER_DETAILS' => $board_url . "/memberlist.$phpEx?mode=viewprofile&u={$user_row['user_id']}", + 'U_ACTIVATE' => $board_url . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", ]); $messenger_method->send(); diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 15fa782d18..46d676013c 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -117,8 +117,8 @@ abstract class base implements messenger_interface service_collection $twig_extensions_collection, lexer $twig_lexer, user $user, - $phpbb_root_path, - $template_cache_path, + string $phpbb_root_path, + string $template_cache_path, ?manager $ext_manager = null, ?log_interface $log = null ) @@ -154,6 +154,8 @@ abstract class base implements messenger_interface /** * Sets the use of messenger queue flag * + * @param bool $use_queue Flag indicating if cached queue to be used + * * @return void */ public function set_use_queue(bool $use_queue = true): void @@ -426,7 +428,6 @@ abstract class base implements messenger_interface if ($this->use_queue && !empty($this->queue)) { $this->queue->save(); - return; } } diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index c33f048fcc..a8927c23e3 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -110,9 +110,7 @@ class email extends base } /** - * Sets the use of messenger queue flag - * - * @return void + * {@inheritdoc} */ public function set_use_queue(bool $use_queue = true): void { @@ -124,7 +122,7 @@ class email extends base */ public function set_addresses(array $user_row): void { - if (isset($user_row['user_email']) && $user_row['user_email']) + if (!empty($user_row['user_email'])) { $this->to($user_row['user_email'], $user_row['username'] ?: ''); } @@ -295,8 +293,8 @@ class email extends base 'Return-Path' => new Address($this->config['board_email']), 'Sender' => new Address($this->config['board_email']), 'X-MSMail-Priority' => self::PRIORITY_MAP[$this->mail_priority], - 'X-Mailer' => 'phpBB3', - 'X-MimeOLE' => 'phpBB3', + 'X-Mailer' => 'phpBB', + 'X-MimeOLE' => 'phpBB', 'X-phpBB-Origin' => 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()), ]; @@ -472,6 +470,7 @@ class email extends base $this->email->subject($this->subject); $this->email->text($this->msg); + $break = false; $subject = $this->subject; $msg = $this->msg; $email = $this->email; @@ -479,13 +478,15 @@ class email extends base * Event to send message via external transport * * @event core.notification_message_email + * @var bool break Flag indicating if the function return after hook * @var string subject The message subject * @var string msg The message text * @var string email The Symfony Email object * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, break + * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses */ $vars = [ + 'break', 'subject', 'msg', 'email', @@ -495,6 +496,11 @@ class email extends base $this->build_headers(); + if ($break) + { + return true; + } + // Send message ... if (!$this->use_queue) { diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index 199adcd65a..b4fab79574 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -191,7 +191,7 @@ class jabber extends base */ public function port(int $port = 5222): self { - $this->port = ($port) ? $port : 5222; + $this->port = ($port > 0) ? $port : 5222; // Change port if we use SSL if ($this->port == 5222 && $this->use_ssl) @@ -210,15 +210,15 @@ class jabber extends base */ public function username(string $username = ''): self { - if (strpos($username, '@') === false) - { - $this->username = $username; - } - else + if (str_contains($username, '@')) { $this->jid = explode('@', $username, 2); $this->username = $this->jid[0]; } + else + { + $this->username = $username; + } return $this; } @@ -232,7 +232,7 @@ class jabber extends base */ public function server(string $server = ''): self { - $this->connect_server = ($server) ? $server : 'localhost'; + $this->connect_server = $server ?: 'localhost'; $this->server = $this->jid[1] ?? $this->connect_server; return $this; @@ -407,7 +407,7 @@ class jabber extends base } /** - * {@inheritDoc} + * Resets all the data (address, template file, etc) to default */ public function reset(): void { @@ -663,7 +663,7 @@ class jabber extends base } /** - * Initiates account registration (based on data used for contructor) + * Initiates account registration (based on data used for constructor) * * @return bool|null */ @@ -714,7 +714,7 @@ class jabber extends base */ function response(array $xml): bool { - if (!is_array($xml) || !count($xml)) + if (!count($xml)) { return false; } diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 97994f84af..4aaf01c133 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -112,7 +112,6 @@ abstract class messenger_base extends \phpbb\notification\method\base continue; } - /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger->getIterator(); foreach ($messenger_collection_iterator as $messenger_method) { diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index fa9fca0705..96a1aa91f1 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -14,6 +14,9 @@ namespace phpbb\template\twig; use Twig\Error\RuntimeError; +use Twig\Extension\CoreExtension; +use Twig\Extension\EscaperExtension; +use Twig\Runtime\EscaperRuntime; class extension extends \Twig\Extension\AbstractExtension { @@ -164,8 +167,7 @@ class extension extends \Twig\Extension\AbstractExtension // We always include the last element (this was the past design) $end = ($end == -1 || $end === null) ? null : $end + 1; - /** @psalm-suppress UndefinedFunction */ - return twig_slice($env, $item, $start, $end, $preserveKeys); + return CoreExtension::slice($env->getCharset(), $item, $start, $end, $preserveKeys); } /** @@ -214,8 +216,7 @@ class extension extends \Twig\Extension\AbstractExtension { $args = func_get_args(); - /** @psalm-suppress UndefinedFunction */ - return twig_escape_filter($this->environment, call_user_func_array([$this, 'lang'], $args), 'js'); + return $this->environment->getRuntime(EscaperRuntime::class)->escape(call_user_func_array([$this, 'lang'], $args), 'js'); } /** From 0d8c0c422841fecbe82ce41ca00712888b0279c9 Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 6 Jan 2025 20:01:52 +0700 Subject: [PATCH 24/29] [ticket/17135] Move notify method constants to interface class PHPBB-17135 --- phpBB/includes/acp/acp_email.php | 15 ++++++------- phpBB/includes/acp/acp_inactive.php | 2 +- phpBB/includes/acp/acp_jabber.php | 21 +++++++------------ phpBB/includes/acp/acp_users.php | 7 ++++--- phpBB/includes/constants.php | 3 +++ phpBB/includes/functions_user.php | 4 +++- phpBB/includes/ucp/ucp_activate.php | 2 +- phpBB/includes/ucp/ucp_prefs.php | 12 ++++++----- phpBB/includes/ucp/ucp_profile.php | 6 ++++-- phpBB/includes/ucp/ucp_resend.php | 2 +- phpBB/install/convertors/convert_phpbb20.php | 4 +++- .../v310/notification_options_reconvert.php | 6 ++++-- phpBB/phpbb/message/admin_form.php | 6 ++++-- phpBB/phpbb/message/message.php | 8 ++++--- phpBB/phpbb/message/topic_form.php | 6 ++++-- phpBB/phpbb/messenger/method/email.php | 2 +- phpBB/phpbb/messenger/method/jabber.php | 2 +- .../messenger/method/messenger_interface.php | 9 ++++++++ phpBB/phpbb/notification/method/email.php | 3 ++- phpBB/phpbb/notification/method/jabber.php | 3 ++- .../notification/method/messenger_base.php | 4 ++-- 21 files changed, 77 insertions(+), 50 deletions(-) diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 9d8657a294..446067c2a8 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -11,6 +11,8 @@ * */ +use phpbb\messenger\method\messenger_interface; + /** * @ignore */ @@ -156,9 +158,9 @@ class acp_email foreach ($rows as $row) { - if (($row['user_notify_type'] == NOTIFY_EMAIL && $row['user_email']) || - ($row['user_notify_type'] == NOTIFY_IM && $row['user_jabber']) || - ($row['user_notify_type'] == NOTIFY_BOTH && ($row['user_email'] || $row['user_jabber']))) + if (($row['user_notify_type'] == messenger_interface::NOTIFY_EMAIL && $row['user_email']) || + ($row['user_notify_type'] == messenger_interface::NOTIFY_IM && $row['user_jabber']) || + ($row['user_notify_type'] == messenger_interface::NOTIFY_BOTH && ($row['user_email'] || $row['user_jabber']))) { if ($i == $max_chunk_size || $row['user_lang'] != $old_lang || $row['user_notify_type'] != $old_notify_type) { @@ -228,14 +230,14 @@ class acp_email foreach ($messenger_collection_iterator as $messenger_method) { $notify_method = $messenger_method->get_id(); - if ($notify_method == $used_method || $used_method == NOTIFY_BOTH) + if ($notify_method == $used_method || $used_method == messenger_interface::NOTIFY_BOTH) { $messenger_method->set_use_queue($use_queue); $messenger_method->template($email_template, $used_lang); $messenger_method->subject(html_entity_decode($subject, ENT_COMPAT)); $messenger_method->assign_vars($template_data); - if ($notify_method == NOTIFY_EMAIL) + if ($notify_method == messenger_interface::NOTIFY_EMAIL) { for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) { @@ -243,7 +245,6 @@ class acp_email if (count($email_list[$i]) == 1) { $messenger_method->to($email_row['email'], $email_row['name']); - } else { @@ -254,7 +255,7 @@ class acp_email $messenger_method->anti_abuse_headers($config, $user); $messenger_method->set_mail_priority($priority); } - else if ($notify_method == NOTIFY_IM) + else if ($notify_method == messenger_interface::NOTIFY_IM) { for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) { diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index fa9ad8fa52..ec74d59169 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -207,7 +207,7 @@ class acp_inactive { foreach ($messenger_collection_iterator as $messenger_method) { - if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) + if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == $messenger_method::NOTIFY_BOTH) { $messenger_method->template('user_remind_inactive', $row['user_lang']); $messenger_method->set_addresses($row); diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 07f5dadbff..c952275daa 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -30,15 +30,10 @@ class acp_jabber function main($id, $mode) { global $db, $user, $template, $phpbb_log, $request; - global $config, $phpbb_root_path, $phpEx; + global $config, $phpbb_container, $phpbb_root_path, $phpEx; $user->add_lang('acp/board'); - if (!class_exists('jabber')) - { - include($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); - } - $submit = (isset($_POST['submit'])) ? true : false; if ($mode != 'settings') @@ -73,11 +68,11 @@ class acp_jabber $message = $user->lang['JAB_SETTINGS_CHANGED']; $log = 'JAB_SETTINGS_CHANGED'; - // Is this feature enabled? Then try to establish a connection - if ($jab_enable) - { - $jabber = new jabber($jab_host, $jab_port, $jab_username, $jab_password, $jab_use_ssl, $jab_verify_peer, $jab_verify_peer_name, $jab_allow_self_signed); + $jabber = $phpbb_container->get('messenger.method.jabber'); + // Is this feature enabled? Then try to establish a connection + if ($jabber->is_enabled()) + { if (!$jabber->connect()) { trigger_error($user->lang['ERR_JAB_CONNECT'] . '

' . $jabber->get_log() . adm_back_link($this->u_action), E_USER_WARNING); @@ -97,12 +92,12 @@ class acp_jabber // We update the user table to be sure all users that have IM as notify type are set to both as notify type // We set this to both because users still have their jabber address entered and may want to receive jabber notifications again once it is re-enabled. $sql_ary = array( - 'user_notify_type' => NOTIFY_BOTH, + 'user_notify_type' => $jabber::NOTIFY_BOTH, ); $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_notify_type = ' . NOTIFY_IM; + WHERE user_notify_type = ' . $jabber::NOTIFY_IM; $db->sql_query($sql); } @@ -137,7 +132,7 @@ class acp_jabber 'JAB_VERIFY_PEER' => $jab_verify_peer, 'JAB_VERIFY_PEER_NAME' => $jab_verify_peer_name, 'JAB_ALLOW_SELF_SIGNED' => $jab_allow_self_signed, - 'S_CAN_USE_SSL' => jabber::can_use_ssl(), + 'S_CAN_USE_SSL' => $jabber::can_use_ssl(), 'S_GTALK_NOTE' => (!@function_exists('dns_get_record')) ? true : false, )); } diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index d88d050387..a954ec09f0 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -16,6 +16,7 @@ */ use phpbb\controller\helper; +use phpbb\messenger\method\messenger_interface; if (!defined('IN_PHPBB')) { @@ -1792,9 +1793,9 @@ class acp_users 'MASS_EMAIL' => $data['massemail'], 'ALLOW_PM' => $data['allowpm'], 'HIDE_ONLINE' => $data['hideonline'], - 'NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, - 'NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, - 'NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false, + 'NOTIFY_EMAIL' => ($data['notifymethod'] == messenger_interface::NOTIFY_EMAIL) ? true : false, + 'NOTIFY_IM' => ($data['notifymethod'] == messenger_interface::NOTIFY_IM) ? true : false, + 'NOTIFY_BOTH' => ($data['notifymethod'] == messenger_interface::NOTIFY_BOTH) ? true : false, 'NOTIFY_PM' => $data['notifypm'], 'BBCODE' => $data['bbcode'], 'SMILIES' => $data['smilies'], diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 825a328d39..e9890d27e1 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -120,8 +120,11 @@ define('POST_ANNOUNCE', 2); define('POST_GLOBAL', 3); // Notify methods +/** @deprecated 4.0.0-a1 Replaced by \phpbb\messenger\method\messenger_interface::NOTIFY_EMAIL, to be removed in 5.0.0-a1 */ define('NOTIFY_EMAIL', 0); +/** @deprecated 4.0.0-a1 Replaced by \phpbb\messenger\method\messenger_interface::NOTIFY_IM, to be removed in 5.0.0-a1 */ define('NOTIFY_IM', 1); +/** @deprecated 4.0.0-a1 Replaced by \phpbb\messenger\method\messenger_interface::NOTIFY_BOTH, to be removed in 5.0.0-a1 */ define('NOTIFY_BOTH', 2); // Notify status diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index bb1b63f177..7441b74413 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -11,6 +11,8 @@ * */ +use phpbb\messenger\method\messenger_interface; + /** * @ignore */ @@ -244,7 +246,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) 'user_notify' => 0, 'user_notify_pm' => 1, - 'user_notify_type' => NOTIFY_EMAIL, + 'user_notify_type' => messenger_interface::NOTIFY_EMAIL, 'user_allow_pm' => 1, 'user_allow_viewonline' => 1, 'user_allow_viewemail' => 1, diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index dcb2801fff..c9dd3e553e 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -135,7 +135,7 @@ class ucp_activate $messenger_collection_iterator = $messenger->getIterator(); foreach ($messenger_collection_iterator as $messenger_method) { - if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) + if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == $messenger_method::NOTIFY_BOTH) { $messenger_method->set_use_queue(false); $messenger_method->template('admin_welcome_activated', $user_row['user_lang']); diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index 8c682cebc0..d08a81b854 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -11,6 +11,8 @@ * */ +use phpbb\messenger\method\messenger_interface; + /** * @ignore */ @@ -52,10 +54,10 @@ class ucp_prefs 'allowpm' => $request->variable('allowpm', (bool) $user->data['user_allow_pm']), ); - if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml'))) + if ($data['notifymethod'] == messenger_interface::NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml'))) { // Jabber isnt enabled, or no jabber field filled in. Update the users table to be sure its correct. - $data['notifymethod'] = NOTIFY_BOTH; + $data['notifymethod'] = messenger_interface::NOTIFY_BOTH; } /** @@ -182,9 +184,9 @@ class ucp_prefs $template->assign_vars([ 'ERROR' => (count($error)) ? implode('
', $error) : '', - 'S_NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, - 'S_NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, - 'S_NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false, + 'S_NOTIFY_EMAIL' => ($data['notifymethod'] == messenger_interface::NOTIFY_EMAIL) ? true : false, + 'S_NOTIFY_IM' => ($data['notifymethod'] == messenger_interface::NOTIFY_IM) ? true : false, + 'S_NOTIFY_BOTH' => ($data['notifymethod'] == messenger_interface::NOTIFY_BOTH) ? true : false, 'S_VIEW_EMAIL' => $data['viewemail'], 'S_MASS_EMAIL' => $data['massemail'], 'S_ALLOW_PM' => $data['allowpm'], diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 0b34598e14..52b007a1fe 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -11,6 +11,8 @@ * */ +use phpbb\messenger\method\messenger_interface; + /** * @ignore */ @@ -363,11 +365,11 @@ class ucp_profile { $data['notify'] = $user->data['user_notify_type']; - if ($data['notify'] == NOTIFY_IM && (!$config['jab_enable'] || !$data['jabber'] || !@extension_loaded('xml'))) + if ($data['notify'] == messenger_interface::NOTIFY_IM && (!$config['jab_enable'] || !$data['jabber'] || !@extension_loaded('xml'))) { // User has not filled in a jabber address (Or one of the modules is disabled or jabber is disabled) // Disable notify by Jabber now for this user. - $data['notify'] = NOTIFY_EMAIL; + $data['notify'] = messenger_interface::NOTIFY_EMAIL; } $sql_ary = array( diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 278c086a8b..4c9c1a86c6 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -139,7 +139,7 @@ class ucp_resend foreach ($messenger_collection_iterator as $messenger_method) { $messenger_method->set_use_queue(false); - if ($messenger_method->get_id() == $row['user_notify_type'] || $row['user_notify_type'] == NOTIFY_BOTH) + if ($messenger_method->get_id() == $row['user_notify_type'] || $row['user_notify_type'] == $messenger_method::NOTIFY_BOTH) { $messenger_method->template('admin_activate', $row['user_lang']); $messenger_method->set_addresses($row); diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 864e6f3b6e..8750c24dcc 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -11,6 +11,8 @@ * */ +use phpbb\messenger\method\messenger_interface; + /** * NOTE to potential convertor authors. Please use this file to get * familiar with the structure since we added some bare explanations here. @@ -936,7 +938,7 @@ if (!$get_info) array('user_emailtime', 'users.user_emailtime', 'null_to_zero'), array('user_notify', 'users.user_notify', 'intval'), array('user_notify_pm', 'users.user_notify_pm', 'intval'), - array('user_notify_type', NOTIFY_EMAIL, ''), + array('user_notify_type', $messenger_method::NOTIFY_EMAIL, ''), array('user_allow_pm', 'users.user_allow_pm', 'intval'), array('user_allow_viewonline', 'users.user_allow_viewonline', 'intval'), array('user_allow_viewemail', 'users.user_viewemail', 'intval'), diff --git a/phpBB/phpbb/db/migration/data/v310/notification_options_reconvert.php b/phpBB/phpbb/db/migration/data/v310/notification_options_reconvert.php index 7c03eef347..7f58076a8d 100644 --- a/phpBB/phpbb/db/migration/data/v310/notification_options_reconvert.php +++ b/phpBB/phpbb/db/migration/data/v310/notification_options_reconvert.php @@ -13,6 +13,8 @@ namespace phpbb\db\migration\data\v310; +use phpbb\messenger\method\messenger_interface; + class notification_options_reconvert extends \phpbb\db\migration\migration { public static function depends_on() @@ -67,12 +69,12 @@ class notification_options_reconvert extends \phpbb\db\migration\migration // In-board notification $notification_methods[] = ''; - if ($row['user_notify_type'] == NOTIFY_EMAIL || $row['user_notify_type'] == NOTIFY_BOTH) + if ($row['user_notify_type'] == messenger_interface::NOTIFY_EMAIL || $row['user_notify_type'] == messenger_interface::NOTIFY_BOTH) { $notification_methods[] = 'email'; } - if ($row['user_notify_type'] == NOTIFY_IM || $row['user_notify_type'] == NOTIFY_BOTH) + if ($row['user_notify_type'] == messenger_interface::NOTIFY_IM || $row['user_notify_type'] == messenger_interface::NOTIFY_BOTH) { $notification_methods[] = 'jabber'; } diff --git a/phpBB/phpbb/message/admin_form.php b/phpBB/phpbb/message/admin_form.php index 2c3305dc03..72beaa38a6 100644 --- a/phpBB/phpbb/message/admin_form.php +++ b/phpBB/phpbb/message/admin_form.php @@ -13,6 +13,8 @@ namespace phpbb\message; +use phpbb\messenger\method\messenger_interface; + /** * Class admin_form * Displays a message to the user and allows him to send an email @@ -155,7 +157,7 @@ class admin_form extends form } $this->message->set_sender($this->user->ip, $this->sender_name, $this->sender_address, $this->user->lang_name); - $this->message->set_sender_notify_type(NOTIFY_EMAIL); + $this->message->set_sender_notify_type(messenger_interface::NOTIFY_EMAIL); } $this->message->set_template('contact_admin'); @@ -165,7 +167,7 @@ class admin_form extends form $this->user->lang['ADMINISTRATOR'], $this->config['board_contact'], $this->config['default_lang'], - NOTIFY_EMAIL + messenger_interface::NOTIFY_EMAIL ); $this->message->set_template_vars(array( diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 34295d1a02..90b8a1ff5f 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -13,6 +13,8 @@ namespace phpbb\message; +use phpbb\messenger\method\messenger_interface; + /** * Class message * Holds all information for an email and sends it in the end @@ -46,7 +48,7 @@ class message /** @var string */ protected $sender_jabber = ''; /** @var int */ - protected $sender_notify_type = NOTIFY_EMAIL; + protected $sender_notify_type = messenger_interface::NOTIFY_EMAIL; /** @var array */ protected $recipients; @@ -134,7 +136,7 @@ class message * @param string $recipient_jabber * @return void */ - public function add_recipient($recipient_name, $recipient_address, $recipient_lang, $recipient_notify_type = NOTIFY_EMAIL, $recipient_username = '', $recipient_jabber = '') + public function add_recipient($recipient_name, $recipient_address, $recipient_lang, $recipient_notify_type = messenger_interface::NOTIFY_EMAIL, $recipient_username = '', $recipient_jabber = '') { $this->recipients[] = array( 'name' => $recipient_name, @@ -250,7 +252,7 @@ class message foreach ($messenger_collection_iterator as $messenger_method) { $messenger_method->set_use_queue(false); - if ($messenger_method->get_id() == $recipient['notify_type'] || $recipient['notify_type'] == NOTIFY_BOTH) + if ($messenger_method->get_id() == $recipient['notify_type'] || $recipient['notify_type'] == $messenger_method::NOTIFY_BOTH) { $messenger_method->template($this->template, $recipient['lang']); $messenger_method->set_addresses($recipient); diff --git a/phpBB/phpbb/message/topic_form.php b/phpBB/phpbb/message/topic_form.php index facde9a462..dd73a67ab2 100644 --- a/phpBB/phpbb/message/topic_form.php +++ b/phpBB/phpbb/message/topic_form.php @@ -13,6 +13,8 @@ namespace phpbb\message; +use phpbb\messenger\method\messenger_interface; + /** * Class topic_form * Form used to send topics as notification emails @@ -130,9 +132,9 @@ class topic_form extends form $this->recipient_name, $this->recipient_address, $this->recipient_lang, - NOTIFY_EMAIL + messenger_interface::NOTIFY_EMAIL ); - $this->message->set_sender_notify_type(NOTIFY_EMAIL); + $this->message->set_sender_notify_type(messenger_interface::NOTIFY_EMAIL); parent::submit($messenger); } diff --git a/phpBB/phpbb/messenger/method/email.php b/phpBB/phpbb/messenger/method/email.php index a8927c23e3..1bad23760c 100644 --- a/phpBB/phpbb/messenger/method/email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -75,7 +75,7 @@ class email extends base */ public function get_id(): int { - return NOTIFY_EMAIL; + return self::NOTIFY_EMAIL; } /** diff --git a/phpBB/phpbb/messenger/method/jabber.php b/phpBB/phpbb/messenger/method/jabber.php index b4fab79574..a4a2c07f61 100644 --- a/phpBB/phpbb/messenger/method/jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -115,7 +115,7 @@ class jabber extends base */ public function get_id(): int { - return NOTIFY_IM; + return self::NOTIFY_IM; } /** diff --git a/phpBB/phpbb/messenger/method/messenger_interface.php b/phpBB/phpbb/messenger/method/messenger_interface.php index 980cd06a22..b733f3d3d4 100644 --- a/phpBB/phpbb/messenger/method/messenger_interface.php +++ b/phpBB/phpbb/messenger/method/messenger_interface.php @@ -18,6 +18,15 @@ namespace phpbb\messenger\method; */ interface messenger_interface { + /** @var int Email notify method used */ + public const NOTIFY_EMAIL = 0; + + /** @var int Instant messaging (Jabber) notify method used */ + public const NOTIFY_IM = 1; + + /** @var int Both notify methods used */ + public const NOTIFY_BOTH = 2; + /** * Get messenger method id * diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index 2c612367cc..8a2fff1bb9 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -19,6 +19,7 @@ use phpbb\user_loader; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\di\service_collection; +use phpbb\messenger\method\messenger_interface; /** * Email notification method class @@ -135,7 +136,7 @@ class email extends \phpbb\notification\method\messenger_base $insert_buffer->flush(); - $this->notify_using_messenger(NOTIFY_EMAIL); + $this->notify_using_messenger(messenger_interface::NOTIFY_EMAIL); } /** diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php index 4a0e52fc62..e3482f98be 100644 --- a/phpBB/phpbb/notification/method/jabber.php +++ b/phpBB/phpbb/notification/method/jabber.php @@ -18,6 +18,7 @@ use phpbb\user; use phpbb\user_loader; use phpbb\config\config; use phpbb\di\service_collection; +use phpbb\messenger\method\messenger_interface; /** * Jabber notification method class @@ -98,6 +99,6 @@ class jabber extends \phpbb\notification\method\messenger_base return; } - $this->notify_using_messenger(NOTIFY_IM, 'short/'); + $this->notify_using_messenger(messenger_interface::NOTIFY_IM, 'short/'); } } diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 4aaf01c133..ca93f4c8a2 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -67,7 +67,7 @@ abstract class messenger_base extends \phpbb\notification\method\base /** * Notify using phpBB messenger * - * @param int $notify_method Notify method for messenger (e.g. NOTIFY_IM) + * @param int $notify_method Notify method for messenger (e.g. \phpbb\messenger\method\messenger_interface::NOTIFY_IM) * @param string $template_dir_prefix Base directory to prepend to the email template name * * @return void @@ -115,7 +115,7 @@ abstract class messenger_base extends \phpbb\notification\method\base $messenger_collection_iterator = $this->messenger->getIterator(); foreach ($messenger_collection_iterator as $messenger_method) { - if ($messenger_method->get_id() == $notify_method || $notify_method == NOTIFY_BOTH) + if ($messenger_method->get_id() == $notify_method || $notify_method == $messenger_method::NOTIFY_BOTH) { $messenger_method->template($notification->get_email_template(), $user['user_lang'], '', $template_dir_prefix); $messenger_method->set_addresses($user); From cd17625e213d4846f3a40395d028747ffcf113b5 Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 6 Jan 2025 20:54:34 +0700 Subject: [PATCH 25/29] [ticket/17135] Add ACP modules common test PHPBB-17135 --- phpBB/phpbb/template/twig/extension.php | 1 - tests/functional/acp_test.php | 60 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/functional/acp_test.php diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index 96a1aa91f1..982601e41b 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -15,7 +15,6 @@ namespace phpbb\template\twig; use Twig\Error\RuntimeError; use Twig\Extension\CoreExtension; -use Twig\Extension\EscaperExtension; use Twig\Runtime\EscaperRuntime; class extension extends \Twig\Extension\AbstractExtension diff --git a/tests/functional/acp_test.php b/tests/functional/acp_test.php new file mode 100644 index 0000000000..1dcd013fae --- /dev/null +++ b/tests/functional/acp_test.php @@ -0,0 +1,60 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_acp_test extends phpbb_functional_test_case +{ + public function test_all_acp_module_links() + { + $this->login(); + $this->admin_login(); + $this->add_lang(['common']); + + // Browse ACP main page + $crawler = self::request('GET', 'index.php'); + $crawler = self::$client->click($crawler->selectLink($this->lang('ACP_SHORT'))->link()); + + // Get all ACP module URLs array + $acp_modules = $crawler->filter('li.tab a')->each( + function ($node, $i) + { + // Filter out responsive mode links + if (empty($node->attr('class'))) + { + return $node->link(); + } + } + ); + + // Browse all ACP modules and get their mode URLs array + $acp_submodules = []; + foreach ($acp_modules as $module) + { + $crawler = self::$client->click($module); + $acp_submodules = array_merge($acp_submodules, $crawler->filter('div.menu_block li a')->each( + function ($node, $i) + { + return $node->link(); + } + )); + } + + // Browse all ACP submodules' modes + foreach ($acp_submodules as $acp_submodule) + { + self::$client->click($acp_submodule); + } + } +} From a447f957ba5c0b4956eef818baca6f24a196e412 Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 6 Jan 2025 21:35:30 +0700 Subject: [PATCH 26/29] [ticket/17135] Assert xCP modules array is not empty and test output PHPBB-17135 --- tests/functional/acp_test.php | 7 ++++++- tests/functional/mcp/mcp_test.php | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/functional/acp_test.php b/tests/functional/acp_test.php index 1dcd013fae..bf37fc7203 100644 --- a/tests/functional/acp_test.php +++ b/tests/functional/acp_test.php @@ -25,6 +25,7 @@ class phpbb_functional_acp_test extends phpbb_functional_test_case // Browse ACP main page $crawler = self::request('GET', 'index.php'); $crawler = self::$client->click($crawler->selectLink($this->lang('ACP_SHORT'))->link()); + self::assert_response_html(); // Get all ACP module URLs array $acp_modules = $crawler->filter('li.tab a')->each( @@ -37,24 +38,28 @@ class phpbb_functional_acp_test extends phpbb_functional_test_case } } ); + $this->assertNotEmpty($acp_modules); // Browse all ACP modules and get their mode URLs array $acp_submodules = []; foreach ($acp_modules as $module) { $crawler = self::$client->click($module); - $acp_submodules = array_merge($acp_submodules, $crawler->filter('div.menu_block li a')->each( + self::assert_response_html(); + $acp_submodules = array_merge($acp_submodules, $crawler->filter('div.menu-block li a')->each( function ($node, $i) { return $node->link(); } )); } + $this->assertNotEmpty($acp_submodules); // Browse all ACP submodules' modes foreach ($acp_submodules as $acp_submodule) { self::$client->click($acp_submodule); + self::assert_response_html(); } } } diff --git a/tests/functional/mcp/mcp_test.php b/tests/functional/mcp/mcp_test.php index ff8dff4564..b2d8fd6cac 100644 --- a/tests/functional/mcp/mcp_test.php +++ b/tests/functional/mcp/mcp_test.php @@ -24,6 +24,7 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case // Browse MCP main page $crawler = self::request('GET', 'index.php'); $crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link()); + self::assert_response_html(); // Get all MCP module URLs array $mcp_modules = $crawler->filter('.tabs a')->each( @@ -32,12 +33,14 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case return $node->link(); } ); + $this->assertNotEmpty($mcp_modules); // Browse all MCP modules and get their mode URLs array $mcp_submodules = []; foreach ($mcp_modules as $module) { $crawler = self::$client->click($module); + self::assert_response_html(); $mcp_submodules = array_merge($mcp_submodules, $crawler->filter('.cp-menu a')->each( function ($node, $i) { @@ -45,11 +48,13 @@ class phpbb_functional_mcp_test extends phpbb_functional_test_case } )); } + $this->assertNotEmpty($mcp_submodules); // Browse all MCP submodules' modes foreach ($mcp_submodules as $mcp_submodule) { self::$client->click($mcp_submodule); + self::assert_response_html(); } } } From 4dd08747e3adc9706f30920f4e72077d4d66006c Mon Sep 17 00:00:00 2001 From: rxu Date: Mon, 6 Jan 2025 22:31:58 +0700 Subject: [PATCH 27/29] [ticket/17135] Fix ACP jabber module PHPBB-17135 --- phpBB/includes/acp/acp_jabber.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index c952275daa..fce1dee1df 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -32,6 +32,8 @@ class acp_jabber global $db, $user, $template, $phpbb_log, $request; global $config, $phpbb_container, $phpbb_root_path, $phpEx; + $jabber = $phpbb_container->get('messenger.method.jabber'); + $user->add_lang('acp/board'); $submit = (isset($_POST['submit'])) ? true : false; @@ -68,8 +70,6 @@ class acp_jabber $message = $user->lang['JAB_SETTINGS_CHANGED']; $log = 'JAB_SETTINGS_CHANGED'; - $jabber = $phpbb_container->get('messenger.method.jabber'); - // Is this feature enabled? Then try to establish a connection if ($jabber->is_enabled()) { From 3e0270d0cff96a9696211570528f521789913f00 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 7 Jan 2025 11:54:11 +0700 Subject: [PATCH 28/29] [ticket/17135] Optimize save_queue() method calls PHPBB-17135 --- phpBB/includes/acp/acp_email.php | 12 +++++++----- phpBB/includes/acp/acp_inactive.php | 14 +++++++++----- phpBB/includes/ucp/ucp_resend.php | 11 ++++++++--- .../phpbb/notification/method/messenger_base.php | 16 ++++++++++------ 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 446067c2a8..00ce89317c 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -265,16 +265,18 @@ class acp_email } $errored = !$messenger_method->send() || $errored; - if ($use_queue) - { - $messenger_method->save_queue(); - } } } } unset($email_list); - $messenger->save_queue(); + if ($use_queue) + { + foreach ($messenger_collection_iterator as $messenger_method) + { + $messenger_method->save_queue(); + } + } if ($generate_log_entry) { diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index ec74d59169..b9ff966b6d 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -194,15 +194,15 @@ class acp_inactive $result = $db->sql_query($sql); + /** @var \phpbb\di\service_collection */ + $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger_collection_iterator = $messenger->getIterator(); + if ($row = $db->sql_fetchrow($result)) { // Send the messages $usernames = $user_ids = array(); - /** @var \phpbb\di\service_collection */ - $messenger = $phpbb_container->get('messenger.method_collection'); - $messenger_collection_iterator = $messenger->getIterator(); - do { foreach ($messenger_collection_iterator as $messenger_method) @@ -219,7 +219,6 @@ class acp_inactive ]); $messenger_method->send(); - $messenger_method->save_queue(); } } @@ -242,6 +241,11 @@ class acp_inactive } $db->sql_freeresult($result); + foreach ($messenger_collection_iterator as $messenger_method) + { + $messenger_method->save_queue(); + } + // For remind we really need to redirect, else a refresh can result in more than one reminder $u_action = $this->u_action . "&$u_sort_param&start=$start"; $u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : ''; diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 4c9c1a86c6..76e748e85d 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -133,6 +133,8 @@ class ucp_resend WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); $result = $db->sql_query($sql); + /** @var \phpbb\di\service_collection */ + $messenger = $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); while ($row = $db->sql_fetchrow($result)) { @@ -151,13 +153,16 @@ class ucp_resend ]); $messenger_method->send(); - - // Save the queue in the messenger method class (has to be called or these messages could be lost) - $messenger_method->save_queue(); } } } $db->sql_freeresult($result); + + // Save the queue in the messenger method class (has to be called or these messages could be lost) + foreach ($messenger_collection_iterator as $messenger_method) + { + $messenger_method->save_queue(); + } } $this->update_activation_expiration(); diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index ca93f4c8a2..e4b97b7cac 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -86,7 +86,7 @@ abstract class messenger_base extends \phpbb\notification\method\base $user_ids[] = $notification->user_id; } - // We do not send emails to banned users + // We do not notify banned users if (!function_exists('phpbb_get_banned_user_ids')) { include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext); @@ -96,7 +96,9 @@ abstract class messenger_base extends \phpbb\notification\method\base // Load all the users we need $this->user_loader->load_users(array_diff($user_ids, $banned_users), array(USER_IGNORE)); - // Time to go through the queue and send emails + // Time to go through the queue and send notifications + $messenger_collection_iterator = $this->messenger->getIterator(); + /** @var type_interface $notification */ foreach ($this->queue as $notification) { @@ -112,7 +114,6 @@ abstract class messenger_base extends \phpbb\notification\method\base continue; } - $messenger_collection_iterator = $this->messenger->getIterator(); foreach ($messenger_collection_iterator as $messenger_method) { if ($messenger_method->get_id() == $notify_method || $notify_method == $messenger_method::NOTIFY_BOTH) @@ -125,13 +126,16 @@ abstract class messenger_base extends \phpbb\notification\method\base ], $notification->get_email_template_variables())); $messenger_method->send(); - - // Save the queue in the messenger method class (has to be called or these messages could be lost) - $messenger_method->save_queue(); } } } + // Save the queue in the messenger method class (has to be called or these messages could be lost) + foreach ($messenger_collection_iterator as $messenger_method) + { + $messenger_method->save_queue(); + } + // We're done, empty the queue $this->empty_queue(); } From a2f99248cb5550ac7641676457a8450c8d499d1a Mon Sep 17 00:00:00 2001 From: rxu Date: Wed, 8 Jan 2025 10:27:55 +0700 Subject: [PATCH 29/29] [ticket/17135] Optimize save_queue() method call for acp_inactive PHPBB-17135 --- phpBB/includes/acp/acp_inactive.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index b9ff966b6d..2436277e15 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -227,6 +227,11 @@ class acp_inactive } while ($row = $db->sql_fetchrow($result)); + foreach ($messenger_collection_iterator as $messenger_method) + { + $messenger_method->save_queue(); + } + // Add the remind state to the database and increase activation expiration by one day $sql = 'UPDATE ' . USERS_TABLE . ' SET user_reminded = user_reminded + 1, @@ -241,11 +246,6 @@ class acp_inactive } $db->sql_freeresult($result); - foreach ($messenger_collection_iterator as $messenger_method) - { - $messenger_method->save_queue(); - } - // For remind we really need to redirect, else a refresh can result in more than one reminder $u_action = $this->u_action . "&$u_sort_param&start=$start"; $u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : '';