Salta ai contenuti

Analizzare e ispezionare un PDF per ottenere dati strutturali

Questa ricetta mostra come leggere i dati strutturali di un PDF tramite il fallback Quick dell’inspector di Core. Sono inclusi la versione, il numero di pagine, il flag di cifratura, il flag di firma, il flag degli allegati, la dimensione del file e i flag di rischio. Quick viene eseguito interamente in-process, senza sidecar Spectrum e senza accesso alla rete. Usarlo per il triage rapido, non come validatore.

Terminal window
composer require nextpdf/core:^3

Un PDF registra la propria versione nell’intestazione del file (ISO 32000-2 §7.5.2). Il trailer contiene un identificatore di file (/ID) costituito da due stringhe di byte (ISO 32000-2 §7.5.5). Quando è presente una firma, questa è rappresentata da un dizionario di firma il cui Contents contiene DER CMS SignedData (ISO 32000-2 §12.8.1). Il fallback Quick ricava la versione, una stima del numero di pagine e i flag di presenza di cifratura, firma e allegati tramite una scansione limitata dei byte del documento.

Chiamare new Inspector(), quindi ->inspect(string $pdfData, InspectConfig::quick()). Il risultato è un InspectResult che espone $pdfVersion, $pageCount, $isEncrypted, $hasSigned, $hasAttachments, $fileSizeBytes, $riskFlags e l’helper 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',
);

Questo è il programma autonomo eseguibile nell’harness. Rispecchia examples/39-parse-and-inspect-pdf.php: crea in memoria un piccolo PDF multipagina, ne legge i dati strutturali con il fallback Quick e instrada in base a tali dati (mai in base a un verdetto di attendibilità). La logica di instradamento è puramente illustrativa. Integrare qui la propria pipeline, la coda del verificatore e la quarantena.

<?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);

STDOUT previsto (la versione e la dimensione dipendono dalla build; il PDF dimostrativo è non cifrato, non firmato e privo di rischi):

PDF version : <version>
Pages : 2
Encrypted : no
Signed : no
Attachments : no
File size : <n> bytes
Risk flags : 0
Route: continue (no risks, unsigned, unencrypted)
  • Quick serve per il triage, non per la validazione. Segnala ciò che è presente e ciò che è assente. Non verifica le firme, non decifra i contenuti e non attesta la conformità. Considerare il risultato come input per l’instradamento.
  • Il numero di pagine è una stima. Il fallback Quick conta i marcatori degli oggetti pagina. Un grafo di oggetti deliberatamente malformato può falsare il conteggio. Usare i livelli di profondità basati su Spectrum quando è necessario un conteggio esatto.
  • Standard/Full richiedono il sidecar. new InspectConfig() (profondità Standard) e InspectConfig::full() richiedono il sidecar Spectrum. Generano INSPECT-SIDECAR-001 quando non è disponibile e non ripiegano automaticamente su Quick.
  • Input vuoto. Una stringa vuota genera un’eccezione di ispezione con il messaggio “PDF data must not be empty”.
  • Ambito del flag di cifratura. Il flag rispecchia una voce /Encrypt nel trailer. Un file contrassegnato non viene decifrato dall’inspector.

Il fallback Quick esegue una scansione limitata, non un parsing completo. È adatto al pre-instradamento ad alto volume dei file in arrivo prima di un’elaborazione più onerosa.

L’inspector opera in-process e legge solo i marcatori strutturali. Nessun byte del documento lascia l’host e non viene estratto alcun testo dal documento. Un flag di rischio, ad esempio JavaScript incorporato, è un segnale indicativo per l’instradamento. Non equivale ad affermare che il file sia sicuro o non sicuro.

DichiarazioneSpecificaClausolareference_id
L’intestazione del file registra la versione del PDF.ISO 32000-2§7.5.2
Il /ID del trailer è un identificatore di file costituito da due stringhe di byte.ISO 32000-2§7.5.5
Il Contents di un dizionario di firma contiene DER CMS SignedData.ISO 32000-2§12.8.1

Questa ricetta riporta dati strutturali. Non attesta che il file sia valido, sicuro o conforme.

I livelli di profondità di ispezione Standard e Full vengono eseguiti tramite il sidecar Spectrum. Aggiungono un’analisi più approfondita di oggetti, font e immagini. Il fallback Quick documentato qui appartiene a Core e funziona offline.