From 1ac1d8c2eb1fa253254a76f57394ca244b0a7c8e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 15 May 2026 12:12:28 +0200 Subject: [PATCH] Fix LibOPML warnings (#8652) * Fix LibOPML warnings Fix https://github.com/FreshRSS/FreshRSS/issues/8651 Apply the same flags than in other similar calls of FreshRSS Will need to send the patch upstream. * No LIBXML_NOERROR due to unit tests expecting a catch * LIBXML_NOERROR while waiting for better upstream fix * lib_opml fix loadXML warnings fix https://github.com/FreshRSS/FreshRSS/issues/8651 Upstream PR https://framagit.org/marienfressinaud/lib_opml/-/merge_requests/48 * Fix regression https://framagit.org/marienfressinaud/lib_opml/-/merge_requests/51 * Temporarily use fork --- lib/.gitignore | 4 ++ lib/composer.json | 6 ++- lib/marienfressinaud/lib_opml/.gitignore | 1 + lib/marienfressinaud/lib_opml/.phpcs.xml | 12 ++++++ lib/marienfressinaud/lib_opml/README.md | 2 +- lib/marienfressinaud/lib_opml/composer.json | 8 ++-- .../lib_opml/src/LibOpml/LibOpml.php | 41 +++++++++++++++++-- 7 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 lib/marienfressinaud/lib_opml/.phpcs.xml diff --git a/lib/.gitignore b/lib/.gitignore index baebf27e2..f02286171 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,14 +1,17 @@ autoload.php composer.lock composer/ + marienfressinaud/lib_opml/.git/ marienfressinaud/lib_opml/.gitlab-ci.yml marienfressinaud/lib_opml/.gitlab/ +marienfressinaud/lib_opml/.phpunit.xml marienfressinaud/lib_opml/ci/ marienfressinaud/lib_opml/examples/ marienfressinaud/lib_opml/Makefile marienfressinaud/lib_opml/src/functions.php marienfressinaud/lib_opml/tests/ + phpgt/cssxpath/.* phpgt/cssxpath/composer.json phpgt/cssxpath/CONTRIBUTING.md @@ -24,6 +27,7 @@ phpmailer/phpmailer/SECURITY* phpmailer/phpmailer/src/DSNConfigurator.php phpmailer/phpmailer/src/OAuth* phpmailer/phpmailer/src/POP3.php + simplepie/simplepie/.* !simplepie/simplepie/.editorconfig !simplepie/simplepie/.github/README.md diff --git a/lib/composer.json b/lib/composer.json index eba6a1b9d..7663974fa 100644 --- a/lib/composer.json +++ b/lib/composer.json @@ -8,10 +8,14 @@ { "type": "git", "url": "https://github.com/FreshRSS/simplepie.git" + }, + { + "type": "git", + "url": "https://framagit.org/Alkarex/lib_opml.git" } ], "require": { - "marienfressinaud/lib_opml": "0.5.1", + "marienfressinaud/lib_opml": "dev-relax-non-fatal-errors#f0e850b6394af90b898daf0e65fcc7363457b844", "phpgt/cssxpath": "v1.5.0", "phpmailer/phpmailer": "7.0.2", "simplepie/simplepie": "dev-freshrss#33e4bcf5685192b0fa4c9819f0813b47c3d22424" diff --git a/lib/marienfressinaud/lib_opml/.gitignore b/lib/marienfressinaud/lib_opml/.gitignore index ca9baaf91..59f8b7e31 100644 --- a/lib/marienfressinaud/lib_opml/.gitignore +++ b/lib/marienfressinaud/lib_opml/.gitignore @@ -1,2 +1,3 @@ /coverage /vendor +/.phpunit-cache diff --git a/lib/marienfressinaud/lib_opml/.phpcs.xml b/lib/marienfressinaud/lib_opml/.phpcs.xml new file mode 100644 index 000000000..76f9e8fcf --- /dev/null +++ b/lib/marienfressinaud/lib_opml/.phpcs.xml @@ -0,0 +1,12 @@ + + + The coding standard for lib_opml. + + examples + src + tests + + + + + diff --git a/lib/marienfressinaud/lib_opml/README.md b/lib/marienfressinaud/lib_opml/README.md index 34026bc14..cfc58ca8c 100644 --- a/lib/marienfressinaud/lib_opml/README.md +++ b/lib/marienfressinaud/lib_opml/README.md @@ -7,7 +7,7 @@ structure arranged to show hierarchical relationships). It is mainly used to exchange list of feeds between feed aggregators. The specification is available at [opml.org](http://opml.org). -lib\_opml has been tested with PHP 7.2+. It requires [DOMDocument](https://www.php.net/manual/book.dom.php) +lib\_opml has been tested with PHP 8.2+. It requires [DOMDocument](https://www.php.net/manual/book.dom.php) to work. It supports versions 1.0 and 2.0 of OPML since these are the only published diff --git a/lib/marienfressinaud/lib_opml/composer.json b/lib/marienfressinaud/lib_opml/composer.json index ba48d16ed..6250631ed 100644 --- a/lib/marienfressinaud/lib_opml/composer.json +++ b/lib/marienfressinaud/lib_opml/composer.json @@ -9,12 +9,12 @@ } ], "require": { - "php": ">=7.2.0", + "php": ">=8.2", "ext-dom": "*" }, "config": { "platform": { - "php": "7.2.0" + "php": "8.2" } }, "support": { @@ -29,7 +29,7 @@ } }, "require-dev": { - "squizlabs/php_codesniffer": "^3.6", - "phpunit/phpunit": "^8" + "squizlabs/php_codesniffer": "^4.0", + "phpunit/phpunit": "^11.0" } } diff --git a/lib/marienfressinaud/lib_opml/src/LibOpml/LibOpml.php b/lib/marienfressinaud/lib_opml/src/LibOpml/LibOpml.php index ed5e51756..7ba4cc37d 100644 --- a/lib/marienfressinaud/lib_opml/src/LibOpml/LibOpml.php +++ b/lib/marienfressinaud/lib_opml/src/LibOpml/LibOpml.php @@ -143,18 +143,30 @@ class LibOpml */ public function parseString($xml) { + $xml = trim($xml); + + if (!$xml) { + throw new Exception('OPML string cannot be empty'); + } + $dom = new \DOMDocument(); $dom->recover = true; $dom->encoding = 'UTF-8'; + libxml_use_internal_errors(true); + try { - $result = @$dom->loadXML($xml); + $result = $dom->loadXML($xml, LIBXML_NONET | LIBXML_NOWARNING); + $error = $this->getLibxmlError(); } catch (\Exception | \Error $e) { $result = false; + $error = $e->getMessage(); } - if (!$result || !$dom->documentElement) { - throw new Exception('OPML string is not valid XML'); + libxml_use_internal_errors(false); + + if ($error) { + throw new Exception($error); } $opml_element = $dom->documentElement; @@ -767,4 +779,27 @@ class LibOpml throw new Exception($message); } } + + /** + * Return a formatted error if any libxml error is returned by + * libxml_get_errors(). In non-strict mode, only fatal errors are reported. + */ + private function getLibxmlError(): string + { + $libxml_error = ''; + $errors = libxml_get_errors(); + + foreach ($errors as $error) { + if (!$this->strict && $error->level < LIBXML_ERR_FATAL) { + continue; + } + + $message = trim($error->message); + $message .= " (line {$error->line}, column {$error->column}, code {$error->code})"; + + $libxml_error .= $message . "\n"; + } + + return trim($libxml_error); + } }