Ohraničená obnova křížových referencí

HotPDF umí obnovit skutečný graf objektů a strom stránek, když má PDF chybějící, neplatnou nebo zastaralou deklaraci startxref nebo nepoužitelné řádky xref

Sekvence obnovy

  1. Nejprve běží normální loader v souladu se specifikací ve výchozím režimu xrrmOnFailure
  2. Obnova skenuje zdroj v 1 MiB chunkách s krátkým přenosem mezi chunky a zaznamenává validované nepřímé objekty a kotvy xref
  3. Značky vnořené uvnitř validovaného nepřímého objektu jsou odmítnuty, včetně řetězců, komentářů, slovníků a binárních dat proudu obsahujících text jako 99 0 obj nebo xref
  4. Platné tabulky nebo proudy xref jsou zkoušeny od nejnovějšího po nejstarší přes existující inkrementální, hybridní a object-stream loader
  5. Je zachováno maximálně 4 096 kotev sekcí xref, což zabraňuje, aby advesariální opakování značek násobilo pokusy o parsování
  6. Pokud žádná sekce xref nevytvoří skutečný strom stránek, jsou offsety přímých objektů přestavěny a duplicitní čísla objektů použijí nejnovější fyzickou definici
  7. Obnova uspěje jen tehdy, když se vyřeší skutečný Catalog, strom Pages a alespoň jeden list stránky

Deklarace

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;

Konfigurace

ČlenVýchozíÚčel
XRefRecoveryModexrrmOnFailureZakáže obnovu, spustí ji jen po selhání normálního parsování, nebo ji vynutí před normálním parsováním
XRefRecoveryMaxScanBytes8 GiBTvrdé maximum velikosti zdroje přijímané chunkovou skenovací obnovou
XRefRecoveryMaxObjects2 000 000Tvrdé maximum kandidátů validovaných nepřímých objektů přijímaných obnovou
ParserRecoveryEventLimit1 024Maximální počet strukturovaných událostí zachovaných pro jedno načtení; nula zakáže zachovávání událostí

Informace o obnově

GetLoadedXRefRecoveryInfo vrací True, když byla obnova zkusena, a kopíruje nejnovější záznam THPDFXRefRecoveryInfo

Informace o slučovací přednosti

GetLoadedXRefMergeInfo vrací True, když načítání proudu xref nebo hybridních referencí narazilo na stav sloučení, který stojí za nahlášení

Informace o prioritách slučování

GetLoadedXRefMergeInfo vrací True, když načítání xref streamů nebo hybridních referencí narazilo na stav slučování stojící za hlášení

Ukládání obnovených dokumentů

Obnovený dokument vždy používá cestu úplného přepsání v SaveLoadedDocument, i když nebyl editován žádný objekt, takže HotPDF nikdy nekopíruje poškozené bajty zdroje jako zdánlivě opravený výstup

Detail zastínění zahrnuje aktivní a odmítnuté typy položek, offsety nebo úložná pole, generace a hloubku revize, s pevným stropem detailů 256 položek

Ukládání obnovených dokumentů

Obnovený dokument vždy použije v SaveLoadedDocument cestu plného přepisu, i když nebyl upraven žádný objekt, takže HotPDF nikdy nezkopíruje poškozené zdrojové bajty jako zjevně opravený výstup

Příklad

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;

Související API