diff --git a/class2.php b/class2.php index e416c4762..a18adb38a 100755 --- a/class2.php +++ b/class2.php @@ -549,7 +549,7 @@ if(!isset($_E107['no_session']) && !isset($_E107['no_lan'])) define('USERCLASS_LIST', $emulatedUser['user_class']); define('ADMINPERMS', $emulatedUser['user_perms']); - define('USERID', $emulatedUser['user_id']); + // define('USERID', $emulatedUser['user_id']); Don't emulate user id. It will mess with logs. define('USERNAME', $emulatedUser['user_name']); } } diff --git a/composer.json b/composer.json index 8663cf618..77ee4917e 100644 --- a/composer.json +++ b/composer.json @@ -15,13 +15,13 @@ }, "config": { "platform": { - "php": "5.6" + "php": "8.0" }, "vendor-dir": "e107_handlers/vendor", "platform-check": false }, "require": { - "php": ">=5.6", + "php": ">=8.0", "ext-json": "*", "ext-pdo": "*", "hybridauth/hybridauth": "^3.6.0", diff --git a/composer.lock b/composer.lock index c4fdc8d65..06296f42f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,42 +4,48 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "12129f1e8aec686d7cae22b9281fe71d", + "content-hash": "2c43b8b28c62180e08d5592eb882f974", "packages": [ { "name": "guzzlehttp/psr7", - "version": "1.9.1", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b" + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/e4490cabc77465aaee90b20cfc9a770f8c04be6b", - "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", "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.1 || ^2.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.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } @@ -78,6 +84,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", @@ -93,7 +104,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.9.1" + "source": "https://github.com/guzzle/psr7/tree/2.7.1" }, "funding": [ { @@ -109,20 +120,20 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:00:37+00:00" + "time": "2025-03-27T12:30:47+00:00" }, { "name": "hybridauth/hybridauth", - "version": "v3.11.0", + "version": "v3.12.1", "source": { "type": "git", "url": "https://github.com/hybridauth/hybridauth.git", - "reference": "b70b9cbe1c7fa99b5847c5868610a8f024cc7d38" + "reference": "9449686baf2593739129a24e515a60908738ea8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hybridauth/hybridauth/zipball/b70b9cbe1c7fa99b5847c5868610a8f024cc7d38", - "reference": "b70b9cbe1c7fa99b5847c5868610a8f024cc7d38", + "url": "https://api.github.com/repos/hybridauth/hybridauth/zipball/9449686baf2593739129a24e515a60908738ea8d", + "reference": "9449686baf2593739129a24e515a60908738ea8d", "shasum": "" }, "require": { @@ -130,7 +141,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^6.5 || ^8.0" + "phpunit/phpunit": "^4.8.35 || ^6.5 || ^8.0 || ^12.0" }, "suggest": { "firebase/php-jwt": "Needed to support Apple provider", @@ -169,9 +180,9 @@ "support": { "gitter": "https://gitter.im/hybridauth/hybridauth", "issues": "https://github.com/hybridauth/hybridauth/issues", - "source": "https://github.com/hybridauth/hybridauth/tree/v3.11.0" + "source": "https://github.com/hybridauth/hybridauth/tree/v3.12.1" }, - "time": "2024-01-02T23:09:56+00:00" + "time": "2025-04-22T05:22:57+00:00" }, { "name": "ifsnop/mysqldump-php", @@ -522,21 +533,22 @@ "time": "2024-11-24T18:04:13+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "psr/http-factory", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -556,7 +568,61 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: 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" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -570,9 +636,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "ralouphie/getallheaders", @@ -622,17 +688,17 @@ "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6", + "php": ">=8.0", "ext-json": "*", "ext-pdo": "*" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { - "php": "5.6" + "php": "8.0" }, "plugin-api-version": "2.6.0" } diff --git a/e107_core/url/news/sef_noid_url.php b/e107_core/url/news/sef_noid_url.php index 8539e8f6e..749725ae3 100644 --- a/e107_core/url/news/sef_noid_url.php +++ b/e107_core/url/news/sef_noid_url.php @@ -67,8 +67,8 @@ class core_news_sef_noid_url extends eUrlConfig if($route[0] == 'view') { ## news are passing array as it is retrieved from the DB, map vars to proper values - if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id']; - if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef']; // TODO - news_sef + if(!empty($params['news_id'])) $params['id'] = $params['news_id']; + if(!empty($params['news_sef'])) $params['id'] = $params['news_sef']; // TODO - news_sef switch ($route[1]) { @@ -84,8 +84,8 @@ class core_news_sef_noid_url extends eUrlConfig elseif($route[0] == 'list') { ## news are passing array as it is retrieved from the DB, map vars to proper values - if(isset($params['category_id']) && !empty($params['category_id'])) $params['id'] = $params['category_id']; - if(isset($params['category_sef']) && !empty($params['category_sef'])) $params['name'] = $params['category_sef']; // TODO - news_sef + if(!empty($params['category_id'])) $params['id'] = $params['category_id']; + if(!empty($params['category_sef'])) $params['name'] = $params['category_sef']; // TODO - news_sef switch ($route[1]) { @@ -166,7 +166,7 @@ class core_news_sef_noid_url extends eUrlConfig * - news/Category/Category-Name?page=10 -> list.xxx.10 * - news/Day|Month-xxx -> day|month-xxx */ - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + public function parse($pathInfo, $params = array(), eRequest|null $request = null, eRouter|null $router = null, $config = array()) { $page = !empty($params['page']) ? intval($params['page']) : '0'; @@ -304,7 +304,7 @@ class core_news_sef_noid_url extends eUrlConfig $sql = e107::getDb('url'); $tp = e107::getParser(); $id = $tp->toDB($id); - if($sql->select('news', 'news_id', "news_sef='{$id}'")) + if($sql->select('news', 'news_id', "news_sef='$id'")) { $id = $sql->fetch(); return $id['news_id']; @@ -318,7 +318,7 @@ class core_news_sef_noid_url extends eUrlConfig $sql = e107::getDb('url'); $tp = e107::getParser(); $id = $tp->toDB($id); - if($sql->select('news_category', 'category_id', "category_sef='{$id}'")) + if($sql->select('news_category', 'category_id', "category_sef='$id'")) { $id = $sql->fetch(); return $id['category_id']; diff --git a/e107_core/url/news/url.php b/e107_core/url/news/url.php index fee6fda64..c04822da6 100644 --- a/e107_core/url/news/url.php +++ b/e107_core/url/news/url.php @@ -175,7 +175,7 @@ class core_news_url extends eUrlConfig return $url; } - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + public function parse($pathInfo, $params = array(), eRequest|null $request = null, eRouter|null $router = null, $config = array()) { // this config doesn't support parsing, it's done by the module entry script (news.php) // this means News are not available via single entry point if this config is currently active diff --git a/e107_core/url/page/url.php b/e107_core/url/page/url.php index 5fa79f3b7..b2cc58f95 100644 --- a/e107_core/url/page/url.php +++ b/e107_core/url/page/url.php @@ -122,7 +122,7 @@ class core_page_url extends eUrlConfig return $admin; } - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + public function parse($pathInfo, $params = array(), eRequest|null $request = null, eRouter|null $router = null, $config = array()) { // this config doesn't support parsing, it's done by the module entry script (news.php) // this means News are not available via single entry point if this config is currently active diff --git a/e107_core/url/user/url.php b/e107_core/url/user/url.php index 8ed195041..80b170536 100644 --- a/e107_core/url/user/url.php +++ b/e107_core/url/user/url.php @@ -121,7 +121,7 @@ class core_user_url extends eUrlConfig return $admin; } - public function parse($pathInfo, $params = array(), eRequest $request = NULL, eRouter $router = NULL, $config = array()) + public function parse($pathInfo, $params = array(), eRequest|null $request = null, eRouter|null $router = null, $config = array()) { // this config doesn't support parsing, it's done by the module entry script (news.php) // this means News are not available via single entry point if this config is currently active diff --git a/e107_handlers/application.php b/e107_handlers/application.php index b4c8c4c26..897edf626 100644 --- a/e107_handlers/application.php +++ b/e107_handlers/application.php @@ -5217,7 +5217,7 @@ class eHelper */ public static function dasherize($str) { - return str_replace(array('_', ' '), '-', $str); + return !empty($str) ? str_replace(array('_', ' '), '-', $str) : ''; } /** diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index f8dcee200..68e31e46b 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -318,7 +318,7 @@ class e_parse * NOTE: can't be called until CHARSET is known * but we all know that it is UTF-8 now * - * @return void + * @return void|null */ public function setMultibyte($bool) { @@ -1895,7 +1895,7 @@ class e_parse } elseif (is_string($mixed)) { - return iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($mixed)); + return iconv('UTF-8', 'UTF-8//IGNORE', mb_convert_encoding($mixed, 'UTF-8', 'ISO-8859-1')); } return $mixed; @@ -2316,7 +2316,7 @@ class e_parse /** * Retrieve img tag width and height attributes for current thumbnail. * - * @return string + * @return string|null */ public function thumbDimensions($type = 'single') { @@ -2385,7 +2385,7 @@ class e_parse * * @param string $path The file path of the image whose alternate text is being cached. * @param string $value The alternate text value to cache. - * @return string or false on failure + * @return string|false String or false on failure */ public function setImageAltCacheFile($path, $value) { @@ -3343,7 +3343,7 @@ class e_parse $replace = ((string) $mode === 'full' || (string) $mode === 'abs') ? $replace_absolute : $replace_relative; - return str_replace($search, $replace, $text); + return !empty($text) ? str_replace($search, $replace, $text) : $text; } // $pattern = ($all ? "#\{([A-Za-z_0-9]*)\}#s" : "#\{(e_[A-Z]*)\}#s"); @@ -4670,8 +4670,9 @@ class e_parse * 'legacy' => (array) Usually a legacy path like {e_FILE} * 'type' => (array) Force the returned image to be a jpg, webp etc. * ] - * @return string + * * @example $tp->toImage('welcome.png', array('legacy'=>{e_IMAGE}newspost_images/','w'=>200)); + * @return string|null */ public function toImage($file, $parm = array()) { @@ -5250,7 +5251,7 @@ class e_parse * * @param integer $datestamp - unix timestamp * @param string $format - short | long | relative - * @return string converted date (html) + * @return string|null converted date (html) */ public function toDate($datestamp = null, $format = 'short') { @@ -5500,11 +5501,7 @@ class e_parse // Set it up for processing. libxml_use_internal_errors(true); - if (function_exists('mb_convert_encoding')) - { - $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'); - - } + $html = mb_encode_numericentity($html, [0x80, 0xffff, 0, 0xffff], 'UTF-8'); // $fragment = $doc->createDocumentFragment(); // $fragment->appendXML($html); diff --git a/e107_handlers/plugin_class.php b/e107_handlers/plugin_class.php index 0bf46dd35..4917939b7 100644 --- a/e107_handlers/plugin_class.php +++ b/e107_handlers/plugin_class.php @@ -1577,7 +1577,7 @@ class e107plugin * Returns an array containing details of all plugins in the plugin table - should normally use e107plugin::update_plugins_table() first to * make sure the table is up to date. (Primarily called from plugin manager to get lists of installed and uninstalled plugins. * @param string $path - * @return int + * @return int|false */ private function getId($path) { @@ -2086,7 +2086,7 @@ class e107plugin /** * Type number to type name * @param integer $typeId - * @return string type name + * @return string|int type name */ private function ue_field_type_name($typeId) { @@ -2941,7 +2941,7 @@ class e107plugin * 'delete_xfields' - to delete extended fields * 'delete_ipool' - to delete icon pool entry * + any defined in _setup.php in the uninstall_options() method. - * @return bool + * @return bool|null */ function install_plugin_xml($id, $function = '', $options = null) { @@ -4411,7 +4411,7 @@ class e107plugin if (class_exists($class_name)) { $obj = new $class_name; - $obj->version_from = $this; + // $obj->version_from = $this; // Not used? if (method_exists($obj, $method_name)) { diff --git a/e107_tests/codeception.yml b/e107_tests/codeception.yml index f8e0fd1b5..32fe16d76 100644 --- a/e107_tests/codeception.yml +++ b/e107_tests/codeception.yml @@ -36,4 +36,6 @@ modules: password: '%db.password%' populate: '%db.populate%' dump: '%db.dump_path%' +settings: + error_level: 28671 # E_ALL & ~E_USER_DEPRECATED diff --git a/e107_tests/tests/unit/e_parseTest.php b/e107_tests/tests/unit/e_parseTest.php index e51e6bbcc..b3abf93a8 100644 --- a/e107_tests/tests/unit/e_parseTest.php +++ b/e107_tests/tests/unit/e_parseTest.php @@ -3147,6 +3147,7 @@ Your browser does not support the audio tag. 'expected' => 'Τη γλώσσα μου έδωσαν ελληνική 您好,世界 こんにちは、世界', ), + ); @@ -3184,6 +3185,92 @@ Your browser does not support the audio tag. } + + public function testToUTF8() + { + $converter = $this->tp; + + // Test simple string + $this::assertEquals('Hello World', + $converter->toUTF8('Hello World'), + 'Simple ASCII string should remain unchanged' + ); + + // Test special characters + $this::assertEquals('café', + $converter->toUTF8(mb_convert_encoding('café', 'ISO-8859-1', 'UTF-8')), + 'Latin-1 encoded string should be converted correctly' + ); + + // Test array with special characters + $inputArray = [ + 'name' => mb_convert_encoding('café', 'ISO-8859-1', 'UTF-8'), + 'city' => mb_convert_encoding('München', 'ISO-8859-1', 'UTF-8') + ]; + $expectedArray = [ + 'name' => 'café', + 'city' => 'München' + ]; + $this::assertEquals($expectedArray, + $converter->toUTF8($inputArray), + 'Array with special characters should be converted correctly' + ); + + // Test nested array + $nestedArray = [ + 'level1' => [ + 'level2' => mb_convert_encoding('São Paulo', 'ISO-8859-1', 'UTF-8'), + 'array' => ['deep' => mb_convert_encoding('über', 'ISO-8859-1', 'UTF-8')] + ] + ]; + $expectedNested = [ + 'level1' => [ + 'level2' => 'São Paulo', + 'array' => ['deep' => 'über'] + ] + ]; + $this::assertEquals($expectedNested, + $converter->toUTF8($nestedArray), + 'Nested array should be converted correctly' + ); + + // Test object + $testObject = new stdClass(); + $testObject->name = mb_convert_encoding('café', 'ISO-8859-1', 'UTF-8'); + $testObject->location = mb_convert_encoding('München', 'ISO-8859-1', 'UTF-8'); + + $expectedObject = new stdClass(); + $expectedObject->name = 'café'; + $expectedObject->location = 'München'; + + $this::assertEquals($expectedObject, + $converter->toUTF8($testObject), + 'Object properties should be converted correctly' + ); + + // Test array with various Western European characters + $inputArray = [ + 'french' => mb_convert_encoding('café', 'ISO-8859-1', 'UTF-8'), + 'german' => mb_convert_encoding('Köln', 'ISO-8859-1', 'UTF-8'), + 'spanish' => mb_convert_encoding('año', 'ISO-8859-1', 'UTF-8'), + 'swedish' => mb_convert_encoding('björn', 'ISO-8859-1', 'UTF-8') + ]; + + $expectedArray = [ + 'french' => 'café', + 'german' => 'Köln', + 'spanish' => 'año', + 'swedish' => 'björn' + ]; + + $this::assertEquals($expectedArray, + $converter->toUTF8($inputArray), + 'Array with Western European characters should be converted correctly' + ); + } + + + /* public function testSecureAttributeValue() {