Skip to content

Commit

Permalink
Merge pull request #48 from simplesamlphp/feature/simplify-schema-val…
Browse files Browse the repository at this point in the history
…idation

Bugfix: use libxml_get_errors instead of looping over libxml_get_last…
  • Loading branch information
tvdijen authored Dec 14, 2024
2 parents 7d7dc3d + 419687c commit ea339c4
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 33 deletions.
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
"ext-libxml": "*",
"ext-pcre": "*",
"ext-spl": "*",
"ext-xmlreader": "*",

"simplesamlphp/assert": "^1.2",
"simplesamlphp/composer-xmlprovider-installer": "~1.0.0",
Expand Down
34 changes: 11 additions & 23 deletions src/DOMDocumentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,19 @@
namespace SimpleSAML\XML;

use DOMDocument;
use Exception;
use LibXMLError;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Exception\IOException;
use SimpleSAML\XML\Exception\RuntimeException;
use SimpleSAML\XML\Exception\SchemaViolationException;
use SimpleSAML\XML\Exception\UnparseableXMLException;
use XMLReader;

use function array_unique;
use function file_exists;
use function file_get_contents;
use function func_num_args;
use function implode;
use function libxml_clear_errors;
use function libxml_get_last_error;
use function libxml_get_errors;
use function libxml_set_external_entity_loader;
use function libxml_use_internal_errors;
use function sprintf;
Expand Down Expand Up @@ -150,29 +148,19 @@ public static function schemaValidation(
string $schemaFile,
int $options = self::DEFAULT_OPTIONS,
): void {
$xmlReader = XMLReader::XML($xml, null, $options);
Assert::notFalse($xmlReader, SchemaViolationException::class);

libxml_use_internal_errors(true);

try {
$xmlReader->setSchema($schemaFile);
} catch (Exception) {
$err = libxml_get_last_error();
throw new SchemaViolationException(trim($err->message) . ' on line ' . $err->line);
if (!file_exists($schemaFile)) {
throw new IOException('File not found.');
}

$msgs = [];
while ($xmlReader->read()) {
if (!$xmlReader->isValid()) {
$err = libxml_get_last_error();
if ($err instanceof LibXMLError) {
$msgs[] = trim($err->message) . ' on line ' . $err->line;
}
$document = DOMDocumentFactory::fromString($xml);
$result = $document->schemaValidate($schemaFile);

if ($result === false) {
$msgs = [];
foreach (libxml_get_errors() as $err) {
$msgs[] = trim($err->message) . ' on line ' . $err->line;
}
}

if ($msgs) {
throw new SchemaViolationException(sprintf(
"XML schema validation errors:\n - %s",
implode("\n - ", array_unique($msgs)),
Expand Down
19 changes: 10 additions & 9 deletions tests/XML/DOMDocumentFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace SimpleSAML\Test\XML;

use DOMDocument;
use Exception;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
Expand All @@ -15,8 +14,6 @@
use SimpleSAML\XML\Exception\SchemaViolationException;
use SimpleSAML\XML\Exception\UnparseableXMLException;

use function restore_error_handler;
use function set_error_handler;
use function strval;

/**
Expand Down Expand Up @@ -145,13 +142,17 @@ public function testSchemaValidationUnknownSchemaFileFails(): void
$file = 'tests/resources/xml/ssp_Chunk.xml';
$schemaFile = 'tests/resources/schemas/doesnotexist.xsd';

// Dirty trick to catch the warning emitted by PHP
set_error_handler(static function (int $errno, string $errstr): never {
restore_error_handler();
throw new Exception($errstr, $errno);
}, E_WARNING);
$this->expectExceptionMessage('File not found.');
DOMDocumentFactory::fromFile($file, $schemaFile);
}

$this->expectExceptionMessage('Failed to locate the main schema resource at');

public function testSchemaValidationInvalidSchemaFileFails(): void
{
$file = 'tests/resources/xml/ssp_Chunk.xml';
$schemaFile = 'resources/schemas/xml.xsd';

$this->expectException(SchemaViolationException::class);
DOMDocumentFactory::fromFile($file, $schemaFile);
}
}

0 comments on commit ea339c4

Please sign in to comment.