diff --git a/src/Document/Dictionary/DictionaryValue/Name/FilterNameValue.php b/src/Document/Dictionary/DictionaryValue/Name/FilterNameValue.php index ede13c9..f81a6f3 100644 --- a/src/Document/Dictionary/DictionaryValue/Name/FilterNameValue.php +++ b/src/Document/Dictionary/DictionaryValue/Name/FilterNameValue.php @@ -7,6 +7,7 @@ use PrinsFrank\PdfParser\Document\Dictionary\DictionaryKey\DictionaryKey; use PrinsFrank\PdfParser\Document\Dictionary\DictionaryValue\Integer\IntegerValue; use PrinsFrank\PdfParser\Document\Document; +use PrinsFrank\PdfParser\Document\Filter\Decode\ASCII85Decode; use PrinsFrank\PdfParser\Document\Filter\Decode\CCITTFaxDecode; use PrinsFrank\PdfParser\Document\Filter\Decode\FlateDecode; use PrinsFrank\PdfParser\Document\Filter\Decode\LZWFlatePredictorValue; @@ -54,6 +55,7 @@ public function decodeBinary(string $content, ?Dictionary $dictionary, ?Document $decodeParams->getValueForKey(DictionaryKey::K, IntegerValue::class)->value ?? throw new ParseFailureException('Missing K'), ), + self::ASCII_85_DECODE => ASCII85Decode::decodeBinary($content), default => throw new ParseFailureException(sprintf('Content "%.100s..." cannot be decoded for filter "%s"', $content, $this->name)) }; } diff --git a/src/Document/Filter/Decode/ASCII85Decode.php b/src/Document/Filter/Decode/ASCII85Decode.php new file mode 100644 index 0000000..6290044 --- /dev/null +++ b/src/Document/Filter/Decode/ASCII85Decode.php @@ -0,0 +1,53 @@ +')) { + $string = substr($string, 2, -2); + } + + $string = preg_replace('/\s+/', '', $string) + ?? throw new RuntimeException('An unexpected error occurred while sanitizing ASCII85 string'); + $length = strlen($string); + $decoded = $block = ''; + for ($i = 0; $i < $length; ++$i) { + $char = $string[$i]; + if ($char === 'z') { + $decoded .= "\0\0\0\0"; + continue; + } + + $block .= $char; + if (strlen($block) === 5) { + $value = 0; + for ($j = 0; $j < 5; ++$j) { + $value = $value * 85 + (ord($block[$j]) - 33); + } + + $decoded .= pack('N', $value); + $block = ''; + } + } + + if ($block !== '') { + $padding = 5 - strlen($block); + $block = str_pad($block, 5, 'u'); + $value = 0; + for ($i = 0; $i < 5; ++$i) { + $value = $value * 85 + (ord($block[$i]) - 33); + } + + $binaryData = pack('N', $value); + $decoded .= substr($binaryData, 0, 4 - $padding); + } + + return $decoded; + } +} diff --git a/tests/Samples/Info/FileInfo.php b/tests/Samples/Info/FileInfo.php index 0938686..48d1202 100644 --- a/tests/Samples/Info/FileInfo.php +++ b/tests/Samples/Info/FileInfo.php @@ -5,7 +5,10 @@ use DateTimeImmutable; class FileInfo { - /** @param list $pages */ + /** + * @param list $pages + * @param string[] $textPartsExpectedSomewhereInTheExtractedText + */ public function __construct( public readonly string $pdfPath, public readonly int $version, @@ -17,6 +20,7 @@ public function __construct( public readonly ?DateTimeImmutable $creationDate, public readonly ?DateTimeImmutable $modificationDate, public readonly ?array $pages, + public readonly ?array $textPartsExpectedSomewhereInTheExtractedText, ) { } } diff --git a/tests/Samples/Info/SampleProvider.php b/tests/Samples/Info/SampleProvider.php index 7b93e0f..13d66a9 100644 --- a/tests/Samples/Info/SampleProvider.php +++ b/tests/Samples/Info/SampleProvider.php @@ -2,6 +2,7 @@ namespace PrinsFrank\PdfParser\Tests\Samples\Info; +use DateTimeImmutable; use RuntimeException; use Symfony\Component\Yaml\Yaml; @@ -23,12 +24,22 @@ public static function samples(): iterable { throw new RuntimeException(); } - /** @var object{version: float, password: ?string, title: ?string, producer: ?string, author: ?string, creator: ?string, creationDate: ?\DateTimeImmutable, modificationDate: ?\DateTimeImmutable, pages: list} $content */ + /** @var object{version: float, password: ?string, title: ?string, producer: ?string, author: ?string, creator: ?string, creationDate: ?\DateTimeImmutable, modificationDate: ?\DateTimeImmutable, pages: list, textPartsExpectedSomewhereInTheExtractedText: string[]|null} $content */ $content = Yaml::parseFile($contentsPath, Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE | Yaml::PARSE_DATETIME); if ($content->password !== null) { continue; } + $creationDate = null; + if (is_string($content->creationDate)) { + $creationDate = new DateTimeImmutable($content->creationDate); + } + + $modificationDate = null; + if (is_string($content->modificationDate)) { + $modificationDate = new DateTimeImmutable($content->modificationDate); + } + yield $sampleName => [ new FileInfo( $pdfPath, @@ -38,16 +49,17 @@ public static function samples(): iterable { $content->producer, $content->author, $content->creator, - $content->creationDate, - $content->modificationDate, + $creationDate, + $modificationDate, array_map( /** @param object{content: string, images?: string[]} $page */ fn (object $page) => new Page( $page->content, array_values(array_map(fn (string $relativePath) => sprintf('%s/images/%s', $sampleFolder, $relativePath), $page->images ?? [])) ), - $content->pages + $content->pages ?? [] ), + $content->textPartsExpectedSomewhereInTheExtractedText ?? null ) ]; } diff --git a/tests/Samples/SamplesTest.php b/tests/Samples/SamplesTest.php index 625b24b..49fc968 100644 --- a/tests/Samples/SamplesTest.php +++ b/tests/Samples/SamplesTest.php @@ -20,15 +20,56 @@ class SamplesTest extends TestCase { #[DataProviderExternal(SampleProvider::class, 'samples')] public function testExternalSourcePDFs(FileInfo $fileInfo): void { $document = (new PdfParser())->parseFile($fileInfo->pdfPath); + + // PDF version static::assertSame(Version::from(number_format($fileInfo->version / 10, 1)), $document->version); - static::assertSame($fileInfo->title, $document->getInformationDictionary()?->getTitle()); - static::assertSame($fileInfo->producer, $document->getInformationDictionary()?->getProducer()); - static::assertSame($fileInfo->author, $document->getInformationDictionary()?->getAuthor()); - static::assertSame($fileInfo->creator, $document->getInformationDictionary()?->getCreator()); - static::assertEquals($fileInfo->creationDate, $document->getInformationDictionary()?->getCreationDate()); - static::assertEquals($fileInfo->modificationDate, $document->getInformationDictionary()?->getModificationDate()); - static::assertSame(count($fileInfo->pages ?? []), $document->getNumberOfPages()); - foreach ($fileInfo->pages ?? [] as $index => $expectedPage) { + + // title + if (null !== $fileInfo->title) { + static::assertSame($fileInfo->title, $document->getInformationDictionary()?->getTitle()); + } + + // producer + if (null !== $fileInfo->producer) { + static::assertSame($fileInfo->producer, $document->getInformationDictionary()?->getProducer()); + } + + // author + if (null !== $fileInfo->author) { + static::assertSame($fileInfo->author, $document->getInformationDictionary()?->getAuthor()); + } + + // creator + if (null !== $fileInfo->creator) { + static::assertSame($fileInfo->creator, $document->getInformationDictionary()?->getCreator()); + } + + // creation date + if (null !== $fileInfo->creationDate) { + static::assertEquals($fileInfo->creationDate, $document->getInformationDictionary()?->getCreationDate()); + } + + // modification date + if (null !== $fileInfo->modificationDate) { + static::assertEquals($fileInfo->modificationDate, $document->getInformationDictionary()?->getModificationDate()); + } + + /* + * Check content related expectations + */ + if (is_array($fileInfo->textPartsExpectedSomewhereInTheExtractedText)) { + foreach ($fileInfo->textPartsExpectedSomewhereInTheExtractedText as $textPart) { + static::assertStringContainsString($textPart, $document->getText()); + } + } + + /* + * Check content of pages (fulltext) + */ + $pages = $fileInfo->pages ?? []; + static::assertSame(count($pages), $document->getNumberOfPages()); + + foreach ($pages as $index => $expectedPage) { static::assertNotNull($page = $document->getPage($index + 1)); static::assertSame(trim($expectedPage->content), trim($page->getText())); foreach ($expectedPage->imagePaths as $imageIndex => $imagePath) { diff --git a/tests/Samples/files/gdocs-hello-world-simple/contents.yml b/tests/Samples/files/gdocs-hello-world-simple/contents.yml index ddf13c3..9262f9a 100644 --- a/tests/Samples/files/gdocs-hello-world-simple/contents.yml +++ b/tests/Samples/files/gdocs-hello-world-simple/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.4' -password: null +userPassword: null +ownerPassword: null title: 'Untitled document' producer: 'Skia/PDF m133 Google Docs Renderer' author: null diff --git a/tests/Samples/files/gdocs-image-simple/contents.yml b/tests/Samples/files/gdocs-image-simple/contents.yml index b173803..4f3e312 100644 --- a/tests/Samples/files/gdocs-image-simple/contents.yml +++ b/tests/Samples/files/gdocs-image-simple/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.4' -password: null +userPassword: null +ownerPassword: null title: 'File with image' producer: 'Skia/PDF m138 Google Docs Renderer' author: null diff --git a/tests/Samples/files/gdocs-lorem-ipsum-with-titles-and-formatting/contents.yml b/tests/Samples/files/gdocs-lorem-ipsum-with-titles-and-formatting/contents.yml index 2f0c1c6..049df87 100644 --- a/tests/Samples/files/gdocs-lorem-ipsum-with-titles-and-formatting/contents.yml +++ b/tests/Samples/files/gdocs-lorem-ipsum-with-titles-and-formatting/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.4' -password: null +userPassword: null +ownerPassword: null title: 'lorem ipsum' producer: 'Skia/PDF m133 Google Docs Renderer' author: null diff --git a/tests/Samples/files/gdocs-scripts/contents.yml b/tests/Samples/files/gdocs-scripts/contents.yml index edd1452..103ee2e 100644 --- a/tests/Samples/files/gdocs-scripts/contents.yml +++ b/tests/Samples/files/gdocs-scripts/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.4' -password: null +userPassword: null +ownerPassword: null title: Scripts producer: 'Skia/PDF m134 Google Docs Renderer' author: null diff --git a/tests/Samples/files/issue-127/contents.yml b/tests/Samples/files/issue-127/contents.yml index b68d962..1663177 100644 --- a/tests/Samples/files/issue-127/contents.yml +++ b/tests/Samples/files/issue-127/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '2.0' -password: null +userPassword: null +ownerPassword: null title: !!binary /v8AMQAuADIAIABUAGEAYgBlAGwAbABlAF8AMQBfAEsAQQBfADEAOQAtADAANwAwADUAOQ== producer: 'Kofax Power PDF' author: 'Rehm, Martin (LSN)' diff --git a/tests/Samples/files/issue-149/contents.yml b/tests/Samples/files/issue-149/contents.yml index 1462baa..8356650 100644 --- a/tests/Samples/files/issue-149/contents.yml +++ b/tests/Samples/files/issue-149/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: '(Dossier représentation Mme BEGOT-3.pdf)' producer: 'GPL Ghostscript 10.03.1' author: mgomes03 diff --git a/tests/Samples/files/issue-150/contents.yml b/tests/Samples/files/issue-150/contents.yml index 9f362e6..e0ab106 100644 --- a/tests/Samples/files/issue-150/contents.yml +++ b/tests/Samples/files/issue-150/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.3' -password: null +userPassword: null +ownerPassword: null title: null producer: 'RICOH M C251FW (6577f3)' author: null diff --git a/tests/Samples/files/issue-153/contents.yml b/tests/Samples/files/issue-153/contents.yml new file mode 100644 index 0000000..8255bc5 --- /dev/null +++ b/tests/Samples/files/issue-153/contents.yml @@ -0,0 +1,81 @@ +# yaml-language-server: $schema=./.yml-schema.json +version: '1.4' +password: null +title: reception0658@reseau-intersport.fr +producer: 'Oracle PDF driver' +author: 'Oracle Reports' +creator: 'Oracle12c AS Reports Services' +creationDate: 2025-07-22T10:00:03+00:00 +modificationDate: 2025-07-22T10:00:03+00:00 +pages: + - + content: |- + CUSTOMER IE802719 + INTERSPORT PAIMPOL + SASU C.E.F SPORTS - 17 T RUE RAYMOND PELLIER + 22500 PAIMPOL France + CHAMPION PRODUCTS EUROPE UNLIMITED COMPANY + Blanchardstown Corporate Park 2 D15 Blanchardstown - Dublin Ireland + Tel. Acc. + +353 (0)1 8864217 +353 (0)1 8864217Fax +353 (0)1 8665927 + Tel. CS + IE802719 + DESTINATION + INTERSPORT PAIMPOL + ZONE DE KERPUNS CARREFOUR ILN Code: 3025810065800 + 22500 PAIMPOL France + DELIVERY NOTE + DC REF. + 5204/165/2025/DN/5204 21/07/2025 + FORWARDER + Label + UPS - United Parcel Service S.r.l 2.0 + VIA G. FANTOLI, 15/2 + REASON + 20138 MILANO Milano + Italy + Subcontractor + TRANSPORTATION COST + Delivery Note N + CHH/2025/70BO/058510DATE 21/07/2025 + COMMENTS + SALES REP VORACE SAS François RAMOND + ARTICLE DESCRIPTION COLOUR SIZE TOTAL + ORD. NUM. + 35/38 39/42 43/46 + 8 19 13 + 4402026619 + 3pk Sneaker Socks + U20100-CHA + WW001 WHT + 40 + 40 + 35/38 39/42 43/46 + 8 17 14 + 4402026619 + 3pk Crew Socks + U24558-CHA + KK001 NBK + 39 + 8 17 14 + 4402026619 + WW001 WHT + 39 + 78 + Tot. qty 118 + Cartons Summary + 250570819669 250570830162 + Picking List-N. + CHH-2025-VE-430761 + Packing list W2025/PL/CHH282537 + Leave from + PACKING Cartons Nr 2 Net Wght 16,790 Gross Wght 18,490 + LABEL NOTES + Label + FORWARDER DESTINATION + CIE + Signature Date Time Signature Date Time Signature Date Time + 1 of + Copy for Customer Page 1 + images: + - page_0_image_0.jpg diff --git a/tests/Samples/files/issue-153/file.pdf b/tests/Samples/files/issue-153/file.pdf new file mode 100644 index 0000000..ba86eb7 Binary files /dev/null and b/tests/Samples/files/issue-153/file.pdf differ diff --git a/tests/Samples/files/issue-153/images/page_0_image_0.jpg b/tests/Samples/files/issue-153/images/page_0_image_0.jpg new file mode 100644 index 0000000..0474c54 Binary files /dev/null and b/tests/Samples/files/issue-153/images/page_0_image_0.jpg differ diff --git a/tests/Samples/files/issue-214/contents.yml b/tests/Samples/files/issue-214/contents.yml index f4008a2..6a13755 100644 --- a/tests/Samples/files/issue-214/contents.yml +++ b/tests/Samples/files/issue-214/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: 'PStill Engine 1.90' author: null diff --git a/tests/Samples/files/issue-235/contents.yml b/tests/Samples/files/issue-235/contents.yml index 972fe02..96f4f94 100644 --- a/tests/Samples/files/issue-235/contents.yml +++ b/tests/Samples/files/issue-235/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.6' -password: null +userPassword: null +ownerPassword: null title: '' producer: 'Adobe PDF Library 20.1.50' author: null diff --git a/tests/Samples/files/issue-254/contents.yml b/tests/Samples/files/issue-254/contents.yml index 17bd88c..da8e1dd 100644 --- a/tests/Samples/files/issue-254/contents.yml +++ b/tests/Samples/files/issue-254/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: 'Publications Office' producer: 'PDFlib+PDI 9.1.2p4 (C++/Win64)' author: 'Publications Office' diff --git a/tests/Samples/files/issue-255/contents.yml b/tests/Samples/files/issue-255/contents.yml index 0aebd68..9642271 100644 --- a/tests/Samples/files/issue-255/contents.yml +++ b/tests/Samples/files/issue-255/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: 'PStill Engine 1.90' author: null diff --git a/tests/Samples/files/issue-272/contents.yml b/tests/Samples/files/issue-272/contents.yml new file mode 100644 index 0000000..cae30ec --- /dev/null +++ b/tests/Samples/files/issue-272/contents.yml @@ -0,0 +1,12 @@ +# yaml-language-server: $schema=./.yml-schema.json +version: '1.7' +password: null +title: null +producer: 'PStill Engine 1.90' +author: null +creator: null +creationDate: 2025-10-06T10:48:53.000000+0200 +modificationDate: null +textPartsExpectedSomewhereInTheExtractedText: + - Liposuktion bei Lipödem + diff --git a/tests/Samples/files/issue-272/file.pdf b/tests/Samples/files/issue-272/file.pdf new file mode 100644 index 0000000..6ce13ce Binary files /dev/null and b/tests/Samples/files/issue-272/file.pdf differ diff --git a/tests/Samples/files/libreoffice-hello-world-hybrid/contents.yml b/tests/Samples/files/libreoffice-hello-world-hybrid/contents.yml index cbd8f89..cd6a5ae 100644 --- a/tests/Samples/files/libreoffice-hello-world-hybrid/contents.yml +++ b/tests/Samples/files/libreoffice-hello-world-hybrid/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: 'LibreOffice 24.2' author: null diff --git a/tests/Samples/files/libreoffice-hello-world-open-password-hello/contents.yml b/tests/Samples/files/libreoffice-hello-world-open-password-hello/contents.yml index fc9ebe7..4a0b1b5 100644 --- a/tests/Samples/files/libreoffice-hello-world-open-password-hello/contents.yml +++ b/tests/Samples/files/libreoffice-hello-world-open-password-hello/contents.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: 1.7 password: Hello title: null diff --git a/tests/Samples/files/libreoffice-hello-world-simple/contents.yml b/tests/Samples/files/libreoffice-hello-world-simple/contents.yml index de3afb8..5ac9181 100644 --- a/tests/Samples/files/libreoffice-hello-world-simple/contents.yml +++ b/tests/Samples/files/libreoffice-hello-world-simple/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: 'LibreOffice 24.2' author: null diff --git a/tests/Samples/files/libreoffice-hello-world-watermarked/contents.yml b/tests/Samples/files/libreoffice-hello-world-watermarked/contents.yml index d7c5c34..8103c63 100644 --- a/tests/Samples/files/libreoffice-hello-world-watermarked/contents.yml +++ b/tests/Samples/files/libreoffice-hello-world-watermarked/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: 'LibreOffice 24.2' author: null diff --git a/tests/Samples/files/libreofficelorem-ipsum-with-titles-and-formatting/contents.yml b/tests/Samples/files/libreofficelorem-ipsum-with-titles-and-formatting/contents.yml index 991b0d9..2db529c 100644 --- a/tests/Samples/files/libreofficelorem-ipsum-with-titles-and-formatting/contents.yml +++ b/tests/Samples/files/libreofficelorem-ipsum-with-titles-and-formatting/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: 'LibreOffice 24.2' author: null diff --git a/tests/Samples/files/pdftex-hello-world-simple/contents.yml b/tests/Samples/files/pdftex-hello-world-simple/contents.yml index 081fd50..586f378 100644 --- a/tests/Samples/files/pdftex-hello-world-simple/contents.yml +++ b/tests/Samples/files/pdftex-hello-world-simple/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.5' -password: null +userPassword: null +ownerPassword: null title: null producer: pdfTeX-1.40.25 author: null diff --git a/tests/Samples/files/text-objects-across-multiple-streams/contents.yml b/tests/Samples/files/text-objects-across-multiple-streams/contents.yml index 7341f95..85305c2 100644 --- a/tests/Samples/files/text-objects-across-multiple-streams/contents.yml +++ b/tests/Samples/files/text-objects-across-multiple-streams/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.4' -password: null +userPassword: null +ownerPassword: null title: 'MPK Router Control Interface to 7707DT' producer: 'Acrobat Distiller 5.0.5 (Windows)' author: 'Alex Martin' diff --git a/tests/Samples/files/word365-hello-world-simple/contents.yml b/tests/Samples/files/word365-hello-world-simple/contents.yml index 33ac58d..8d5b5b1 100644 --- a/tests/Samples/files/word365-hello-world-simple/contents.yml +++ b/tests/Samples/files/word365-hello-world-simple/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: null author: 'Frank Prins' diff --git a/tests/Samples/files/word365-lorem-ipsum-with-titles-and-formatting/contents.yml b/tests/Samples/files/word365-lorem-ipsum-with-titles-and-formatting/contents.yml index 7b2250b..505866d 100644 --- a/tests/Samples/files/word365-lorem-ipsum-with-titles-and-formatting/contents.yml +++ b/tests/Samples/files/word365-lorem-ipsum-with-titles-and-formatting/contents.yml @@ -1,6 +1,7 @@ -# yaml-language-server: $schema=./.yml-schema.json +# yaml-language-server: $schema=../../schema.json version: '1.7' -password: null +userPassword: null +ownerPassword: null title: null producer: null author: 'Frank Prins' diff --git a/tests/Samples/schema.json b/tests/Samples/schema.json index e8a8c1f..0aa7bbe 100644 --- a/tests/Samples/schema.json +++ b/tests/Samples/schema.json @@ -6,10 +6,14 @@ "type": "number", "description": "PDF version" }, - "password": { + "userPassword": { "type": ["string", "null"], "description": "Password to open the file" }, + "ownerPassword": { + "type": ["string", "null"], + "description": "Password to restrict document actions" + }, "title": { "type": ["string", "null"], "description": "Title of the document" diff --git a/tests/Samples/update-content b/tests/Samples/update-content index d21b573..9eacf6d 100755 --- a/tests/Samples/update-content +++ b/tests/Samples/update-content @@ -46,7 +46,8 @@ foreach (array_diff(scandir($filesDir = __DIR__ . '/files'), ['..', '.']) as $sa $yamlContent = Yaml::dump( [ 'version' => $parsedPDF->version->value, - 'password' => null, + 'userPassword' => null, + 'ownerPassword' => null, 'title' => $parsedPDF->getInformationDictionary()?->getTitle(), 'producer' => $parsedPDF->getInformationDictionary()?->getProducer(), 'author' => $parsedPDF->getInformationDictionary()?->getAuthor(), @@ -62,6 +63,6 @@ foreach (array_diff(scandir($filesDir = __DIR__ . '/files'), ['..', '.']) as $sa file_put_contents( $sampleFolder . DIRECTORY_SEPARATOR . 'contents.yml', - '# yaml-language-server: $schema=./.yml-schema.json' . PHP_EOL . trim($yamlContent, PHP_EOL) . PHP_EOL + '# yaml-language-server: $schema=../../schema.json' . PHP_EOL . trim($yamlContent, PHP_EOL) . PHP_EOL ); } diff --git a/tests/Unit/Document/Filter/ASCII85DecodeTest.php b/tests/Unit/Document/Filter/ASCII85DecodeTest.php new file mode 100644 index 0000000..2a29fd9 --- /dev/null +++ b/tests/Unit/Document/Filter/ASCII85DecodeTest.php @@ -0,0 +1,37 @@ +Cj@.4Gp$d7F!,L7@<6@)/0JDEF@3BB/F*&OCAfu2/AKYi( + DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF-FD5W8ARlolDIal( + DIdu + D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c + ASCII85 + ) + ); + static::assertSame( + 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.', + ASCII85Decode::decodeBinary( + <<<'ASCII85' + <~9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKFCj@.4Gp$d7F!,L7@<6@)/0JDEF@3BB/F*&OCAfu2/AKYi( + DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF-FD5W8ARlolDIal( + DIdu + D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c~> + ASCII85 + ) + ); + } +}