fix: strip invalid XML characters from responses
This commit is contained in:
1 parent
b047465339
commit
e9766dbdce
3 files changed
+147
-1
No files matched your search
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\BusProNet\Utility;
|
||||
|
||||
use App\BusProNet\Utility\XmlCharacterFilter;
|
||||
use App\BusProNet\XmlCrawlerFactory;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class XmlCharacterFilterTest extends TestCase
|
||||
{
|
||||
public function testNulPaddedFieldNoLongerBreaksTheResponse(): void
|
||||
{
|
||||
// Shape of a real KUNDENKONTO/Adressdaten response with a NUL-padded Geburtsort.
|
||||
$xml = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="KUNDENKONTO"></satz>'
|
||||
.'<idperson>11297</idperson><adressdaten><name>Muster</name>'
|
||||
.'<geburtsort>'.str_repeat('�', 40).'</geburtsort><beruf></beruf></adressdaten></ergebnis>';
|
||||
|
||||
$this->assertCount(0, XmlCrawlerFactory::create($xml));
|
||||
|
||||
$filtered = XmlCharacterFilter::strip($xml, $count);
|
||||
|
||||
$this->assertSame(40, $count);
|
||||
$crawler = XmlCrawlerFactory::create($filtered);
|
||||
$this->assertSame('Muster', $crawler->filterXPath('//adressdaten/name')->text());
|
||||
$this->assertSame('', $crawler->filterXPath('//adressdaten/geburtsort')->text());
|
||||
}
|
||||
|
||||
/** @return iterable<string, array{string}> */
|
||||
public static function invalidProvider(): iterable
|
||||
{
|
||||
yield 'hex NUL' => ['�'];
|
||||
yield 'hex NUL, padded and upper case' => ['�'];
|
||||
yield 'decimal NUL' => ['�'];
|
||||
yield 'vertical tab' => [''];
|
||||
yield 'decimal 31' => [''];
|
||||
yield 'surrogate' => ['�'];
|
||||
yield 'noncharacter FFFE' => [''];
|
||||
yield 'beyond Unicode' => ['�'];
|
||||
yield 'raw NUL byte' => ["\x00"];
|
||||
yield 'raw escape byte' => ["\x1B"];
|
||||
}
|
||||
|
||||
#[DataProvider('invalidProvider')]
|
||||
public function testRemovesInvalidCharacters(string $invalid): void
|
||||
{
|
||||
$this->assertSame('<a>xy</a>', XmlCharacterFilter::strip('<a>x'.$invalid.'y</a>', $count));
|
||||
$this->assertSame(1, $count);
|
||||
}
|
||||
|
||||
/** @return iterable<string, array{string}> */
|
||||
public static function validProvider(): iterable
|
||||
{
|
||||
yield 'tab' => ['	'];
|
||||
yield 'line feed' => [' '];
|
||||
yield 'carriage return' => ['
'];
|
||||
yield 'space' => [' '];
|
||||
yield 'umlaut' => ['ü'];
|
||||
yield 'emoji' => ['😀'];
|
||||
yield 'named entity' => ['&'];
|
||||
yield 'raw tab and newline' => ["\t\r\n"];
|
||||
yield 'raw UTF-8' => ['Grüße 😀'];
|
||||
}
|
||||
|
||||
#[DataProvider('validProvider')]
|
||||
public function testKeepsAllowedCharacters(string $valid): void
|
||||
{
|
||||
$xml = '<a>x'.$valid.'y</a>';
|
||||
|
||||
$this->assertSame($xml, XmlCharacterFilter::strip($xml, $count));
|
||||
$this->assertSame(0, $count);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user