diff --git a/README.md b/README.md index d27ec746f..0aaa27f32 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ and go from there. The documentation will be translated into english in the near * Apache / nginx * 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 ## Installation diff --git a/admin/admin_mass_email.php b/admin/admin_mass_email.php index 2338e57eb..311d5dfd5 100644 --- a/admin/admin_mass_email.php +++ b/admin/admin_mass_email.php @@ -20,9 +20,10 @@ if (!$bb_cfg['emailer']['enabled']) { set_time_limit(1200); -$subject = (string)trim(request_var('subject', '')); +$subject = trim(request_var('subject', '')); $message = (string)request_var('message', ''); $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', ''); $errors = $user_id_sql = []; @@ -66,12 +67,12 @@ if (isset($_POST['submit'])) { } foreach ($user_list as $i => $row) { - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_reply($reply_to); $emailer->set_template('admin_send_email'); $emailer->assign_vars(array( @@ -101,6 +102,7 @@ foreach (DB()->fetch_rowset($sql) as $row) { $template->assign_vars(array( 'MESSAGE' => $message, 'SUBJECT' => $subject, + 'REPLY_TO' => $reply_to, 'ERROR_MESSAGE' => $errors ? implode('
', array_unique($errors)) : '', diff --git a/common.php b/common.php index 2e2cd676b..ad504df54 100644 --- a/common.php +++ b/common.php @@ -7,6 +7,8 @@ * @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License */ +use TorrentPier\Env; + if (isset($_REQUEST['GLOBALS'])) { die(); } @@ -51,46 +53,20 @@ if (!file_exists(__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 mixed $default + * @param string $key + * @param mixed $default * @return mixed */ function env($key, $default = null) { - $value = getenv($key); - 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; + return Env::get($key, $default); } // Get initial config -if (!getenv('APP_DEBUG') && file_exists(__DIR__ . '/.env')) { - (new Symfony\Component\Dotenv\Dotenv())->load(__DIR__ . '/.env'); -} +$dotenv = Dotenv\Dotenv::createMutable(__DIR__); +$dotenv->safeLoad(); require_once __DIR__ . '/library/config.php'; // Local config diff --git a/composer.json b/composer.json index c38385dbf..0ee8ec85f 100644 --- a/composer.json +++ b/composer.json @@ -17,16 +17,6 @@ "homepage": "https://github.com/Exileum", "role": "Developer" }, - { - "name": "Diolektor", - "homepage": "https://github.com/VasyOk", - "role": "Developer" - }, - { - "name": "PheRum", - "homepage": "https://github.com/PheRum", - "role": "Developer" - }, { "name": "belomaxorka", "email": "roman25052006.kelesh@gmail.com", @@ -37,28 +27,27 @@ "support": { "email": "support@torrentpier.com", "issues": "https://github.com/torrentpier/torrentpier/issues", - "forum": "https://torrentpier.com", - "docs": "https://docs.torrentpier.com/" + "forum": "https://torrentpier.com" }, "require": { - "php": "^7.1.3", + "php": "^7.4", "bugsnag/bugsnag": "v3.29.0", - "egulias/email-validator": "2.*", - "filp/whoops": "2.15.1", + "egulias/email-validator": "^3.2", + "filp/whoops": "^2.15", "gigablah/sphinxphp": "2.0.8", - "google/recaptcha": "1.2.4", - "guzzlehttp/guzzle": "6.*", - "guzzlehttp/psr7": "1.*", + "google/recaptcha": "^1.2", + "guzzlehttp/guzzle": "^7.5", + "guzzlehttp/psr7": "^2.4", "longman/ip-tools": "1.2.1", - "monolog/monolog": "1.*", + "monolog/monolog": "^2.9", "rych/bencode": "v1.0.0", "samdark/sitemap": "2.4.0", - "swiftmailer/swiftmailer": "v6.3.0", - "symfony/dotenv": "4.*", - "symfony/polyfill": "v1.27.0" + "symfony/mailer": "^5.4", + "symfony/polyfill": "v1.27.0", + "vlucas/phpdotenv": "^5.5" }, "require-dev": { - "symfony/var-dumper": "4.*" + "symfony/var-dumper": "^5.4" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index eeaba4318..004e32873 100644 --- a/composer.lock +++ b/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": "5cbe568826fbd0fe40fe76d58d1e1a9c", + "content-hash": "6241213ade775fe6873c1265d649c934", "packages": [ { "name": "bugsnag/bugsnag", @@ -146,32 +146,77 @@ "time": "2023-01-11T08:27:00+00:00" }, { - "name": "doctrine/lexer", - "version": "1.2.3", + "name": "doctrine/deprecations", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.1|^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -203,7 +248,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, "funding": [ { @@ -219,31 +264,30 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "egulias/email-validator", - "version": "2.1.25", + "version": "3.2.5", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4" + "reference": "b531a2311709443320c786feb4519cfaf94af796" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0dbf5d78455d4d6a41d186da50adc1122ec066f4", - "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b531a2311709443320c786feb4519cfaf94af796", + "reference": "b531a2311709443320c786feb4519cfaf94af796", "shasum": "" }, "require": { - "doctrine/lexer": "^1.0.1", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.10" + "doctrine/lexer": "^1.2|^2", + "php": ">=7.2", + "symfony/polyfill-intl-idn": "^1.15" }, "require-dev": { - "dominicsayers/isemail": "^3.0.7", - "phpunit/phpunit": "^4.8.36|^7.5.15", - "satooshi/php-coveralls": "^1.0.1" + "phpunit/phpunit": "^8.5.8|^9.3.3", + "vimeo/psalm": "^4" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -251,7 +295,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -279,7 +323,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + "source": "https://github.com/egulias/EmailValidator/tree/3.2.5" }, "funding": [ { @@ -287,7 +331,7 @@ "type": "github" } ], - "time": "2020-12-29T14:50:06+00:00" + "time": "2023-01-02T17:26:14+00:00" }, { "name": "filp/whoops", @@ -468,38 +512,112 @@ "time": "2020-03-31T17:50:54+00:00" }, { - "name": "guzzlehttp/guzzle", - "version": "6.5.8", + "name": "graham-campbell/result-type", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981" + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2023-02-25T20:23:15+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba", + "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.9", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.17" + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.9 || ^2.4", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.1" + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, "branch-alias": { - "dev-master": "6.5-dev" + "dev-master": "7.5-dev" } }, "autoload": { @@ -552,19 +670,20 @@ } ], "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", "keywords": [ "client", "curl", "framework", "http", "http client", + "psr-18", + "psr-7", "rest", "web service" ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/6.5.8" + "source": "https://github.com/guzzle/guzzle/tree/7.5.0" }, "funding": [ { @@ -580,7 +699,7 @@ "type": "tidelift" } ], - "time": "2022-06-20T22:16:07+00:00" + "time": "2022-08-28T15:39:27+00:00" }, { "name": "guzzlehttp/promises", @@ -668,43 +787,47 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.9.0", + "version": "2.4.4", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318" + "reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", - "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf", + "reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf", "shasum": "" }, "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { - "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "2.4-dev" } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } @@ -743,6 +866,11 @@ "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", @@ -758,7 +886,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.9.0" + "source": "https://github.com/guzzle/psr7/tree/2.4.4" }, "funding": [ { @@ -774,7 +902,7 @@ "type": "tidelift" } ], - "time": "2022-06-20T21:43:03+00:00" + "time": "2023-03-09T13:19:02+00:00" }, { "name": "longman/ip-tools", @@ -838,51 +966,67 @@ }, { "name": "monolog/monolog", - "version": "1.27.1", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "904713c5929655dc9b97288b69cfeedad610c9a1" + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/904713c5929655dc9b97288b69cfeedad610c9a1", - "reference": "904713c5929655dc9b97288b69cfeedad610c9a1", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", "shasum": "" }, "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpstan/phpstan": "^0.12.59", - "phpunit/phpunit": "~4.5", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "^5.3|^6.0" + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, "autoload": { "psr-4": { "Monolog\\": "src/Monolog" @@ -896,11 +1040,11 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ "log", "logging", @@ -908,7 +1052,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/1.27.1" + "source": "https://github.com/Seldaek/monolog/tree/2.9.1" }, "funding": [ { @@ -920,7 +1064,287 @@ "type": "tidelift" } ], - "time": "2022-06-09T08:53:42+00:00" + "time": "2023-02-06T13:44:46+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-02-25T19:38:58+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" }, { "name": "psr/http-message", @@ -1184,42 +1608,35 @@ "time": "2021-10-02T04:04:28+00:00" }, { - "name": "swiftmailer/swiftmailer", - "version": "v6.3.0", + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", "source": { "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8a5d5072dca8f48460fce2f4131fcc495eec654c", - "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", "shasum": "" }, "require": { - "egulias/email-validator": "^2.0|^3.1", - "php": ">=7.0.0", - "symfony/polyfill-iconv": "^1.0", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "symfony/phpunit-bridge": "^4.4|^5.4" - }, - "suggest": { - "ext-intl": "Needed to support internationalized email addresses" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "files": [ - "lib/swift_required.php" + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1228,61 +1645,80 @@ ], "authors": [ { - "name": "Chris Corbyn" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Swiftmailer, free feature-rich PHP mailer", - "homepage": "https://swiftmailer.symfony.com", - "keywords": [ - "email", - "mail", - "mailer" - ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/swiftmailer/swiftmailer/issues", - "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" }, "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, { "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "abandoned": "symfony/mailer", - "time": "2021-10-18T15:26:12+00:00" + "time": "2022-01-02T09:53:40+00:00" }, { - "name": "symfony/dotenv", - "version": "v4.4.37", + "name": "symfony/event-dispatcher", + "version": "v5.4.21", "source": { "type": "git", - "url": "https://github.com/symfony/dotenv.git", - "reference": "fcedd6d382b3afc3e1e786aa4e4fc4cf06f564cf" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "f0ae1383a8285dfc6752b8d8602790953118ff5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/fcedd6d382b3afc3e1e786aa4e4fc4cf06f564cf", - "reference": "fcedd6d382b3afc3e1e786aa4e4fc4cf06f564cf", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f0ae1383a8285dfc6752b8d8602790953118ff5a", + "reference": "f0ae1383a8285dfc6752b8d8602790953118ff5a", "shasum": "" }, "require": { - "php": ">=7.1.3" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { - "symfony/process": "^3.4.2|^4.0|^5.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Dotenv\\": "" + "Symfony\\Component\\EventDispatcher\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1302,15 +1738,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Registers environment variables from a .env file", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", - "keywords": [ - "dotenv", - "env", - "environment" - ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v4.4.37" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.21" }, "funding": [ { @@ -1326,7 +1757,246 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:41:36+00:00" + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + }, + "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": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/mailer", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "60c5f5a29399ff591fadd99da345a4a8bf048c41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/60c5f5a29399ff591fadd99da345a4a8bf048c41", + "reference": "60c5f5a29399ff591fadd99da345a4a8bf048c41", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=7.2.5", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/mime": "^5.2.6|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<4.4" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0" + }, + "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/v5.4.21" + }, + "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-02-21T10:48:16+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "ef57d9fb9cdd5e6b2ffc567d109865d10b6920cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/ef57d9fb9cdd5e6b2ffc567d109865d10b6920cd", + "reference": "ef57d9fb9cdd5e6b2ffc567d109865d10b6920cd", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<4.4", + "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/property-access": "^4.4|^5.1|^6.0", + "symfony/property-info": "^4.4|^5.1|^6.0", + "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "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": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v5.4.21" + }, + "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-02-21T19:46:44+00:00" }, { "name": "symfony/polyfill", @@ -1444,38 +2114,205 @@ } ], "time": "2022-11-10T10:11:03+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + }, + "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": "2022-05-30T19:17:29+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.5.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "5.5-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2022-10-16T01:01:54+00:00" } ], "packages-dev": [ { "name": "symfony/var-dumper", - "version": "v4.4.47", + "version": "v5.4.21", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "1069c7a3fca74578022fab6f81643248d02f8e63" + "reference": "6c5ac3a1be8b849d59a1a77877ee110e1b55eb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1069c7a3fca74578022fab6f81643248d02f8e63", - "reference": "1069c7a3fca74578022fab6f81643248d02f8e63", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6c5ac3a1be8b849d59a1a77877ee110e1b55eb74", + "reference": "6c5ac3a1be8b849d59a1a77877ee110e1b55eb74", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.5", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/console": "<3.4" + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^3.4|^4.0|^5.0", - "symfony/process": "^4.4|^5.0", - "twig/twig": "^1.43|^2.13|^3.0.4" + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", @@ -1518,7 +2355,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v4.4.47" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.21" }, "funding": [ { @@ -1534,7 +2371,7 @@ "type": "tidelift" } ], - "time": "2022-10-03T15:15:11+00:00" + "time": "2023-02-23T10:00:28+00:00" } ], "aliases": [], @@ -1543,8 +2380,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.1.3" + "php": "^7.4" }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } diff --git a/group.php b/group.php index c8f42840b..8c014ac37 100644 --- a/group.php +++ b/group.php @@ -168,11 +168,10 @@ if (!$group_id) { \TorrentPier\Legacy\Group::add_user_into_group($group_id, $userdata['user_id'], 1, TIMENOW); if ($bb_cfg['group_send_email']) { - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_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']); if ($bb_cfg['group_send_email']) { - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template('group_added', $row['user_lang']); @@ -269,11 +267,10 @@ if (!$group_id) { } foreach (DB()->fetch_rowset($sql_select) as $row) { - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template('group_approved', $row['user_lang']); diff --git a/library/ajax/change_user_opt.php b/library/ajax/change_user_opt.php index d612cf746..0417f9ca6 100644 --- a/library/ajax/change_user_opt.php +++ b/library/ajax/change_user_opt.php @@ -14,7 +14,7 @@ if (!defined('IN_AJAX')) { global $bf, $lang; $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)) { $this->ajax_die($lang['NO_USER_ID_SPECIFIED']); diff --git a/library/attach_mod/includes/functions_attach.php b/library/attach_mod/includes/functions_attach.php index ef7d20cc5..6b978af24 100644 --- a/library/attach_mod/includes/functions_attach.php +++ b/library/attach_mod/includes/functions_attach.php @@ -55,7 +55,7 @@ function base64_unpack($string) for ($i = 1; $i <= $length; $i++) { $pos = $length - $i; - $operand = strpos($chars, $string[$pos]); + $operand = strpos($chars, (string) $string[$pos]); $exponent = $base ** ($i - 1); $decValue = $operand * $exponent; $number += $decValue; diff --git a/library/config.php b/library/config.php index 67c8fad6c..52710aded 100644 --- a/library/config.php +++ b/library/config.php @@ -377,7 +377,7 @@ $bb_cfg['emailer'] = [ 'enabled' => true, 'smtp' => [ 'enabled' => false, // send email via external SMTP server - 'host' => '', // SMTP server host + 'host' => 'localhost', // SMTP server host 'port' => 25, // SMTP server port 'username' => '', // SMTP username (if server requires it) 'password' => '', // SMTP password (if server requires it) diff --git a/library/includes/functions.php b/library/includes/functions.php index 6172ae7d3..24072086d 100644 --- a/library/includes/functions.php +++ b/library/includes/functions.php @@ -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) { 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); } function get_attach_path($id, $ext_id = '', $base_path = null, $first_div = 10000, $sec_div = 100) { 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); } @@ -762,7 +762,7 @@ function str_short($text, $max_length, $space = ' ') if ($max_length && mb_strlen($text, 'UTF-8') > $max_length) { $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)) { $last_space_pos--; $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; $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) { $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); } 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]; diff --git a/library/includes/init_bb.php b/library/includes/init_bb.php index f98b576c2..39264b704 100644 --- a/library/includes/init_bb.php +++ b/library/includes/init_bb.php @@ -14,8 +14,8 @@ if (!defined('BB_ROOT')) { /** * Check PHP version */ -if (PHP_VERSION_ID < 70103) { - die('TorrentPier requires PHP version 7.1.3+. Your PHP version ' . PHP_VERSION); +if (PHP_VERSION_ID < 70400) { + die('TorrentPier requires PHP version 7.4+. Your PHP version ' . PHP_VERSION); } /** @@ -88,10 +88,16 @@ define('COOKIE_MAX_TRACKS', 90); * @param bool $httponly * @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; - 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, + ]); } /** diff --git a/library/includes/page_header.php b/library/includes/page_header.php index 2b9418ba2..b3832f42d 100644 --- a/library/includes/page_header.php +++ b/library/includes/page_header.php @@ -119,7 +119,7 @@ $template->assign_vars(array( 'USER_LANG' => $userdata['user_lang'], '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']), diff --git a/library/includes/ucp/email.php b/library/includes/ucp/email.php index 3e8567ebb..751d46400 100644 --- a/library/includes/ucp/email.php +++ b/library/includes/ucp/email.php @@ -53,11 +53,10 @@ if ($row = DB()->fetch_row($sql)) { } if (!$errors) { - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template('profile_send_email', $user_lang); diff --git a/library/includes/ucp/register.php b/library/includes/ucp/register.php index c96ba98a8..f6732920f 100644 --- a/library/includes/ucp/register.php +++ b/library/includes/ucp/register.php @@ -568,11 +568,10 @@ if ($submit && !$errors) { $email_template = 'user_welcome'; } - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template($email_template, $user_lang); @@ -601,11 +600,10 @@ if ($submit && !$errors) { $pr_data['user_actkey'] = $user_actkey; $db_data['user_actkey'] = $user_actkey; - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template('user_activate', $pr_data['user_lang']); diff --git a/library/includes/ucp/sendpasswd.php b/library/includes/ucp/sendpasswd.php index 1d4589edb..52fb5e516 100644 --- a/library/includes/ucp/sendpasswd.php +++ b/library/includes/ucp/sendpasswd.php @@ -47,11 +47,10 @@ if (isset($_POST['submit'])) { bb_die('Could not update new password information'); } - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template('user_activate_passwd', $row['user_lang']); diff --git a/library/includes/ucp/viewprofile.php b/library/includes/ucp/viewprofile.php index deb529e62..820ac5ca9 100644 --- a/library/includes/ucp/viewprofile.php +++ b/library/includes/ucp/viewprofile.php @@ -184,7 +184,7 @@ if (IS_ADMIN) { 'dis_post' => bf($profiledata['user_opt'], 'user_opt', 'dis_post'), 'dis_post_edit' => bf($profiledata['user_opt'], 'user_opt', 'dis_post_edit'), 'dis_topic' => bf($profiledata['user_opt'], 'user_opt', 'dis_topic'), - )); + ), JSON_THROW_ON_ERROR); $template->assign_vars(array( 'EDITABLE_TPLS' => true, diff --git a/library/language/source/main.php b/library/language/source/main.php index 0ba24ecdd..78999a8da 100644 --- a/library/language/source/main.php +++ b/library/language/source/main.php @@ -2809,6 +2809,7 @@ $lang['CAPTCHA_WRONG'] = 'You could not confirm that you are not a robot'; $lang['CAPTCHA_SETTINGS'] = '

ReCaptcha not being fully configured

If you haven\'t already generated the keys, you can do it on https://www.google.com/recaptcha/admin.
After you generate the keys, you need to put them at the file library/config.php.

'; // Sending email +$lang['REPLY_TO'] = 'Reply to'; $lang['EMAILER_SUBJECT'] = [ 'EMPTY' => 'No subject', 'GROUP_ADDED' => 'You have been added to the user group', diff --git a/privmsg.php b/privmsg.php index 234326a98..2c9889011 100644 --- a/privmsg.php +++ b/privmsg.php @@ -898,11 +898,10 @@ if ($mode == 'read') { \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']) { - /** @var TorrentPier\Legacy\Emailer() $emailer */ - $emailer = new TorrentPier\Legacy\Emailer(); + // Sending email + $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_template('privmsg_notify', $to_userdata['user_lang']); diff --git a/src/Emailer.php b/src/Emailer.php new file mode 100644 index 000000000..7fab43bf7 --- /dev/null +++ b/src/Emailer.php @@ -0,0 +1,215 @@ +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); + } +} diff --git a/src/Env.php b/src/Env.php new file mode 100644 index 000000000..6d7d6d73e --- /dev/null +++ b/src/Env.php @@ -0,0 +1,101 @@ +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)); + } +} diff --git a/src/Legacy/Ajax.php b/src/Legacy/Ajax.php index 42a4d0aad..5d612d077 100644 --- a/src/Legacy/Ajax.php +++ b/src/Legacy/Ajax.php @@ -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 (UA_GZIP_SUPPORTED && \strlen($response_js) > 2000) { diff --git a/src/Legacy/Attach.php b/src/Legacy/Attach.php index c4e93fbf4..b165a3173 100644 --- a/src/Legacy/Attach.php +++ b/src/Legacy/Attach.php @@ -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 ($mode === 'newtopic' || $mode === 'reply' || $mode === 'editpost') { @@ -315,7 +315,7 @@ class Attach // restore values :) 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; $del_thumb = false; @@ -383,7 +383,7 @@ class Attach $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]; } } @@ -405,7 +405,7 @@ class Attach $attachment_id = 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]])) { $attachment_id = (int)$actual_id_list[$i]; $actual_element = $i; @@ -532,7 +532,7 @@ class Attach } 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]) { //bt if ($this->attachment_extension_list[$i] === TORRENT_EXT && !\defined('TORRENT_ATTACH_ID')) { @@ -659,7 +659,7 @@ class Attach if ($this->attachment_list) { $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 .= ''; $hidden .= ''; $hidden .= ''; @@ -691,7 +691,7 @@ class Attach '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) { $download_link = $upload_dir . '/' . basename($this->attachment_list[$i]); } else { diff --git a/src/Legacy/AttachPosting.php b/src/Legacy/AttachPosting.php index 762609ae3..0fa506561 100644 --- a/src/Legacy/AttachPosting.php +++ b/src/Legacy/AttachPosting.php @@ -38,7 +38,7 @@ class AttachPosting extends Attach $this->do_insert_attachment('attach_list', '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; if (!DB()->sql_query($sql)) { diff --git a/src/Legacy/Common/User.php b/src/Legacy/Common/User.php index 6efb5f555..612364400 100644 --- a/src/Legacy/Common/User.php +++ b/src/Legacy/Common/User.php @@ -647,7 +647,7 @@ class User if (IS_GUEST) { $this->opt_js = array_merge($this->opt_js, $this->opt_js_guest); } 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)) { $this->opt_js = array_merge($this->opt_js, $opt_js); diff --git a/src/Legacy/Emailer.php b/src/Legacy/Emailer.php deleted file mode 100644 index 3655fd244..000000000 --- a/src/Legacy/Emailer.php +++ /dev/null @@ -1,261 +0,0 @@ -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']}" : '', - ]; - } -} diff --git a/src/Legacy/Post.php b/src/Legacy/Post.php index ca6db5ef4..a7c78868f 100644 --- a/src/Legacy/Post.php +++ b/src/Legacy/Post.php @@ -9,6 +9,7 @@ namespace TorrentPier\Legacy; +use TorrentPier\Emailer; use TorrentPier\Legacy\Admin\Common; /** @@ -373,11 +374,10 @@ class Post $unwatch_topic = make_url(TOPIC_URL . "$topic_id&unwatch=topic"); foreach ($watch_list as $row) { - /** @var Emailer $emailer */ - $emailer = new Emailer; + // Sending email + $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_template('topic_notify', $row['user_lang']); diff --git a/src/Legacy/Template.php b/src/Legacy/Template.php index cc6f7d876..6ea32b9b4 100644 --- a/src/Legacy/Template.php +++ b/src/Legacy/Template.php @@ -313,7 +313,7 @@ class Template $str = &$this->_tpldata; for ($i = 0; $i < $blockcount; $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. // 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 $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 = []; $replace = []; for ($i = 0; $i < $varcount; $i++) { @@ -783,7 +783,7 @@ class Template [^\s(),]+)/x', $tag_args, $match); $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 = []; 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)); - 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; break; @@ -985,13 +985,13 @@ class Template // adding language variable (eg: "english" or "german") // 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 $tpl = $this->root . '/'; if (0 === strpos($tpl, './')) { $tpl = substr($tpl, 2, \strlen($tpl)); } - $this->vars['TEMPLATE'] = $this->vars['TEMPLATE'] ?? $tpl; - $this->vars['TEMPLATE_NAME'] = $this->vars['TEMPLATE_NAME'] ?? $this->tpl; + $this->vars['TEMPLATE'] ??= $tpl; + $this->vars['TEMPLATE_NAME'] ??= $this->tpl; } } diff --git a/styles/templates/admin/admin_mass_email.tpl b/styles/templates/admin/admin_mass_email.tpl index a4cf0b6e9..03b820c01 100644 --- a/styles/templates/admin/admin_mass_email.tpl +++ b/styles/templates/admin/admin_mass_email.tpl @@ -1,58 +1,66 @@

{L_MASS_EMAIL}

{L_MASS_EMAIL_EXPLAIN}

-
+
- - - - - - - - - - - - - - - - - - - - - - - -
{L_COMPOSE}
{L_RECIPIENTS}{S_GROUP_SELECT}
{L_MASS_EMAIL_MESSAGE_TYPE} - -
{L_SUBJECT}
{L_MESSAGE}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{L_COMPOSE}
{L_RECIPIENTS}{S_GROUP_SELECT}
{L_MASS_EMAIL_MESSAGE_TYPE} + +
{L_REPLY_TO} + +
{L_SUBJECT} + +
{L_MESSAGE} + +
+