コンテンツにスキップ

PDF を解析して構造的事実を確認する

このレシピでは、Core インスペクターの Quick フォールバックを使い、PDF から構造的事実を読み取ります。対象となる事実は、バージョン、ページ数、暗号化フラグ、署名フラグ、添付ファイルフラグ、ファイルサイズ、リスクフラグです。Quick は完全にプロセス内で実行され、Spectrum サイドカーもネットワークも使用しません。バリデーターとしてではなく、迅速なトリアージに使用してください。

Terminal window
composer require nextpdf/core:^3

PDF は、バージョンをファイルヘッダーに記録します(ISO 32000-2 §7.5.2)。トレーラーには、2 つのバイト文字列からなるファイル識別子(/ID)が保持されます(ISO 32000-2 §7.5.5)。署名が存在する場合、それは署名ディクショナリであり、その Contents に DER CMS SignedData が保持されます(ISO 32000-2 §12.8.1)。Quick フォールバックは、ドキュメントのバイト列を範囲を限定してスキャンし、バージョン、ページ数の推定値、および暗号化・署名・添付ファイルの有無を示すフラグを導き出します。

まず new Inspector() を呼び出し、その後 ->inspect(string $pdfData, InspectConfig::quick()) を呼び出します。返される結果は InspectResult で、$pdfVersion$pageCount$isEncrypted$hasSigned$hasAttachments$fileSizeBytes$riskFlags、および 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',
);

これは自己完結型で、ハーネスから実行できるプログラムです。サンプル examples/39-parse-and-inspect-pdf.php を反映しており、メモリ内で小さな複数ページの PDF を構築し、Quick フォールバックでその構造的事実を読み取り、それらの事実に基づいてルーティングします(信頼性の判定には基づきません)。ルーティングの分岐は例示です。独自のパイプライン、検証キュー、隔離処理を組み込んでください。

<?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(バージョンとサイズはビルドによって異なります。デモ PDF は暗号化なし、署名なし、リスクなしです):

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 はバリデーションではなくトリアージです。 何が存在し、何が存在しないかを報告します。署名の検証、コンテンツの復号、適合性の表明は行いません。結果はルーティングの入力として扱ってください。
  • ページ数は推定値です。 Quick フォールバックはページオブジェクトのマーカーを数えます。意図的に不正な形式にされたオブジェクトグラフは、カウントを歪めることがあります。正確なカウントが重要な場合は、Spectrum がサポートする深度を使用してください。
  • Standard/Full はサイドカーが必要です。 new InspectConfig()(深度 Standard)および InspectConfig::full() には Spectrum サイドカーが必要です。サイドカーが利用できない場合は INSPECT-SIDECAR-001 をスローし、Quick へ暗黙的に縮退することはありません。
  • 空の入力。 空文字列は「PDF data must not be empty」というメッセージを伴って inspect 例外をスローします。
  • 暗号化フラグの範囲。 このフラグは、トレーラーの /Encrypt エントリを反映したものです。フラグが付いたファイルをインスペクターが復号することはありません。

Quick フォールバックは完全な解析ではなく、範囲を限定したスキャンです。より重い処理を行う前に、大量の受信ファイルを事前ルーティングする用途に適しています。

インスペクターはプロセス内で動作し、構造的なマーカーのみを読み取ります。ドキュメントのバイト列がホストの外に出ることはなく、ドキュメントのテキストが抽出されることもありません。リスクフラグ(たとえば埋め込み JavaScript)は、ルーティングの参考シグナルです。ファイルが安全であるか危険であるかを表明するものではありません。

記述仕様箇条リファレンス ID
PDF のバージョンを記録するファイルヘッダーISO 32000-2§7.5.2
トレーラーの /ID は、2 つのバイト文字列からなるファイル識別子ISO 32000-2§7.5.5
DER CMS SignedData を保持する署名ディクショナリの ContentsISO 32000-2§12.8.1

このレシピが報告するのは構造的事実です。ファイルが有効、安全、または適合していることを表明するものではありません。

Standard および Full の検査深度は、Spectrum サイドカーを経由して実行されます。これらの深度では、より詳細なオブジェクト、フォント、画像の解析が追加されます。ここで説明している Quick フォールバックは Core の機能であり、オフラインで動作します。