Recuperación acotada de referencias cruzadas
HotPDF puede recuperar un grafo de objetos y árbol de páginas reales cuando un PDF tiene una declaración startxref ausente, inválida o desactualizada, o filas xref inutilizables
Secuencia de recuperación
- El cargador normal conforme a la especificación se ejecuta primero en el modo
xrrmOnFailurepredeterminado - La recuperación recorre el origen en bloques de 1 MiB con un arrastre corto entre bloques y registra los objetos indirectos validados y los anclajes xref
- Los marcadores anidados dentro de un objeto indirecto validado se rechazan, incluidos strings, comentarios, diccionarios y datos de flujo binario que contienen texto como
99 0 objoxref - Las tablas o flujos xref válidos se prueban del más reciente al más antiguo mediante el cargador incremental, híbrido y de flujo de objetos existente
- Se retienen como máximo 4096 anclajes de sección xref, lo que evita que la repetición adversaria de marcadores multiplique los intentos de análisis
- Si ninguna sección xref produce un árbol de páginas real, se reconstruyen los desplazamientos de objetos directos y los números de objeto duplicados usan la definición física más reciente
- La recuperación solo tiene éxito cuando un Catalog, un árbol de Pages y al menos una hoja de página reales se resuelven
Declaraciones
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;
Configuración
| Miembro | Predeterminado | Propósito |
|---|---|---|
XRefRecoveryMode | xrrmOnFailure | Desactiva la recuperación, la ejecuta solo después de que el análisis normal falle, o la fuerza antes del análisis normal |
XRefRecoveryMaxScanBytes | 8 GiB | Tamaño máximo estricto de origen aceptado por el recorrido de recuperación por bloques |
XRefRecoveryMaxObjects | 2,000,000 | Cantidad máxima estricta de candidatos de objetos indirectos validados aceptados por la recuperación |
ParserRecoveryEventLimit | 1,024 | Máximo de eventos estructurados que se conservan por cada carga; cero desactiva la retención de eventos |
Información de recuperación
GetLoadedXRefRecoveryInfo devuelve True cuando se intentó la recuperación y copia el registro THPDFXRefRecoveryInfo más reciente
Statusdistingue entre éxito, recuperación deshabilitada, fallo por límite de bytes, fallo por límite de objetos, fallo por límite de anclajes xref y fallo estructuralMethodidentifica una sección xref reubicada o desplazamientos de objetos directos reconstruidosBytesScanned,CandidateObjectCount,RecoveredObjectCount,DuplicateObjectCount,RejectedCandidateCountyXRefCandidateCountexponen el trabajo acotado y la calidad de la recuperaciónSelectedXRefOffsetidentifica la sección reubicada cuando ese método tiene éxitoDiagnosticcontiene una descripción de resultado concisa en inglés
Información de precedencia de fusión
GetLoadedParserRecoveryEvents devuelve una instantánea, propiedad de quien llama, del flujo de eventos conservado, mientras que GetLoadedParserRecoveryEvent lee una sola entrada sin asignar una copia del arreglo
Kinddistingue los eventos de intento, política, límite, candidato a objeto, candidato a xref, sección seleccionada, offsets reconstruidos, éxito y falloFirstBytees inclusivo yEndByteexclusivo, ambos fijados en-1cuando no existe rango de origenObjectNumberyGenerationNumberidentifican candidatos a objetos indirectos y usan-1para los eventos a nivel de documento o de ancla xrefConfidenceprogresa desdeprcNonehasta resultados bajo, medio, alto y verificadoLoadedParserRecoveryEventDroppedCountinforma de los eventos omitidos tras el límite de retención configurado, preservando memoria acotada ante entradas hostiles
Información de precedencia de fusión
GetLoadedXRefMergeInfo devuelve True cuando la carga de xref-stream o de referencias híbridas encontró estado de fusión que valga la pena informar
HybridRevisionCountcuenta las revisiones tradicionales que aportaron un xref stream lateral vía/XRefStmHybridOverlapCountcuenta las entradas de tabla ya suministradas por el xref stream de la misma revisión, que tiene precedenciaOlderRevisionShadowedEntryCountcuenta las entradas ignoradas porque una revisión más reciente ya definía ese número de objetoDuplicateEntryCountcuenta las entradas repetidas dentro de la sección no híbrida más reciente- Los dos flags de precedencia indican si la regla correspondiente se ejerció o si solo estaba disponible
Información de integridad
GetLoadedXRefIntegrityInfo informa de la cadena de lista libre activa, enlaces no válidos, ciclos, entradas libres sin enlazar, errores de transición de generación, definiciones vivas duplicadas y entradas antiguas sombreadas por la revisión más reciente
El detalle sombreado incluye tipos de entrada activos y rechazados, offsets o campos de almacenamiento, generaciones y profundidad de revisión, con un techo fijo de 256 entradas de detalle
Guardado de documentos recuperados
Un documento recuperado siempre usa la ruta de reescritura completa en SaveLoadedDocument, incluso cuando no se editó ningún objeto, de modo que HotPDF nunca copia bytes de origen dañados como una salida aparentemente reparada
Ejemplo
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;