Przejdź do głównej zawartości
getnextpdf.com

Parsowanie i inspekcja pliku PDF pod kątem faktów strukturalnych

Ten przepis wykorzystuje rezerwowy tryb Quick w inspektorze Core do odczytywania faktów strukturalnych z pliku w formacie Portable Document Format (PDF). Wynik obejmuje wersję, liczbę stron, flagę szyfrowania, flagę podpisu, flagę załączników, rozmiar pliku oraz flagi ryzyka. Tryb Quick działa w całości w tym samym procesie, bez sidecara Spectrum i bez dostępu do sieci. Służy do szybkiej selekcji, nie do walidacji.

Okno terminala
composer require nextpdf/core:^3

Wersja pliku PDF jest zapisana w nagłówku pliku (ISO 32000-2 §7.5.2). Trailer zawiera identyfikator pliku (/ID) złożony z dwóch ciągów bajtów (ISO 32000-2 §7.5.5). Jeśli podpis jest obecny, słownik podpisu przechowuje w Contents strukturę Cryptographic Message Syntax (CMS) SignedData zakodowaną zgodnie z Distinguished Encoding Rules (DER) (ISO 32000-2 §12.8.1). Rezerwowy tryb Quick korzysta z ograniczonego skanowania bajtów dokumentu, aby ustalić wersję, szacunkową liczbę stron oraz flagi obecności szyfrowania, podpisu i załączników.

Utwórz new Inspector(), a następnie wywołaj ->inspect(string $pdfData, InspectConfig::quick()). Metoda zwraca obiekt InspectResult z polami $pdfVersion, $pageCount, $isEncrypted, $hasSigned, $hasAttachments, $fileSizeBytes, $riskFlags oraz metodą pomocniczą hasRisks().

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Inspect\InspectConfig;
use NextPDF\Inspect\Inspector;
$pdf = file_get_contents(__DIR__ . '/document.pdf');
$result = (new Inspector())->inspect($pdf, InspectConfig::quick());
printf(
"v%s, %d page(s), encrypted=%s, signed=%s\n",
$result->pdfVersion ?? '?',
$result->pageCount,
$result->isEncrypted ? 'yes' : 'no',
$result->hasSigned ? 'yes' : 'no',
);

Ten samodzielny program działa w środowisku testowym dla przepisów. Odpowiada examples/39-parse-and-inspect-pdf.php: buduje w pamięci niewielki, wielostronicowy plik PDF, odczytuje jego fakty strukturalne za pomocą rezerwowego trybu Quick i kieruje przetwarzaniem na podstawie tych faktów, nigdy na podstawie werdyktu zaufania. Gałąź kierowania ma charakter poglądowy. Zastąp ją własnym potokiem, kolejką weryfikatora oraz kwarantanną.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Inspect\InspectConfig;
use NextPDF\Inspect\Inspector;
// A self-contained input so the program runs with no external file.
$doc = Document::createStandalone();
$doc->setTitle('Parse-and-inspect demo');
$doc->setAuthor('NextPDF Cookbook');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Page one of the parse-and-inspect demonstration.', newLine: true);
$doc->addPage();
$doc->cell(0, 10, 'Page two.', newLine: true);
$pdf = $doc->getPdfData();
$result = (new Inspector())->inspect($pdf, InspectConfig::quick());
echo 'PDF version : ' . ($result->pdfVersion ?? 'unknown') . "\n";
echo 'Pages : ' . $result->pageCount . "\n";
echo 'Encrypted : ' . ($result->isEncrypted ? 'yes' : 'no') . "\n";
echo 'Signed : ' . ($result->hasSigned ? 'yes' : 'no') . "\n";
echo 'Attachments : ' . ($result->hasAttachments ? 'yes' : 'no') . "\n";
echo 'File size : ' . $result->fileSizeBytes . " bytes\n";
echo 'Risk flags : ' . ($result->hasRisks() ? count($result->riskFlags) : 0) . "\n";
// Route on structural facts, not trust verdicts. Replace these calls with
// your own pipeline / verifier queue / quarantine.
if ($result->isEncrypted) {
// $pipeline->decryptThenContinue($pdf);
echo "Route: decrypt-then-continue\n";
} elseif ($result->hasSigned) {
// $verifierQueue->enqueue($pdf); // see the signature-inspect recipe
echo "Route: enqueue for cryptographic verification\n";
} elseif ($result->hasRisks()) {
// $quarantine->hold($pdf, $result->riskFlags);
echo "Route: quarantine (risk flags present)\n";
} else {
// $pipeline->continue($pdf);
echo "Route: continue (no risks, unsigned, unencrypted)\n";
}
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the
// semantic profile; emit the document to the side-channel.
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
file_put_contents($out !== false && $out !== '' ? $out : __DIR__ . '/inspected.pdf', $pdf);

