diff options
Diffstat (limited to 'phpBB/includes/functions_messenger.php')
| -rw-r--r-- | phpBB/includes/functions_messenger.php | 301 |
1 files changed, 209 insertions, 92 deletions
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 98975b9d8f..ec297b536a 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -24,8 +24,9 @@ if (!defined('IN_PHPBB')) */ class messenger { - var $msg, $extra_headers, $replyto, $from, $subject; + var $msg, $replyto, $from, $subject; var $addresses = array(); + var $extra_headers = array(); var $mail_priority = MAIL_NORMAL_PRIORITY; var $use_queue = true; @@ -33,21 +34,15 @@ class messenger /** @var \phpbb\template\template */ protected $template; - var $eol = "\n"; - /** * Constructor */ - function messenger($use_queue = true) + function __construct($use_queue = true) { global $config; $this->use_queue = (!$config['email_package_size']) ? false : $use_queue; $this->subject = ''; - - // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) - $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; - $this->eol = (!$this->eol) ? "\n" : $this->eol; } /** @@ -90,7 +85,7 @@ class messenger return; } - $pos = isset($this->addresses['to']) ? sizeof($this->addresses['to']) : 0; + $pos = isset($this->addresses['to']) ? count($this->addresses['to']) : 0; $this->addresses['to'][$pos]['email'] = trim($address); @@ -115,7 +110,7 @@ class messenger return; } - $pos = isset($this->addresses['cc']) ? sizeof($this->addresses['cc']) : 0; + $pos = isset($this->addresses['cc']) ? count($this->addresses['cc']) : 0; $this->addresses['cc'][$pos]['email'] = trim($address); $this->addresses['cc'][$pos]['name'] = trim($realname); } @@ -130,7 +125,7 @@ class messenger return; } - $pos = isset($this->addresses['bcc']) ? sizeof($this->addresses['bcc']) : 0; + $pos = isset($this->addresses['bcc']) ? count($this->addresses['bcc']) : 0; $this->addresses['bcc'][$pos]['email'] = trim($address); $this->addresses['bcc'][$pos]['name'] = trim($realname); } @@ -146,7 +141,7 @@ class messenger return; } - $pos = isset($this->addresses['im']) ? sizeof($this->addresses['im']) : 0; + $pos = isset($this->addresses['im']) ? count($this->addresses['im']) : 0; $this->addresses['im'][$pos]['uid'] = trim($address); $this->addresses['im'][$pos]['name'] = trim($realname); } @@ -186,10 +181,9 @@ class messenger /** * Adds X-AntiAbuse headers * - * @param array $config Configuration array - * @param user $user A user object - * - * @return null + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object + * @return void */ function anti_abuse_headers($config, $user) { @@ -212,7 +206,7 @@ class messenger */ function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') { - global $config, $phpbb_root_path, $phpEx, $user, $phpbb_extension_manager; + global $config, $phpbb_root_path, $user; $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; @@ -331,9 +325,26 @@ class messenger )); $subject = $this->subject; - $message = $this->msg; + $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))); + + // Parse message through template + $message = trim($this->template->assign_display('body')); + /** - * Event to modify notification message text before parsing + * 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 @@ -343,19 +354,12 @@ class messenger * @var string message The message text * @since 3.1.11-RC1 */ - $vars = array( - 'method', - 'break', - 'subject', - 'message', - ); + $vars = array('method', 'break', 'subject', 'message'); extract($phpbb_dispatcher->trigger_event('core.modify_notification_message', compact($vars))); + $this->subject = $subject; $this->msg = $message; - unset($subject, $message); - - // Parse message through template - $this->msg = trim($this->template->assign_display('body')); + 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); @@ -374,6 +378,12 @@ class messenger $this->subject = (($this->subject != '') ? $this->subject : $user->lang['NO_EMAIL_SUBJECT']); } + if (preg_match('#^(List-Unsubscribe:(.*?))$#m', $this->msg, $match)) + { + $this->extra_headers[] = $match[1]; + $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); + } + if ($drop_header) { $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); @@ -409,7 +419,7 @@ class messenger */ function error($type, $msg) { - global $user, $phpEx, $phpbb_root_path, $config, $request; + global $user, $config, $request, $phpbb_log; // Session doesn't exist, create it if (!isset($user->session_id) || $user->session_id === '') @@ -419,11 +429,10 @@ class messenger $calling_page = htmlspecialchars_decode($request->server('PHP_SELF')); - $message = ''; switch ($type) { case 'EMAIL': - $message = '<strong>EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/' . $config['email_function_name'] . '()') . '</strong>'; + $message = '<strong>EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()') . '</strong>'; break; default: @@ -432,7 +441,7 @@ class messenger } $message .= '<br /><em>' . htmlspecialchars($calling_page) . '</em><br /><br />' . $msg . '<br />'; - add_log('critical', 'LOG_ERROR_' . $type, $message); + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_' . $type, false, array($message)); } /** @@ -510,7 +519,7 @@ class messenger $vars = array('headers'); extract($phpbb_dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - if (sizeof($this->extra_headers)) + if (count($this->extra_headers)) { $headers = array_merge($headers, $this->extra_headers); } @@ -523,7 +532,7 @@ class messenger */ function msg_email() { - global $config, $user; + global $config, $phpbb_dispatcher; if (empty($config['email_enable'])) { @@ -551,6 +560,33 @@ class messenger $contact_name = htmlspecialchars_decode($config['board_contact_name']); $board_contact = (($contact_name !== '') ? '"' . mail_encode($contact_name) . '" ' : '') . '<' . $config['board_contact'] . '>'; + $break = false; + $addresses = $this->addresses; + $subject = $this->subject; + $msg = $this->msg; + /** + * 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 + */ + $vars = array( + 'break', + 'addresses', + 'subject', + 'msg', + ); + extract($phpbb_dispatcher->trigger_event('core.notification_message_email', compact($vars))); + + if ($break) + { + return true; + } + if (empty($this->replyto)) { $this->replyto = $board_contact; @@ -561,7 +597,7 @@ class messenger $this->from = $board_contact; } - $encode_eol = ($config['smtp_delivery']) ? "\r\n" : $this->eol; + $encode_eol = ($config['smtp_delivery']) ? "\r\n" : PHP_EOL; // Build to, cc and bcc strings $to = $cc = $bcc = ''; @@ -593,7 +629,7 @@ class messenger } else { - $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg); + $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, PHP_EOL, $err_msg); } if (!$result) @@ -621,7 +657,7 @@ class messenger */ function msg_jabber() { - global $config, $db, $user, $phpbb_root_path, $phpEx; + global $config, $user, $phpbb_root_path, $phpEx; if (empty($config['jab_enable']) || empty($config['jab_host']) || empty($config['jab_username']) || empty($config['jab_password'])) { @@ -693,14 +729,37 @@ class messenger */ protected function setup_template() { - global $config, $phpbb_path_helper, $user, $phpbb_extension_manager; + global $phpbb_container, $phpbb_dispatcher; if ($this->template instanceof \phpbb\template\template) { return; } - $this->template = new \phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new \phpbb\template\context(), $phpbb_extension_manager); + $template_environment = new \phpbb\template\twig\environment( + $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( + $phpbb_container->get('filesystem') + ), + $phpbb_dispatcher, + array() + ); + $template_environment->setLexer($phpbb_container->get('template.twig.lexer')); + + $this->template = new \phpbb\template\twig\twig( + $phpbb_container->get('path_helper'), + $phpbb_container->get('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') + ); } /** @@ -726,18 +785,20 @@ class queue var $eol = "\n"; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * constructor */ - function queue() + function __construct() { - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_filesystem, $phpbb_container; $this->data = array(); - $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; - - // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) - $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; - $this->eol = (!$this->eol) ? "\n" : $this->eol; + $this->cache_file = $phpbb_container->getParameter('core.cache_dir') . "queue.$phpEx"; + $this->filesystem = $phpbb_filesystem; } /** @@ -764,7 +825,7 @@ class queue */ function process() { - global $db, $config, $phpEx, $phpbb_root_path, $user; + global $config, $phpEx, $phpbb_root_path, $user, $phpbb_dispatcher; $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); @@ -775,14 +836,14 @@ class queue { if (!$have_cache_file) { - set_config('last_queue_run', time(), true); + $config->set('last_queue_run', time(), false); } $lock->release(); return; } - set_config('last_queue_run', time(), true); + $config->set('last_queue_run', time(), false); include($this->cache_file); @@ -796,7 +857,7 @@ class queue } $package_size = $data_ary['package_size']; - $num_items = (!$package_size || sizeof($data_ary['data']) < $package_size) ? sizeof($data_ary['data']) : $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. @@ -805,9 +866,9 @@ class queue * 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 (sizeof($data_ary['data']) > $package_size * 2.5) + if (count($data_ary['data']) > $package_size * 2.5) { - $num_items = sizeof($data_ary['data']); + $num_items = count($data_ary['data']); } */ @@ -861,23 +922,45 @@ class queue switch ($object) { case 'email': - $err_msg = ''; - $to = (!$to) ? 'undisclosed-recipients:;' : $to; - - if ($config['smtp_delivery']) - { - $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); - } - else + $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( + 'break', + 'addresses', + 'subject', + 'msg', + ); + extract($phpbb_dispatcher->trigger_event('core.notification_message_process', compact($vars))); + + if (!$break) { - $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg); - } + $err_msg = ''; + $to = (!$to) ? 'undisclosed-recipients:;' : $to; - if (!$result) - { - $messenger = new messenger(); - $messenger->error('EMAIL', $err_msg); - continue 2; + if ($config['smtp_delivery']) + { + $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); + } + else + { + $result = phpbb_mail($to, $subject, $msg, $headers, PHP_EOL, $err_msg); + } + + if (!$result) + { + $messenger = new messenger(); + $messenger->error('EMAIL', $err_msg); + continue 2; + } } break; @@ -896,7 +979,7 @@ class queue } // No more data for this object? Unset it - if (!sizeof($this->queue_data[$object]['data'])) + if (!count($this->queue_data[$object]['data'])) { unset($this->queue_data[$object]); } @@ -912,7 +995,7 @@ class queue } } - if (!sizeof($this->queue_data)) + if (!count($this->queue_data)) { @unlink($this->cache_file); } @@ -928,7 +1011,14 @@ class queue @opcache_invalidate($this->cache_file); } - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -940,7 +1030,7 @@ class queue */ function save() { - if (!sizeof($this->data)) + if (!count($this->data)) { return; } @@ -954,7 +1044,7 @@ class queue foreach ($this->queue_data as $object => $data_ary) { - if (isset($this->data[$object]) && sizeof($this->data[$object])) + if (isset($this->data[$object]) && count($this->data[$object])) { $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']); } @@ -975,7 +1065,14 @@ class queue @opcache_invalidate($this->cache_file); } - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } $this->data = array(); } @@ -1035,7 +1132,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = 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']) && sizeof($addresses['to'])) + if (isset($addresses['to']) && count($addresses['to'])) { foreach ($addresses['to'] as $which_ary) { @@ -1044,7 +1141,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) } } - if (isset($addresses['bcc']) && sizeof($addresses['bcc'])) + if (isset($addresses['bcc']) && count($addresses['bcc'])) { foreach ($addresses['bcc'] as $which_ary) { @@ -1052,7 +1149,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) } } - if (isset($addresses['cc']) && sizeof($addresses['cc'])) + if (isset($addresses['cc']) && count($addresses['cc'])) { foreach ($addresses['cc'] as $which_ary) { @@ -1231,7 +1328,7 @@ class smtp_class var $backtrace = false; var $backtrace_log = array(); - function smtp_class() + function __construct() { // Always create a backtrace for admins to identify SMTP problems $this->backtrace = true; @@ -1314,8 +1411,6 @@ class smtp_class { global $user; - $err_msg = ''; - // Here we try to determine the *real* hostname (reverse DNS entry preferrably) $local_host = $user->host; @@ -1350,7 +1445,7 @@ class smtp_class $this->server_send("QUIT"); fclose($this->socket); - $result = $this->pop_before_smtp($hostname, $username, $password); + $this->pop_before_smtp($hostname, $username, $password); $username = $password = $default_auth_method = ''; // We need to close the previous session, else the server is not @@ -1486,6 +1581,14 @@ class smtp_class */ 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; @@ -1508,7 +1611,9 @@ class smtp_class if (socket_set_blocking($this->socket, 1)) { - $result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + // 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']); } @@ -1772,11 +1877,11 @@ function mail_encode($str, $eol = "\r\n") $array = utf8_str_split($str); $str = ''; - while (sizeof($array)) + while (count($array)) { $text = ''; - while (sizeof($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length) + while (count($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length) { $text .= array_shift($array); } @@ -1788,14 +1893,21 @@ function mail_encode($str, $eol = "\r\n") } /** -* Wrapper for sending out emails with the PHP's mail function -*/ + * 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; - // 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 + // 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')) @@ -1806,10 +1918,15 @@ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) $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) - $result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers); + /** + * 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'] : ''; + + $result = mail($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers, $additional_parameters); $collector->uninstall(); $err_msg = $collector->format_errors(); |
