Switching to Symfony Mailer (#629)

* Switching to Symfony Mailer

Additionally, support for all versions of PHP below 7.4 has been withdrawn

* Language variable for reply to

* Update to PHP 7.4
This commit is contained in:
Yury Pikhtarev 2023-03-20 01:26:26 +07:00 committed by GitHub
commit faf2306862
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1450 additions and 584 deletions

View file

@ -31,7 +31,7 @@ and go from there. The documentation will be translated into english in the near
* Apache / nginx * Apache / nginx
* MySQL 5.5.3 or above / MariaDB 10.0 or above / Percona * MySQL 5.5.3 or above / MariaDB 10.0 or above / Percona
* PHP: 7.1 / 7.2 / 7.3 / 7.4 * PHP: 7.4 / 8.0 / 8.1 / 8.2
* PHP Extensions: bcmath, intl, tidy (optional), xml, xmlwriter * PHP Extensions: bcmath, intl, tidy (optional), xml, xmlwriter
## Installation ## Installation

View file

@ -20,9 +20,10 @@ if (!$bb_cfg['emailer']['enabled']) {
set_time_limit(1200); set_time_limit(1200);
$subject = (string)trim(request_var('subject', '')); $subject = trim(request_var('subject', ''));
$message = (string)request_var('message', ''); $message = (string)request_var('message', '');
$group_id = (int)request_var(POST_GROUPS_URL, 0); $group_id = (int)request_var(POST_GROUPS_URL, 0);
$reply_to = (string)request_var('reply_to', $bb_cfg['board_email']);
$message_type = (string)request_var('message_type', ''); $message_type = (string)request_var('message_type', '');
$errors = $user_id_sql = []; $errors = $user_id_sql = [];
@ -66,12 +67,12 @@ if (isset($_POST['submit'])) {
} }
foreach ($user_list as $i => $row) { foreach ($user_list as $i => $row) {
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($row['user_email'], $row['username']);
$emailer->set_to([$row['user_email'] => $row['username']]);
$emailer->set_subject($subject); $emailer->set_subject($subject);
$emailer->set_reply($reply_to);
$emailer->set_template('admin_send_email'); $emailer->set_template('admin_send_email');
$emailer->assign_vars(array( $emailer->assign_vars(array(
@ -101,6 +102,7 @@ foreach (DB()->fetch_rowset($sql) as $row) {
$template->assign_vars(array( $template->assign_vars(array(
'MESSAGE' => $message, 'MESSAGE' => $message,
'SUBJECT' => $subject, 'SUBJECT' => $subject,
'REPLY_TO' => $reply_to,
'ERROR_MESSAGE' => $errors ? implode('<br />', array_unique($errors)) : '', 'ERROR_MESSAGE' => $errors ? implode('<br />', array_unique($errors)) : '',

View file

@ -7,6 +7,8 @@
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License * @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/ */
use TorrentPier\Env;
if (isset($_REQUEST['GLOBALS'])) { if (isset($_REQUEST['GLOBALS'])) {
die(); die();
} }
@ -51,7 +53,7 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/vendor/autoload.php';
/** /**
* Gets the value of an environment variable. Supports boolean, empty and null. * Gets the value of an environment variable.
* *
* @param string $key * @param string $key
* @param mixed $default * @param mixed $default
@ -59,38 +61,12 @@ require_once __DIR__ . '/vendor/autoload.php';
*/ */
function env($key, $default = null) function env($key, $default = null)
{ {
$value = getenv($key); return Env::get($key, $default);
if (!$value) return value($default);
switch (strtolower($value)) {
case 'true':
case '(true)':
return true;
case 'false':
case '(false)':
return false;
case '(null)':
return null;
case '(empty)':
return '';
}
return $value;
}
/**
* Return the default value of the given value.
*
* @param mixed $value
* @return mixed
*/
function value($value)
{
return $value instanceof Closure ? $value() : $value;
} }
// Get initial config // Get initial config
if (!getenv('APP_DEBUG') && file_exists(__DIR__ . '/.env')) { $dotenv = Dotenv\Dotenv::createMutable(__DIR__);
(new Symfony\Component\Dotenv\Dotenv())->load(__DIR__ . '/.env'); $dotenv->safeLoad();
}
require_once __DIR__ . '/library/config.php'; require_once __DIR__ . '/library/config.php';
// Local config // Local config

View file

@ -17,16 +17,6 @@
"homepage": "https://github.com/Exileum", "homepage": "https://github.com/Exileum",
"role": "Developer" "role": "Developer"
}, },
{
"name": "Diolektor",
"homepage": "https://github.com/VasyOk",
"role": "Developer"
},
{
"name": "PheRum",
"homepage": "https://github.com/PheRum",
"role": "Developer"
},
{ {
"name": "belomaxorka", "name": "belomaxorka",
"email": "roman25052006.kelesh@gmail.com", "email": "roman25052006.kelesh@gmail.com",
@ -37,28 +27,27 @@
"support": { "support": {
"email": "support@torrentpier.com", "email": "support@torrentpier.com",
"issues": "https://github.com/torrentpier/torrentpier/issues", "issues": "https://github.com/torrentpier/torrentpier/issues",
"forum": "https://torrentpier.com", "forum": "https://torrentpier.com"
"docs": "https://docs.torrentpier.com/"
}, },
"require": { "require": {
"php": "^7.1.3", "php": "^7.4",
"bugsnag/bugsnag": "v3.29.0", "bugsnag/bugsnag": "v3.29.0",
"egulias/email-validator": "2.*", "egulias/email-validator": "^3.2",
"filp/whoops": "2.15.1", "filp/whoops": "^2.15",
"gigablah/sphinxphp": "2.0.8", "gigablah/sphinxphp": "2.0.8",
"google/recaptcha": "1.2.4", "google/recaptcha": "^1.2",
"guzzlehttp/guzzle": "6.*", "guzzlehttp/guzzle": "^7.5",
"guzzlehttp/psr7": "1.*", "guzzlehttp/psr7": "^2.4",
"longman/ip-tools": "1.2.1", "longman/ip-tools": "1.2.1",
"monolog/monolog": "1.*", "monolog/monolog": "^2.9",
"rych/bencode": "v1.0.0", "rych/bencode": "v1.0.0",
"samdark/sitemap": "2.4.0", "samdark/sitemap": "2.4.0",
"swiftmailer/swiftmailer": "v6.3.0", "symfony/mailer": "^5.4",
"symfony/dotenv": "4.*", "symfony/polyfill": "v1.27.0",
"symfony/polyfill": "v1.27.0" "vlucas/phpdotenv": "^5.5"
}, },
"require-dev": { "require-dev": {
"symfony/var-dumper": "4.*" "symfony/var-dumper": "^5.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

1137
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -168,11 +168,10 @@ if (!$group_id) {
\TorrentPier\Legacy\Group::add_user_into_group($group_id, $userdata['user_id'], 1, TIMENOW); \TorrentPier\Legacy\Group::add_user_into_group($group_id, $userdata['user_id'], 1, TIMENOW);
if ($bb_cfg['group_send_email']) { if ($bb_cfg['group_send_email']) {
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($moderator['user_email'], $moderator['username']);
$emailer->set_to([$moderator['user_email'] => $moderator['username']]);
$emailer->set_subject($lang['EMAILER_SUBJECT']['GROUP_REQUEST']); $emailer->set_subject($lang['EMAILER_SUBJECT']['GROUP_REQUEST']);
$emailer->set_template('group_request', $moderator['user_lang']); $emailer->set_template('group_request', $moderator['user_lang']);
@ -210,11 +209,10 @@ if (!$group_id) {
\TorrentPier\Legacy\Group::add_user_into_group($group_id, $row['user_id']); \TorrentPier\Legacy\Group::add_user_into_group($group_id, $row['user_id']);
if ($bb_cfg['group_send_email']) { if ($bb_cfg['group_send_email']) {
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($row['user_email'], $row['username']);
$emailer->set_to([$row['user_email'] => $row['username']]);
$emailer->set_subject($lang['EMAILER_SUBJECT']['GROUP_ADDED']); $emailer->set_subject($lang['EMAILER_SUBJECT']['GROUP_ADDED']);
$emailer->set_template('group_added', $row['user_lang']); $emailer->set_template('group_added', $row['user_lang']);
@ -269,11 +267,10 @@ if (!$group_id) {
} }
foreach (DB()->fetch_rowset($sql_select) as $row) { foreach (DB()->fetch_rowset($sql_select) as $row) {
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($row['user_email'], $row['username']);
$emailer->set_to([$row['user_email'] => $row['username']]);
$emailer->set_subject($lang['EMAILER_SUBJECT']['GROUP_APPROVED']); $emailer->set_subject($lang['EMAILER_SUBJECT']['GROUP_APPROVED']);
$emailer->set_template('group_approved', $row['user_lang']); $emailer->set_template('group_approved', $row['user_lang']);

View file

@ -14,7 +14,7 @@ if (!defined('IN_AJAX')) {
global $bf, $lang; global $bf, $lang;
$user_id = (int)$this->request['user_id']; $user_id = (int)$this->request['user_id'];
$new_opt = json_decode($this->request['user_opt'], true); $new_opt = json_decode($this->request['user_opt'], true, 512, JSON_THROW_ON_ERROR);
if (!$user_id or !$u_data = get_userdata($user_id)) { if (!$user_id or !$u_data = get_userdata($user_id)) {
$this->ajax_die($lang['NO_USER_ID_SPECIFIED']); $this->ajax_die($lang['NO_USER_ID_SPECIFIED']);

View file

@ -55,7 +55,7 @@ function base64_unpack($string)
for ($i = 1; $i <= $length; $i++) { for ($i = 1; $i <= $length; $i++) {
$pos = $length - $i; $pos = $length - $i;
$operand = strpos($chars, $string[$pos]); $operand = strpos($chars, (string) $string[$pos]);
$exponent = $base ** ($i - 1); $exponent = $base ** ($i - 1);
$decValue = $operand * $exponent; $decValue = $operand * $exponent;
$number += $decValue; $number += $decValue;

View file

@ -377,7 +377,7 @@ $bb_cfg['emailer'] = [
'enabled' => true, 'enabled' => true,
'smtp' => [ 'smtp' => [
'enabled' => false, // send email via external SMTP server 'enabled' => false, // send email via external SMTP server
'host' => '', // SMTP server host 'host' => 'localhost', // SMTP server host
'port' => 25, // SMTP server port 'port' => 25, // SMTP server port
'username' => '', // SMTP username (if server requires it) 'username' => '', // SMTP username (if server requires it)
'password' => '', // SMTP password (if server requires it) 'password' => '', // SMTP password (if server requires it)

View file

@ -21,14 +21,14 @@ function get_path_from_id($id, $ext_id, $base_path, $first_div, $sec_div)
function get_avatar_path($id, $ext_id, $base_path = null, $first_div = 10000, $sec_div = 100) function get_avatar_path($id, $ext_id, $base_path = null, $first_div = 10000, $sec_div = 100)
{ {
global $bb_cfg; global $bb_cfg;
$base_path = $base_path ?? $bb_cfg['avatars']['upload_path']; $base_path ??= $bb_cfg['avatars']['upload_path'];
return get_path_from_id($id, $ext_id, $base_path, $first_div, $sec_div); return get_path_from_id($id, $ext_id, $base_path, $first_div, $sec_div);
} }
function get_attach_path($id, $ext_id = '', $base_path = null, $first_div = 10000, $sec_div = 100) function get_attach_path($id, $ext_id = '', $base_path = null, $first_div = 10000, $sec_div = 100)
{ {
global $bb_cfg; global $bb_cfg;
$base_path = $base_path ?? $bb_cfg['attach']['upload_path']; $base_path ??= $bb_cfg['attach']['upload_path'];
return get_path_from_id($id, $ext_id, $base_path, $first_div, $sec_div); return get_path_from_id($id, $ext_id, $base_path, $first_div, $sec_div);
} }
@ -762,7 +762,7 @@ function str_short($text, $max_length, $space = ' ')
if ($max_length && mb_strlen($text, 'UTF-8') > $max_length) { if ($max_length && mb_strlen($text, 'UTF-8') > $max_length) {
$text = mb_substr($text, 0, $max_length, 'UTF-8'); $text = mb_substr($text, 0, $max_length, 'UTF-8');
if ($last_space_pos = $max_length - (int)strpos(strrev($text), $space)) { if ($last_space_pos = $max_length - (int)strpos(strrev($text), (string) $space)) {
if ($last_space_pos > round($max_length * 3 / 4)) { if ($last_space_pos > round($max_length * 3 / 4)) {
$last_space_pos--; $last_space_pos--;
$text = mb_substr($text, 0, $last_space_pos, 'UTF-8'); $text = mb_substr($text, 0, $last_space_pos, 'UTF-8');
@ -1559,7 +1559,7 @@ function get_topic_icon($topic, $is_unread = null)
global $bb_cfg, $images; global $bb_cfg, $images;
$t_hot = ($topic['topic_replies'] >= $bb_cfg['hot_threshold']); $t_hot = ($topic['topic_replies'] >= $bb_cfg['hot_threshold']);
$is_unread = $is_unread ?? is_unread($topic['topic_last_post_time'], $topic['topic_id'], $topic['forum_id']); $is_unread ??= is_unread($topic['topic_last_post_time'], $topic['topic_id'], $topic['forum_id']);
if ($topic['topic_status'] == TOPIC_MOVED) { if ($topic['topic_status'] == TOPIC_MOVED) {
$folder_image = $images['folder']; $folder_image = $images['folder'];
@ -1638,7 +1638,7 @@ function get_poll_data_items_js($topic_id)
$items[$row['topic_id']][$row['vote_id']] = array($opt_text_for_js, $opt_result_for_js); $items[$row['topic_id']][$row['vote_id']] = array($opt_text_for_js, $opt_result_for_js);
} }
foreach ($items as $k => $v) { foreach ($items as $k => $v) {
$items[$k] = json_encode($v); $items[$k] = json_encode($v, JSON_THROW_ON_ERROR);
} }
return is_array($topic_id) ? $items : $items[$topic_id]; return is_array($topic_id) ? $items : $items[$topic_id];

View file

@ -14,8 +14,8 @@ if (!defined('BB_ROOT')) {
/** /**
* Check PHP version * Check PHP version
*/ */
if (PHP_VERSION_ID < 70103) { if (PHP_VERSION_ID < 70400) {
die('TorrentPier requires PHP version 7.1.3+. Your PHP version ' . PHP_VERSION); die('TorrentPier requires PHP version 7.4+. Your PHP version ' . PHP_VERSION);
} }
/** /**
@ -88,10 +88,16 @@ define('COOKIE_MAX_TRACKS', 90);
* @param bool $httponly * @param bool $httponly
* @return bool * @return bool
*/ */
function bb_setcookie($name, $val, $lifetime = COOKIE_PERSIST, $httponly = false) function bb_setcookie($name, $val, int $lifetime = COOKIE_PERSIST, bool $httponly = false)
{ {
global $bb_cfg; global $bb_cfg;
return setcookie($name, $val, $lifetime, $bb_cfg['script_path'], $bb_cfg['cookie_domain'], $bb_cfg['cookie_secure'], $httponly); return setcookie($name, $val, [
'expires' => $lifetime,
'path' => $bb_cfg['script_path'],
'domain' => $bb_cfg['cookie_domain'],
'secure' => $bb_cfg['cookie_secure'],
'httponly' => $httponly,
]);
} }
/** /**

View file

@ -119,7 +119,7 @@ $template->assign_vars(array(
'USER_LANG' => $userdata['user_lang'], 'USER_LANG' => $userdata['user_lang'],
'INCLUDE_BBCODE_JS' => !empty($page_cfg['include_bbcode_js']), 'INCLUDE_BBCODE_JS' => !empty($page_cfg['include_bbcode_js']),
'USER_OPTIONS_JS' => (IS_GUEST) ? '{}' : json_encode($user->opt_js), 'USER_OPTIONS_JS' => (IS_GUEST) ? '{}' : json_encode($user->opt_js, JSON_THROW_ON_ERROR),
'USE_TABLESORTER' => !empty($page_cfg['use_tablesorter']), 'USE_TABLESORTER' => !empty($page_cfg['use_tablesorter']),

View file

@ -53,11 +53,10 @@ if ($row = DB()->fetch_row($sql)) {
} }
if (!$errors) { if (!$errors) {
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$userdata['user_email'] => $userdata['username']]); $emailer->set_to($user_email, $username);
$emailer->set_to([$user_email => $username]);
$emailer->set_subject($subject); $emailer->set_subject($subject);
$emailer->set_template('profile_send_email', $user_lang); $emailer->set_template('profile_send_email', $user_lang);

View file

@ -568,11 +568,10 @@ if ($submit && !$errors) {
$email_template = 'user_welcome'; $email_template = 'user_welcome';
} }
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($email, $username);
$emailer->set_to([$email => $username]);
$emailer->set_subject($email_subject); $emailer->set_subject($email_subject);
$emailer->set_template($email_template, $user_lang); $emailer->set_template($email_template, $user_lang);
@ -601,11 +600,10 @@ if ($submit && !$errors) {
$pr_data['user_actkey'] = $user_actkey; $pr_data['user_actkey'] = $user_actkey;
$db_data['user_actkey'] = $user_actkey; $db_data['user_actkey'] = $user_actkey;
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($email, $username);
$emailer->set_to([$email => $username]);
$emailer->set_subject($lang['EMAILER_SUBJECT']['USER_ACTIVATE']); $emailer->set_subject($lang['EMAILER_SUBJECT']['USER_ACTIVATE']);
$emailer->set_template('user_activate', $pr_data['user_lang']); $emailer->set_template('user_activate', $pr_data['user_lang']);

View file

@ -47,11 +47,10 @@ if (isset($_POST['submit'])) {
bb_die('Could not update new password information'); bb_die('Could not update new password information');
} }
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($row['user_email'], $username);
$emailer->set_to([$row['user_email'] => $username]);
$emailer->set_subject($lang['EMAILER_SUBJECT']['USER_ACTIVATE_PASSWD']); $emailer->set_subject($lang['EMAILER_SUBJECT']['USER_ACTIVATE_PASSWD']);
$emailer->set_template('user_activate_passwd', $row['user_lang']); $emailer->set_template('user_activate_passwd', $row['user_lang']);

View file

@ -184,7 +184,7 @@ if (IS_ADMIN) {
'dis_post' => bf($profiledata['user_opt'], 'user_opt', 'dis_post'), 'dis_post' => bf($profiledata['user_opt'], 'user_opt', 'dis_post'),
'dis_post_edit' => bf($profiledata['user_opt'], 'user_opt', 'dis_post_edit'), 'dis_post_edit' => bf($profiledata['user_opt'], 'user_opt', 'dis_post_edit'),
'dis_topic' => bf($profiledata['user_opt'], 'user_opt', 'dis_topic'), 'dis_topic' => bf($profiledata['user_opt'], 'user_opt', 'dis_topic'),
)); ), JSON_THROW_ON_ERROR);
$template->assign_vars(array( $template->assign_vars(array(
'EDITABLE_TPLS' => true, 'EDITABLE_TPLS' => true,

View file

@ -2809,6 +2809,7 @@ $lang['CAPTCHA_WRONG'] = 'You could not confirm that you are not a robot';
$lang['CAPTCHA_SETTINGS'] = '<h2>ReCaptcha not being fully configured</h2><p>If you haven\'t already generated the keys, you can do it on <a href="https://www.google.com/recaptcha/admin">https://www.google.com/recaptcha/admin</a>.<br />After you generate the keys, you need to put them at the file library/config.php.</p>'; $lang['CAPTCHA_SETTINGS'] = '<h2>ReCaptcha not being fully configured</h2><p>If you haven\'t already generated the keys, you can do it on <a href="https://www.google.com/recaptcha/admin">https://www.google.com/recaptcha/admin</a>.<br />After you generate the keys, you need to put them at the file library/config.php.</p>';
// Sending email // Sending email
$lang['REPLY_TO'] = 'Reply to';
$lang['EMAILER_SUBJECT'] = [ $lang['EMAILER_SUBJECT'] = [
'EMPTY' => 'No subject', 'EMPTY' => 'No subject',
'GROUP_ADDED' => 'You have been added to the user group', 'GROUP_ADDED' => 'You have been added to the user group',

View file

@ -898,11 +898,10 @@ if ($mode == 'read') {
\TorrentPier\Legacy\Sessions::cache_rm_user_sessions($to_userdata['user_id']); \TorrentPier\Legacy\Sessions::cache_rm_user_sessions($to_userdata['user_id']);
if (bf($to_userdata['user_opt'], 'user_opt', 'user_notify_pm') && $to_userdata['user_active'] && $bb_cfg['pm_notify_enabled']) { if (bf($to_userdata['user_opt'], 'user_opt', 'user_notify_pm') && $to_userdata['user_active'] && $bb_cfg['pm_notify_enabled']) {
/** @var TorrentPier\Legacy\Emailer() $emailer */ // Sending email
$emailer = new TorrentPier\Legacy\Emailer(); $emailer = new TorrentPier\Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($to_userdata['user_email'], $to_userdata['username']);
$emailer->set_to([$to_userdata['user_email'] => $to_userdata['username']]);
$emailer->set_subject($lang['EMAILER_SUBJECT']['PRIVMSG_NOTIFY']); $emailer->set_subject($lang['EMAILER_SUBJECT']['PRIVMSG_NOTIFY']);
$emailer->set_template('privmsg_notify', $to_userdata['user_lang']); $emailer->set_template('privmsg_notify', $to_userdata['user_lang']);

215
src/Emailer.php Normal file
View file

@ -0,0 +1,215 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2023 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
namespace TorrentPier;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport\SendmailTransport;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
class Emailer
{
/** @var string message text */
private $message;
/** @var string message subject */
private $subject;
private ?\Symfony\Component\Mime\Address $to = null;
private ?\Symfony\Component\Mime\Address $reply = null;
/** @var array message template with the language */
private array $tpl_msg = [];
/** @var array variables to be substituted in message templates */
private $vars = [];
/**
* Setting the message subject
*
* @param string $subject
*
* @return void
*/
public function set_subject(string $subject)
{
$this->subject = $subject;
}
/**
* Set recipient address
*
* @param string $email recipient address
* @param string $name recipient name
*
* @return void
*/
public function set_to(string $email, string $name)
{
$this->to = new Address($email, $name);
}
/**
* Setting an address for the response
*
* @param string $email recipient address
*
* @return void
*/
public function set_reply(string $email)
{
$this->reply = new Address($email);
}
/**
* Setting the message template
*
* @param string $template_file
* @param string $template_lang
*
* @return void
*/
public function set_template(string $template_file, string $template_lang = '')
{
global $bb_cfg;
if (!$template_lang) {
$template_lang = $bb_cfg['default_lang'];
}
if (empty($this->tpl_msg[$template_lang . $template_file])) {
$tpl_file = LANG_ROOT_DIR . '/' . $template_lang . '/email/' . $template_file . '.html';
if (!file_exists($tpl_file)) {
$tpl_file = LANG_ROOT_DIR . '/' . $bb_cfg['default_lang'] . '/email/' . $template_file . '.html';
if (!file_exists($tpl_file)) {
bb_die('Could not find email template file: ' . $template_file);
}
}
if (!$fd = fopen($tpl_file, 'rb')) {
bb_die('Failed opening email template file: ' . $tpl_file);
}
$this->tpl_msg[$template_lang . $template_file] = fread($fd, filesize($tpl_file));
fclose($fd);
}
$this->message = $this->tpl_msg[$template_lang . $template_file];
}
/**
* Sending a message to recipients via Symfony Mailer
*
* @param string $email_format
*
* @return bool
*/
public function send(string $email_format = 'text/plain'): bool
{
global $bb_cfg, $lang;
if (!$bb_cfg['emailer']['enabled']) {
return false;
}
/** Replace vars and prepare message */
$this->message = preg_replace('#\{([a-z0-9\-_]*?)}#is', "$\\1", $this->message);
foreach ($this->vars as $key => $val) {
$this->message = preg_replace(sprintf('/\$\{?%s\}?/', $key), $val, $this->message);
}
$this->message = trim($this->message);
/** Set some variables */
$this->subject = !empty($this->subject) ? $this->subject : $lang['EMAILER_SUBJECT']['EMPTY'];
/** Prepare message */
if ($bb_cfg['emailer']['smtp']['enabled']) {
if (!empty($bb_cfg['emailer']['smtp']['host'])) {
if (empty($bb_cfg['emailer']['ssl_type'])) {
/** @var EsmtpTransport $transport external SMTP without SSL */
$transport = (new EsmtpTransport(
$bb_cfg['emailer']['smtp']['host'],
$bb_cfg['emailer']['smtp']['port']
))
->setUsername($bb_cfg['emailer']['smtp']['username'])
->setPassword($bb_cfg['emailer']['smtp']['password']);
} else {
/** @var EsmtpTransport $transport external SMTP with SSL */
$transport = (new EsmtpTransport(
$bb_cfg['emailer']['smtp']['host'],
$bb_cfg['emailer']['smtp']['port'],
$bb_cfg['emailer']['ssl_type']
))
->setUsername($bb_cfg['emailer']['smtp']['username'])
->setPassword($bb_cfg['emailer']['smtp']['password']);
}
} else {
$transport = new EsmtpTransport('localhost', 25);
}
} else {
$transport = new SendmailTransport('/usr/sbin/sendmail -bs');
}
$mailer = new Mailer($transport);
/** @var Email $message */
$message = (new Email())
->subject($this->subject)
->to($this->to)
->from(new Address($bb_cfg['board_email'], $bb_cfg['board_email_sitename']))
->returnPath(new Address($bb_cfg['bounce_email']))
->replyTo($this->reply ?? new Address($bb_cfg['board_email']));
/**
* This non-standard header tells compliant autoresponders ("email holiday mode") to not
* reply to this message because it's an automated email
*/
$message->getHeaders()
->addTextHeader('X-Auto-Response-Suppress', 'OOF, DR, RN, NRN, AutoReply');
if ($email_format == 'text/html') {
$message->html($this->message);
} else {
$message->text($this->message);
}
/** Send message */
try {
$mailer->send($message);
} catch (TransportExceptionInterface $e) {
bb_die('Failed sending email: ' . $e);
}
return true;
}
/**
* Set message template variables
*
* @param $vars
*
* @return void
*/
public function assign_vars($vars)
{
global $bb_cfg;
$this->vars = array_merge([
'BOARD_EMAIL' => $bb_cfg['board_email'],
'SITENAME' => $bb_cfg['board_email_sitename'],
'EMAIL_SIG' => !empty($bb_cfg['board_email_sig']) ? "-- \n{$bb_cfg['board_email_sig']}" : '',
], $vars);
}
}

101
src/Env.php Normal file
View file

@ -0,0 +1,101 @@
<?php
namespace TorrentPier;
use Dotenv\Repository\Adapter\PutenvAdapter;
use Dotenv\Repository\RepositoryBuilder;
use PhpOption\Option;
class Env
{
/**
* Indicates if the putenv adapter is enabled.
*
* @var bool
*/
protected static $putenv = true;
/**
* The environment repository instance.
*
* @var \Dotenv\Repository\RepositoryInterface|null
*/
protected static $repository;
/**
* Enable the putenv adapter.
*
* @return void
*/
public static function enablePutenv()
{
static::$putenv = true;
static::$repository = null;
}
/**
* Disable the putenv adapter.
*
* @return void
*/
public static function disablePutenv()
{
static::$putenv = false;
static::$repository = null;
}
/**
* Get the environment repository instance.
*
* @return \Dotenv\Repository\RepositoryInterface
*/
public static function getRepository()
{
if (static::$repository === null) {
$builder = RepositoryBuilder::createWithDefaultAdapters();
if (static::$putenv) {
$builder = $builder->addAdapter(PutenvAdapter::class);
}
static::$repository = $builder->immutable()->make();
}
return static::$repository;
}
/**
* Gets the value of an environment variable.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function get($key, $default = null)
{
return Option::fromValue(static::getRepository()->get($key))
->map(function ($value) {
switch (strtolower($value)) {
case 'true':
case '(true)':
return true;
case 'false':
case '(false)':
return false;
case 'empty':
case '(empty)':
return '';
case 'null':
case '(null)':
return null;
}
if (preg_match('/\A([\'"])(.*)\1\z/', $value, $matches)) {
return $matches[2];
}
return $value;
})
->getOrCall(fn () => value($default));
}
}

View file

@ -195,7 +195,7 @@ class Ajax
} }
} }
$response_js = json_encode($this->response); $response_js = json_encode($this->response, JSON_THROW_ON_ERROR);
if (GZIP_OUTPUT_ALLOWED && !\defined('NO_GZIP')) { if (GZIP_OUTPUT_ALLOWED && !\defined('NO_GZIP')) {
if (UA_GZIP_SUPPORTED && \strlen($response_js) > 2000) { if (UA_GZIP_SUPPORTED && \strlen($response_js) > 2000) {

View file

@ -247,7 +247,7 @@ class Attach
} }
} }
$this->num_attachments = is_array($this->attachment_list) || $this->attachment_list instanceof \Countable ? \count($this->attachment_list) : 0; $this->num_attachments = is_countable($this->attachment_list) ? \count($this->attachment_list) : 0;
if ($submit) { if ($submit) {
if ($mode === 'newtopic' || $mode === 'reply' || $mode === 'editpost') { if ($mode === 'newtopic' || $mode === 'reply' || $mode === 'editpost') {
@ -315,7 +315,7 @@ class Attach
// restore values :) // restore values :)
if (isset($_POST['attachment_list'])) { if (isset($_POST['attachment_list'])) {
for ($i = 0, $iMax = is_array($actual_list) || $actual_list instanceof \Countable ? \count($actual_list) : 0; $i < $iMax; $i++) { for ($i = 0, $iMax = is_countable($actual_list) ? \count($actual_list) : 0; $i < $iMax; $i++) {
$restore = false; $restore = false;
$del_thumb = false; $del_thumb = false;
@ -383,7 +383,7 @@ class Attach
$this->attachment_comment_list = []; $this->attachment_comment_list = [];
for ($i = 0, $iMax = is_array($this->attachment_list) || $this->attachment_list instanceof \Countable ? \count($this->attachment_list) : 0; $i < $iMax; $i++) { for ($i = 0, $iMax = is_countable($this->attachment_list) ? \count($this->attachment_list) : 0; $i < $iMax; $i++) {
$this->attachment_comment_list[$i] = $actual_comment_list[$i]; $this->attachment_comment_list[$i] = $actual_comment_list[$i];
} }
} }
@ -405,7 +405,7 @@ class Attach
$attachment_id = 0; $attachment_id = 0;
$actual_element = 0; $actual_element = 0;
for ($i = 0, $iMax = is_array($actual_id_list) || $actual_id_list instanceof \Countable ? \count($actual_id_list) : 0; $i < $iMax; $i++) { for ($i = 0, $iMax = is_countable($actual_id_list) ? \count($actual_id_list) : 0; $i < $iMax; $i++) {
if (isset($_POST['update_attachment'][$actual_id_list[$i]])) { if (isset($_POST['update_attachment'][$actual_id_list[$i]])) {
$attachment_id = (int)$actual_id_list[$i]; $attachment_id = (int)$actual_id_list[$i];
$actual_element = $i; $actual_element = $i;
@ -532,7 +532,7 @@ class Attach
} }
if ($mode === 'attach_list') { if ($mode === 'attach_list') {
for ($i = 0, $iMax = is_array($this->attachment_list) || $this->attachment_list instanceof \Countable ? \count($this->attachment_list) : 0; $i < $iMax; $i++) { for ($i = 0, $iMax = is_countable($this->attachment_list) ? \count($this->attachment_list) : 0; $i < $iMax; $i++) {
if ($this->attachment_id_list[$i]) { if ($this->attachment_id_list[$i]) {
//bt //bt
if ($this->attachment_extension_list[$i] === TORRENT_EXT && !\defined('TORRENT_ATTACH_ID')) { if ($this->attachment_extension_list[$i] === TORRENT_EXT && !\defined('TORRENT_ATTACH_ID')) {
@ -659,7 +659,7 @@ class Attach
if ($this->attachment_list) { if ($this->attachment_list) {
$hidden = ''; $hidden = '';
for ($i = 0, $iMax = is_array($this->attachment_list) || $this->attachment_list instanceof \Countable ? \count($this->attachment_list) : 0; $i < $iMax; $i++) { for ($i = 0, $iMax = is_countable($this->attachment_list) ? \count($this->attachment_list) : 0; $i < $iMax; $i++) {
$hidden .= '<input type="hidden" name="attachment_list[]" value="' . $this->attachment_list[$i] . '" />'; $hidden .= '<input type="hidden" name="attachment_list[]" value="' . $this->attachment_list[$i] . '" />';
$hidden .= '<input type="hidden" name="filename_list[]" value="' . $this->attachment_filename_list[$i] . '" />'; $hidden .= '<input type="hidden" name="filename_list[]" value="' . $this->attachment_filename_list[$i] . '" />';
$hidden .= '<input type="hidden" name="extension_list[]" value="' . $this->attachment_extension_list[$i] . '" />'; $hidden .= '<input type="hidden" name="extension_list[]" value="' . $this->attachment_extension_list[$i] . '" />';
@ -691,7 +691,7 @@ class Attach
'TPL_POSTED_ATTACHMENTS' => true, 'TPL_POSTED_ATTACHMENTS' => true,
]); ]);
for ($i = 0, $iMax = is_array($this->attachment_list) || $this->attachment_list instanceof \Countable ? \count($this->attachment_list) : 0; $i < $iMax; $i++) { for ($i = 0, $iMax = is_countable($this->attachment_list) ? \count($this->attachment_list) : 0; $i < $iMax; $i++) {
if (@$this->attachment_id_list[$i] == 0) { if (@$this->attachment_id_list[$i] == 0) {
$download_link = $upload_dir . '/' . basename($this->attachment_list[$i]); $download_link = $upload_dir . '/' . basename($this->attachment_list[$i]);
} else { } else {

View file

@ -38,7 +38,7 @@ class AttachPosting extends Attach
$this->do_insert_attachment('attach_list', 'post', $post_id); $this->do_insert_attachment('attach_list', 'post', $post_id);
$this->do_insert_attachment('last_attachment', 'post', $post_id); $this->do_insert_attachment('last_attachment', 'post', $post_id);
if (((is_array($this->attachment_list) || $this->attachment_list instanceof \Countable ? \count($this->attachment_list) : 0) > 0 || $this->post_attach) && !isset($_POST['update_attachment'])) { if (((is_countable($this->attachment_list) ? \count($this->attachment_list) : 0) > 0 || $this->post_attach) && !isset($_POST['update_attachment'])) {
$sql = 'UPDATE ' . BB_POSTS . ' SET post_attachment = 1 WHERE post_id = ' . (int)$post_id; $sql = 'UPDATE ' . BB_POSTS . ' SET post_attachment = 1 WHERE post_id = ' . (int)$post_id;
if (!DB()->sql_query($sql)) { if (!DB()->sql_query($sql)) {

View file

@ -647,7 +647,7 @@ class User
if (IS_GUEST) { if (IS_GUEST) {
$this->opt_js = array_merge($this->opt_js, $this->opt_js_guest); $this->opt_js = array_merge($this->opt_js, $this->opt_js_guest);
} elseif (!empty($_COOKIE['opt_js'])) { } elseif (!empty($_COOKIE['opt_js'])) {
$opt_js = json_decode($_COOKIE['opt_js'], true); $opt_js = json_decode($_COOKIE['opt_js'], true, 512, JSON_THROW_ON_ERROR);
if (\is_array($opt_js)) { if (\is_array($opt_js)) {
$this->opt_js = array_merge($this->opt_js, $opt_js); $this->opt_js = array_merge($this->opt_js, $opt_js);

View file

@ -1,261 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2023 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
namespace TorrentPier\Legacy;
use Swift_Mailer;
use Swift_Message;
use Swift_SendmailTransport;
use Swift_SmtpTransport;
/**
* Имплементация старого класса Emailer с заменой отправки на SwiftMailer
* Переписать при дальнейшем переходе проекта на контейнерную структуру
*
* Class Emailer
* @package TorrentPier\Legacy
*/
class Emailer
{
/**
* Обычное текстовое сообщение
*/
public const FORMAT_TEXT = 'text/plain';
/**
* HTML-сообщение
*/
public const FORMAT_HTML = 'text/html';
/** @var string текст сообщения */
private $message;
/** @var string тема сообщения */
private $subject;
/** @var string адрес получателя */
private $to;
/** @var string адрес отправителя */
private $from;
/** @var string адрес для ответа */
private $reply;
/** @var string адрес копии */
private $cc;
/** @var array шаблон письма с указанием языка */
private $tpl_msg = [];
/** @var array переменные, подменяемые в шаблонах писем */
private $vars = [];
/** @var string кодировка отправляемых сообщений */
private $encoding;
public function __construct()
{
global $bb_cfg;
$this->reply = $bb_cfg['board_email'];
}
/**
* Установка темы сообщения
*
* @param string $subject
*/
public function set_subject($subject)
{
$this->subject = $subject;
}
/**
* Установка адреса получателя
*
* @param $address
*/
public function set_to($address)
{
$this->to = $address;
}
/**
* Установка адреса отправителя
*
* @param $address
*/
public function set_from($address)
{
$this->from = $address;
}
/**
* Установка адреса для ответа
*
* @param $address
*/
public function set_reply($address)
{
$this->reply = $address;
}
/**
* Установка адреса для копии
*
* @param $address
*/
public function set_cc($address)
{
$this->cc = $address;
}
/**
* Установка шаблона сообщения
*
* @param string $template_file имя шаблона
* @param string $template_lang язык шаблона
*/
public function set_template($template_file, $template_lang = '')
{
global $bb_cfg;
if (!$template_lang) {
$template_lang = $bb_cfg['default_lang'];
}
if (empty($this->tpl_msg[$template_lang . $template_file])) {
$tpl_file = LANG_ROOT_DIR . '/' . $template_lang . '/email/' . $template_file . '.html';
if (!file_exists($tpl_file)) {
$tpl_file = LANG_ROOT_DIR . '/' . $bb_cfg['default_lang'] . '/email/' . $template_file . '.html';
/** @noinspection NotOptimalIfConditionsInspection */
if (!file_exists($tpl_file)) {
bb_die('Could not find email template file: ' . $template_file);
}
}
if (!$fd = fopen($tpl_file, 'rb')) {
bb_die('Failed opening email template file: ' . $tpl_file);
}
$this->tpl_msg[$template_lang . $template_file] = fread($fd, filesize($tpl_file));
fclose($fd);
}
$this->message = $this->tpl_msg[$template_lang . $template_file];
}
/**
* Отправка сообщения получателям через SwiftMailer
*
* @param string $email_format
* @return bool
*/
public function send(string $email_format = self::FORMAT_TEXT)
{
global $bb_cfg, $lang, $userdata;
if (!$bb_cfg['emailer']['enabled']) {
return false;
}
/** Replace vars and prepare message */
$this->message = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "$\\1", $this->message);
foreach ($this->vars as $key => $val) {
$this->message = preg_replace(sprintf('/\$\{?%s\}?/', $key), $val, $this->message);
}
$this->message = trim($this->message);
/** Set some variables */
$this->subject = !empty($this->subject) ? $this->subject : $lang['EMAILER_SUBJECT']['EMPTY'];
$this->encoding = $bb_cfg['charset'];
/** Prepare message */
if ($bb_cfg['emailer']['smtp']['enabled']) {
if (!empty($bb_cfg['emailer']['smtp']['host'])) {
if (empty($bb_cfg['emailer']['ssl_type'])) {
/** @var Swift_SmtpTransport $transport external SMTP without ssl */
$transport = (new Swift_SmtpTransport(
$bb_cfg['emailer']['smtp']['host'],
$bb_cfg['emailer']['smtp']['port']
))
->setUsername($bb_cfg['emailer']['smtp']['username'])
->setPassword($bb_cfg['emailer']['smtp']['password']);
} else {
/** @var Swift_SmtpTransport $transport external SMTP with ssl */
$transport = (new Swift_SmtpTransport(
$bb_cfg['emailer']['smtp']['host'],
$bb_cfg['emailer']['smtp']['port'],
$bb_cfg['emailer']['ssl_type']
))
->setUsername($bb_cfg['emailer']['smtp']['username'])
->setPassword($bb_cfg['emailer']['smtp']['password']);
}
} else {
/** @var Swift_SmtpTransport $transport local SMTP */
$transport = new Swift_SmtpTransport('localhost', 25);
}
} else {
/** @var Swift_SendmailTransport $transport local SendMail */
$transport = new Swift_SendmailTransport('/usr/sbin/sendmail -bs');
}
/** @var Swift_Mailer $mailer */
$mailer = new Swift_Mailer($transport);
/** @var Swift_Message $message */
$message = (new Swift_Message())
->setSubject($this->subject)
->setReturnPath($bb_cfg['bounce_email'])
->setFrom($this->from)
->setTo($this->to)
->setReplyTo($this->reply)
->setBody($this->message, $email_format)
->setCharset($this->encoding);
if (!empty($this->cc)) {
$message->setCc($this->cc);
}
/** Send message */
if (!$result = $mailer->send($message)) {
bb_die('Failed sending email: ' . $result);
}
return true;
}
/**
* Установка переменных шаблона сообщения
*
* @param $vars
*/
public function assign_vars($vars)
{
$this->set_default_vars();
$this->vars = array_merge($this->vars, $vars);
}
/**
* Задание стандартных переменных шаблонов сообщения
*/
public function set_default_vars()
{
global $bb_cfg;
$this->vars = [
'BOARD_EMAIL' => $bb_cfg['board_email'],
'SITENAME' => $bb_cfg['board_email_sitename'],
'EMAIL_SIG' => !empty($bb_cfg['board_email_sig']) ? "-- \n{$bb_cfg['board_email_sig']}" : '',
];
}
}

View file

@ -9,6 +9,7 @@
namespace TorrentPier\Legacy; namespace TorrentPier\Legacy;
use TorrentPier\Emailer;
use TorrentPier\Legacy\Admin\Common; use TorrentPier\Legacy\Admin\Common;
/** /**
@ -373,11 +374,10 @@ class Post
$unwatch_topic = make_url(TOPIC_URL . "$topic_id&unwatch=topic"); $unwatch_topic = make_url(TOPIC_URL . "$topic_id&unwatch=topic");
foreach ($watch_list as $row) { foreach ($watch_list as $row) {
/** @var Emailer $emailer */ // Sending email
$emailer = new Emailer; $emailer = new Emailer();
$emailer->set_from([$bb_cfg['board_email'] => $bb_cfg['sitename']]); $emailer->set_to($row['user_email'], $row['username']);
$emailer->set_to([$row['user_email'] => $row['username']]);
$emailer->set_subject(sprintf($lang['EMAILER_SUBJECT']['TOPIC_NOTIFY'], $topic_title)); $emailer->set_subject(sprintf($lang['EMAILER_SUBJECT']['TOPIC_NOTIFY'], $topic_title));
$emailer->set_template('topic_notify', $row['user_lang']); $emailer->set_template('topic_notify', $row['user_lang']);

View file

@ -313,7 +313,7 @@ class Template
$str = &$this->_tpldata; $str = &$this->_tpldata;
for ($i = 0; $i < $blockcount; $i++) { for ($i = 0; $i < $blockcount; $i++) {
$str = &$str[$blocks[$i] . '.']; $str = &$str[$blocks[$i] . '.'];
$str = &$str[(is_array($str) || $str instanceof \Countable ? \count($str) : 0) - 1]; $str = &$str[(is_countable($str) ? \count($str) : 0) - 1];
} }
// Now we add the block that we're actually assigning to. // Now we add the block that we're actually assigning to.
// We're adding a new iteration to this block with the given // We're adding a new iteration to this block with the given
@ -745,7 +745,7 @@ class Template
// This one will handle varrefs WITH namespaces // This one will handle varrefs WITH namespaces
$varrefs = []; $varrefs = [];
preg_match_all('#\{(([a-z0-9\-_]+?\.)+)([a-z0-9\-_]+?)\}#is', $code, $varrefs); preg_match_all('#\{(([a-z0-9\-_]+?\.)+)([a-z0-9\-_]+?)\}#is', $code, $varrefs);
$varcount = is_array($varrefs[1]) || $varrefs[1] instanceof \Countable ? \count($varrefs[1]) : 0; $varcount = is_countable($varrefs[1]) ? \count($varrefs[1]) : 0;
$search = []; $search = [];
$replace = []; $replace = [];
for ($i = 0; $i < $varcount; $i++) { for ($i = 0; $i < $varcount; $i++) {
@ -783,7 +783,7 @@ class Template
[^\s(),]+)/x', $tag_args, $match); [^\s(),]+)/x', $tag_args, $match);
$tokens = $match[0]; $tokens = $match[0];
$tokens_cnt = is_array($tokens) || $tokens instanceof \Countable ? \count($tokens) : 0; $tokens_cnt = is_countable($tokens) ? \count($tokens) : 0;
$is_arg_stack = []; $is_arg_stack = [];
for ($i = 0; $i < $tokens_cnt; $i++) { for ($i = 0; $i < $tokens_cnt; $i++) {
@ -843,7 +843,7 @@ class Template
$new_tokens = $this->_parse_is_expr($is_arg, \array_slice($tokens, $i + 1)); $new_tokens = $this->_parse_is_expr($is_arg, \array_slice($tokens, $i + 1));
array_splice($tokens, $is_arg_start, is_array($tokens) || $tokens instanceof \Countable ? \count($tokens) : 0, $new_tokens); array_splice($tokens, $is_arg_start, is_countable($tokens) ? \count($tokens) : 0, $new_tokens);
$i = $is_arg_start; $i = $is_arg_start;
break; break;
@ -985,13 +985,13 @@ class Template
// adding language variable (eg: "english" or "german") // adding language variable (eg: "english" or "german")
// can be used to make truly multi-lingual templates // can be used to make truly multi-lingual templates
$this->vars['LANG'] = $this->vars['LANG'] ?? $bb_cfg['default_lang']; $this->vars['LANG'] ??= $bb_cfg['default_lang'];
// adding current template // adding current template
$tpl = $this->root . '/'; $tpl = $this->root . '/';
if (0 === strpos($tpl, './')) { if (0 === strpos($tpl, './')) {
$tpl = substr($tpl, 2, \strlen($tpl)); $tpl = substr($tpl, 2, \strlen($tpl));
} }
$this->vars['TEMPLATE'] = $this->vars['TEMPLATE'] ?? $tpl; $this->vars['TEMPLATE'] ??= $tpl;
$this->vars['TEMPLATE_NAME'] = $this->vars['TEMPLATE_NAME'] ?? $this->tpl; $this->vars['TEMPLATE_NAME'] ??= $this->tpl;
} }
} }

View file

@ -22,31 +22,39 @@
</select> </select>
</td> </td>
</tr> </tr>
<tr>
<td class="row1" align="right"><b>{L_REPLY_TO}</b></td>
<td class="row2">
<input type="text" name="reply_to" size="45" maxlength="100" style="width:98%" value="{REPLY_TO}"/>
</td>
</tr>
<tr> <tr>
<td class="row1" align="right"><b>{L_SUBJECT}</b></td> <td class="row1" align="right"><b>{L_SUBJECT}</b></td>
<td class="row2"><input type="text" name="subject" size="45" maxlength="100" style="width:98%" tabindex="2" class="post" value="{SUBJECT}" /></td> <td class="row2">
<input type="text" name="subject" size="45" maxlength="100" style="width:98%" value="{SUBJECT}"/>
</td>
</tr> </tr>
<tr> <tr>
<td class="row1" align="right" valign="top"><span class="gen"><b>{L_MESSAGE}</b></span></td> <td class="row1" align="right" valign="top"><span class="gen"><b>{L_MESSAGE}</b></span></td>
<td class="row2"><textarea name="message" rows="15" cols="35" wrap="virtual" style="width:98%" tabindex="3" class="post">{MESSAGE}</textarea></td> <td class="row2">
<textarea name="message" rows="15" cols="35" wrap="virtual" style="width:98%">{MESSAGE}</textarea>
</td>
</tr> </tr>
<tr> <tr>
<td class="catBottom" colspan="2"><input type="submit" value="{L_SEND_EMAIL}" name="submit" class="mainoption" /></td> <td class="catBottom" colspan="2"><input type="submit" value="{L_SEND_EMAIL}" name="submit" class="mainoption"/>
</td>
</tr> </tr>
</table> </table>
</form> </form>
<script type="text/javascript"> <script type="text/javascript">
function checkForm(formObj) function checkForm(formObj) {
{
var formErrors = false; var formErrors = false;
if (formObj.message.value.length < 2) { if (formObj.message.value.length < 2) {
formErrors = "{L_EMPTY_MESSAGE_EMAIL}"; formErrors = "{L_EMPTY_MESSAGE_EMAIL}";
} } else if (formObj.subject.value.length < 2) {
else if ( formObj.subject.value.length < 2)
{
formErrors = "{L_EMPTY_SUBJECT_EMAIL}"; formErrors = "{L_EMPTY_SUBJECT_EMAIL}";
} }