Files
2026-08-30 22:02:02 +00:00

139 lines
4.5 KiB
PHP

<?php
/**
* ParserTest.php
*
* @since 2011-05-23
* @category Library
* @package Pdfparser
* @author Nicola Asuni <info@tecnick.com>
* @copyright 2011-2026 Nicola Asuni - Tecnick.com LTD
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
* @link https://github.com/tecnickcom/tc-lib-pdf-parser
*
* This file is part of tc-lib-pdf-parser software library.
*/
namespace Test;
use Com\Tecnick\Pdf\Parser\Parser;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
/**
* Filter Test
*
* @since 2011-05-23
* @category Library
* @package PdfParser
* @author Nicola Asuni <info@tecnick.com>
* @copyright 2011-2026 Nicola Asuni - Tecnick.com LTD
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
* @link https://github.com/tecnickcom/tc-lib-pdf-parser
*/
class ParserTest extends TestCase
{
/**
* @throws \Com\Tecnick\Pdf\Parser\Exception
*/
#[DataProvider('getParseProvider')]
public function testParse(string $filename, string $hash): void
{
$cfg = [
'ignore_filter_errors' => true,
];
$rawdata = \file_get_contents($filename);
$this->assertNotFalse($rawdata);
$parser = new Parser($cfg);
$data = $parser->parse($rawdata);
$this->assertEquals($hash, \md5(\serialize($data)));
}
/**
* @return array<int, array{0:string, 1:string}>
*/
public static function getParseProvider(): array
{
return [
['resources/test/example_005.pdf', '510a5ea860470dae0781f4bd8d5eb250'],
['resources/test/example_036.pdf', '2869501cf41a4c4a0402c00832329e25'],
['resources/test/example_046.pdf', 'cfaee514b9c09aa282b4e2a8f0061a3d'],
];
}
/**
* @throws \Com\Tecnick\Pdf\Parser\Exception
*/
public function testParseHandlesMultiRangeXrefIndexRegression(): void
{
$parser = new Parser(['ignore_filter_errors' => true]);
$data = $parser->parse($this->buildMultiRangeXrefIndexPdf());
$xref = $data[0];
$objects = $data[1];
$this->assertSame('41_0', $xref['trailer']['root']);
$this->assertArrayNotHasKey('encrypt', $xref['trailer']);
$this->assertNotNull($objects['41_0'][0] ?? null);
$this->assertSame('<<', $objects['41_0'][0][0]);
$this->assertNotNull($objects['42_0'][0] ?? null);
$this->assertSame('<<', $objects['42_0'][0][0]);
$this->assertNotNull($objects['43_0'][0] ?? null);
$this->assertSame('<<', $objects['43_0'][0][0]);
$this->assertSame('7aa83a972ca79bafe26be3620b7512e2', \md5(\serialize($data)));
}
private function buildMultiRangeXrefIndexPdf(): string
{
$pdf = "%PDF-1.7\n";
$offsets = [];
$addObject = static function (string &$pdfData, array &$objOffsets, int $objNum, string $body): void {
$objOffsets[$objNum] = \strlen($pdfData);
$pdfData .= $objNum . " 0 obj\n" . $body . "\nendobj\n";
};
$addObject($pdf, $offsets, 3, '<< /Dummy 3 >>');
$addObject($pdf, $offsets, 15, '<< /Dummy 15 >>');
$addObject($pdf, $offsets, 17, '<< /Dummy 17 >>');
$addObject($pdf, $offsets, 18, '<< /Dummy 18 >>');
$addObject($pdf, $offsets, 41, '<< /Type /Catalog /Pages 42 0 R >>');
$addObject($pdf, $offsets, 42, '<< /Type /Pages /Count 1 /Kids [43 0 R] >>');
$addObject($pdf, $offsets, 43, '<< /Type /Page /Parent 42 0 R /MediaBox [0 0 10 10] >>');
$indexObjects = [3, 15, 17, 18, 41, 42, 43];
$bytes = [];
foreach ($indexObjects as $objNum) {
$offset = (int) ($offsets[$objNum] ?? 0);
$bytes[] = 0;
$bytes[] = 1;
$bytes[] = ($offset >> 16) & 0xff;
$bytes[] = ($offset >> 8) & 0xff;
$bytes[] = $offset & 0xff;
}
$stream = \pack('C*', ...$bytes);
$streamLen = \strlen($stream);
$xrefBody =
'<< /Type /XRef'
. ' /Size 60'
. ' /Root 41 0 R'
. ' /Index [3 1 15 1 17 2 41 3]'
. ' /W [1 3 0]'
. ' /Length '
. $streamLen
. ' /DecodeParms << /Columns 4 /Predictor 12 >>'
. " >>\nstream\n"
. $stream
. "\nendstream";
$addObject($pdf, $offsets, 50, $xrefBody);
$startxref = (int) ($offsets[50] ?? 0);
$pdf .= "startxref\n" . $startxref . "\n%%EOF";
return $pdf;
}
}