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
- Nejprve běží normální loader v souladu se specifikací ve výchozím režimu
xrrmOnFailure - 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
- 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 objneboxref - 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
- 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í
- 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
- 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
| Člen | Výchozí | Účel |
|---|---|---|
XRefRecoveryMode | xrrmOnFailure | Zakáže obnovu, spustí ji jen po selhání normálního parsování, nebo ji vynutí před normálním parsováním |
XRefRecoveryMaxScanBytes | 8 GiB | Tvrdé maximum velikosti zdroje přijímané chunkovou skenovací obnovou |
XRefRecoveryMaxObjects | 2 000 000 | Tvrdé maximum kandidátů validovaných nepřímých objektů přijímaných obnovou |
ParserRecoveryEventLimit | 1 024 | Maximá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
Statusrozlišuje úspěch, zakázanou obnovu, selhání bajtového limitu, selhání limitu objektů, selhání limitu kotev xref a strukturální selháníMethodidentifikuje přemístěnou sekci xref nebo přestavěné offsety přímých objektůBytesScanned,CandidateObjectCount,RecoveredObjectCount,DuplicateObjectCount,RejectedCandidateCountaXRefCandidateCountzpřístupňují ohraničenou práci a kvalitu obnovySelectedXRefOffsetidentifikuje přemístěnou sekci, když tato metoda uspějeDiagnosticobsahuje stručný anglický popis výsledku
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í
HybridRevisionCountpočítá tradiční revize, které přispěly bočním proudem xref přesFirstByteje inkluzivní aEndByteexkluzivní, přičemž obě hodnoty jsou-1, když žádný zdrojový rozsah neexistujeObjectNumberaGenerationNumberidentifikují kandidáty nepřímých objektů a používají-1pro události na úrovni dokumentu nebo xref kotvyConfidencepostupuje odprcNonepřes nízkou, střední, vysokou až po ověřený výsledekLoadedParserRecoveryEventDroppedCounthlásí události vynechané po nastaveném limitu zachovávání, čímž drží paměť ohraničenou na nepřátelských vstupech
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í
HybridRevisionCount/XRefStmHybridOverlapCountpočítá položky tabulky již dodané proudem xref stejné revize, který má přednostOlderRevisionShadowedEntryCountpočítá položky ignorované, protože novější revize již definovala dané číslo objektuDuplicateEntryCountpočítá opakované položky uvnitř nejnovější nehybridní sekce- Dva příznaky přednosti uvádějí, zda bylo odpovídající pravidlo uplatněno, nikoliv pouze dostupné
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;