境界付きクロスリファレンス復元
HotPDF は、PDF に欠落、無効、または古い startxref 宣言や使用不能な xref 行がある場合に、実際のオブジェクトグラフとページツリーを復元できます
復元シーケンス
- デフォルトの
xrrmOnFailureモードで、最初に通常の仕様準拠ローダーが実行されます - 復元はソースを 1 MiB チャンクでスキャンし、チャンク間の短い繰り越しを持ち、検証された間接オブジェクトと xref アンカーを記録します
- 検証された間接オブジェクト内にネストされたマーカーは拒否されます。これには、
99 0 objやxrefなどのテキストを含む文字列、コメント、辞書、およびバイナリストリームデータが含まれます - 有効な xref テーブルまたはストリームは、既存のインクリメンタル、ハイブリッド、およびオブジェクトストリームローダーを通じて新しいものから古いものへと試行されます
- 最大 4,096 の xref セクションアンカーが保持され、敵対的なマーカー反復が解析試行を倍増させるのを防ぎます
- xref セクションが実際のページツリーを生成しない場合、直接オブジェクトのオフセットが再構築され、重複するオブジェクト番号は最新の物理定義を使用します
- 実際の Catalog、Pages ツリー、および少なくとも1つのページリーフが解決された場合にのみ復元は成功します
宣言
type
THPDFXRefRecoveryMode = (
xrrmDisabled,
xrrmOnFailure,
xrrmForce
);
THPDFXRefRecoveryStatus = (
xrrsNotNeeded,
xrrsSucceeded,
xrrsDisabled,
xrrsScanLimitExceeded,
xrrsObjectLimitExceeded,
xrrsXRefLimitExceeded,
xrrsFailed
);
THPDFXRefRecoveryMethod = (
xrrmethodNone,
xrrmethodRelocatedSection,
xrrmethodRebuiltObjectOffsets
);
THPDFXRefMergeInfo = record
HybridRevisionCount: Integer;
HybridOverlapCount: Integer;
OlderRevisionShadowedEntryCount: Integer;
DuplicateEntryCount: Integer;
NewestRevisionPrecedenceApplied: boolean;
HybridStreamPrecedenceApplied: boolean;
end;
property XRefRecoveryMode: THPDFXRefRecoveryMode;
property XRefRecoveryMaxScanBytes: Int64;
property XRefRecoveryMaxObjects: Integer;
function GetLoadedXRefRecoveryInfo(
out Info: THPDFXRefRecoveryInfo
): boolean;
function GetLoadedXRefMergeInfo(
out Info: THPDFXRefMergeInfo
): boolean;
設定
| メンバー | デフォルト | 目的 |
|---|---|---|
XRefRecoveryMode | xrrmOnFailure | 復元を無効化する、通常のパースが失敗した後にだけ実行する、または通常のパースの前に強制実行する、のいずれかを指定します |
XRefRecoveryMaxScanBytes | 8 GiB | チャンク形式の復元スキャンが受け入れる、ハードな最大ソースサイズ |
XRefRecoveryMaxObjects | 2,000,000 | 復元が受け入れる、検証済み間接オブジェクト候補のハードな最大数 |
ParserRecoveryEventLimit | 1,024 | 1 回の読み込みで保持される構造化イベントの最大数。0 でイベント保持を無効化します |
復元情報
GetLoadedXRefRecoveryInfo は復元が試行された場合に True を返し、最新の THPDFXRefRecoveryInfo レコードをコピーします
Statusは成功、無効化された復元、バイト制限失敗、オブジェクト制限失敗、xref アンカー制限失敗、および構造的失敗を区別しますMethodは再配置された xref セクションまたは再構築された直接オブジェクトオフセットを識別しますBytesScanned、CandidateObjectCount、RecoveredObjectCount、DuplicateObjectCount、RejectedCandidateCount、XRefCandidateCountは境界付き作業と復元品質を公開しますSelectedXRefOffsetはそのメソッドが成功した場合に再配置されたセクションを識別しますDiagnosticは簡潔な英語の結果記述を含みます
マージ優先情報
GetLoadedParserRecoveryEvents は保持されたイベントストリームの呼び出し側所有のスナップショットを返し、GetLoadedParserRecoveryEvent は配列コピーを確保せずに 1 エントリを読み取ります
Kindは、試行・ポリシー・上限・オブジェクト候補・xref 候補・選択されたセクション・再構築されたオフセット・成功・失敗の各イベントを区別しますFirstByteは込み、EndByteは除外です。ソース範囲が存在しない場合は両方とも-1に設定されますObjectNumberとGenerationNumberが間接オブジェクト候補を特定し、ドキュメントレベルまたは xref アンカーのイベントには-1を使いますConfidenceは、prcNoneから始まって low・medium・high・verified の結果へと進みますLoadedParserRecoveryEventDroppedCountは、設定された保持上限を超えて省略されたイベントを報告します。敵対的な入力に対してもメモリを制限内に保ちます
復元されたドキュメントの保存
xref ストリームまたはハイブリッドリファレンス読み込みで報告する価値のあるマージ状態が検出された場合、GetLoadedXRefMergeInfo は True を返します
HybridRevisionCountは、/XRefStmを通じてサイド xref ストリームを寄与した従来形式のリビジョンを数えますHybridOverlapCountは、同じリビジョンの xref ストリームがすでに供給しているテーブルエントリを数えます。xref ストリームが優先されますOlderRevisionShadowedEntryCountは、より新しいリビジョンがすでにそのオブジェクト番号を定義していたために無視されたエントリを数えますDuplicateEntryCountは、最新の非ハイブリッドセクション内の繰り返しエントリを数えます- 2 つの優先フラグは、対応するルールが単に利用可能だっただけでなく、実際に適用されたかどうかを示します
完全性情報
GetLoadedXRefIntegrityInfo は、アクティブなフリーリストチェーン・無効なリンク・サイクル・リンクされていない空きエントリ・ジェネレーション遷移エラー・重複する有効な定義・最新リビジョンに覆い隠された古いエントリを報告します
覆い隠された詳細には、アクティブ / 拒否されたエントリタイプ・オフセットまたはストレージフィールド・ジェネレーション・リビジョンの深さが含まれ、詳細は固定の 256 エントリを上限とします
復元したドキュメントの保存
復元されたドキュメントは、オブジェクトが 1 つも編集されていなくても、常に SaveLoadedDocument の完全書き直しパスを使用します。そのため HotPDF が、損傷したソースバイトを修復済みらしき出力としてコピーすることはありません
例
var
Info: THPDFXRefRecoveryInfo;
PDF: THotPDF;
begin
PDF := THotPDF.Create(nil);
try
PDF.XRefRecoveryMode := xrrmOnFailure;
PDF.XRefRecoveryMaxScanBytes := Int64(16) * 1024 * 1024 * 1024;
PDF.XRefRecoveryMaxObjects := 3000000;
if PDF.LoadFromFile('damaged.pdf') > 0 then
begin
if PDF.GetLoadedXRefRecoveryInfo(Info) then
WriteLn(Info.Diagnostic);
PDF.SaveLoadedDocument('recovered.pdf');
end;
finally
PDF.Free;
end;
end;