Oczekiwane wyjście standardowe (STDOUT) (wersja i rozmiar zależą od kompilacji; demonstracyjny plik PDF jest nieszyfrowany, niepodpisany i nie zawiera flag ryzyka):

PDF version : <version>
Pages : 2
Encrypted : no
Signed : no
Attachments : no
File size : <n> bytes
Risk flags : 0
Route: continue (no risks, unsigned, unencrypted)
  • Tryb Quick to selekcja, a nie walidacja. Informuje, co jest obecne, a czego brakuje. Nie weryfikuje podpisów, nie odszyfrowuje treści ani nie potwierdza zgodności. Traktuj wynik jako dane wejściowe do kierowania przetwarzaniem.
  • Liczba stron jest szacunkowa. Rezerwowy tryb Quick zlicza znaczniki obiektów stron. Celowo zniekształcony graf obiektów może zafałszować tę liczbę. Jeśli potrzebna jest dokładna liczba, użyj poziomów głębi opartych na Spectrum.
  • Tryby Standard/Full wymagają sidecara. new InspectConfig() (głębia Standard) oraz InspectConfig::full() wymagają sidecara Spectrum. Jeśli jest on niedostępny, zgłaszają INSPECT-SIDECAR-001 i nie przechodzą po cichu do trybu Quick.
  • Puste dane wejściowe. Przekazanie pustego ciągu znaków powoduje zgłoszenie wyjątku inspekcji z komunikatem „PDF data must not be empty” (dane PDF nie mogą być puste).
  • Zakres flagi szyfrowania. Flaga odzwierciedla wpis /Encrypt w trailerze. Plik oznaczony tą flagą nie jest odszyfrowywany przez inspektor.

Rezerwowy tryb Quick używa ograniczonego skanowania, a nie pełnego parsowania. Stosuj go do wstępnego kierowania dużej liczby przychodzących plików przed cięższym przetwarzaniem.

Inspektor działa w tym samym procesie i odczytuje wyłącznie znaczniki strukturalne. Żadne bajty dokumentu nie opuszczają hosta, a z dokumentu nie jest wyodrębniany żaden tekst. Flaga ryzyka, na przykład osadzony JavaScript, jest sygnałem doradczym używanym do kierowania przetwarzaniem. Nie jest to stwierdzenie, że plik jest bezpieczny lub niebezpieczny.

StwierdzenieSpecyfikacjaKlauzula
Nagłówek pliku zapisuje wersję PDF.ISO 32000-2§7.5.2
Wpis /ID w trailerze jest identyfikatorem pliku złożonym z dwóch ciągów bajtów.ISO 32000-2§7.5.5
Wpis Contents słownika podpisu przechowuje strukturę CMS SignedData w kodowaniu DER.ISO 32000-2§12.8.1

Ten przepis zgłasza wyłącznie fakty strukturalne. Nie stwierdza, że plik jest prawidłowy, bezpieczny ani zgodny.

Poziomy głębi inspekcji Standard i Full działają za pośrednictwem sidecara Spectrum. Zapewniają bogatszą analizę obiektów, czcionek i obrazów. Opisany tutaj rezerwowy tryb Quick jest częścią Core i działa offline.