有界的交互參考復原

當 PDF 有遺失、無效或過時的 startxref 宣告或無法使用的 xref 列時,HotPDF 可以復原真實的物件圖與頁面樹

復原順序

  1. 在預設的 xrrmOnFailure 模式下,一般符合規範的載入器會先執行
  2. 復原會以 1 MiB 的分塊掃描來源,分塊之間帶有簡短延續,並記錄已驗證的間接物件與 xref 錨點
  3. 巢狀於已驗證間接物件內的標記會被拒絕,包含字串、註解、字典,以及含有如 99 0 obj 或 xref 等文字的二進位串流資料
  4. 有效的 xref 表格或串流會透過既有的增量、混合與物件串流載入器,從最新到最舊嘗試
  5. 最多保留 4,096 個 xref 區段錨點,以防範敵意的標記重複增加剖析嘗試
  6. 若沒有任何 xref 區段產生真實的頁面樹,則會重建直接物件偏移,且重複的物件編號會使用最新的實體定義
  7. 只有當真實的 Catalog、Pages 樹與至少一個頁面分葉解析時,復原才會成功

宣告

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;

組態

成員預設值用途
XRefRecoveryModexrrmOnFailure停用復原、僅在正常剖析失敗後執行,或在正常剖析之前強制執行
XRefRecoveryMaxScanBytes8 GiB分塊復原掃描接受的硬性來源大小上限
XRefRecoveryMaxObjects2,000,000復原接受的已驗證間接物件候選硬性上限
ParserRecoveryEventLimit1,024單次載入保留的結構化事件上限,零表示停用事件保留

復原資訊

GetLoadedXRefRecoveryInfo 在已嘗試復原時傳回 True,並複製最近的 THPDFXRefRecoveryInfo 記錄

合併優先順序資訊

GetLoadedXRefMergeInfo 在 xref 串流或混合參照載入遇到值得回報的合併狀態時傳回 True

合併優先序資訊

GetLoadedXRefMergeInfo 在 xref stream 或混合參照載入遇到值得回報的合併狀態時回傳 True

完整性資訊

GetLoadedXRefIntegrityInfo 回報作用中的 free-list 鏈、無效連結、循環、未連結的 free 項目、generation 轉換錯誤、重複的存活定義,以及被最新修訂版遮蔽的較舊項目

遮蔽細節包含作用中與被拒的項目型別、偏移量或儲存欄位、generation 與修訂深度,細節上限固定為 256 項

儲存已復原的文件

已復原的文件在 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;

相關 API