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

  1. El cargador normal conforme a la especificación se ejecuta primero en el modo xrrmOnFailure predeterminado
  2. 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
  3. 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 obj o xref
  4. 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
  5. 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
  6. 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
  7. 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

MiembroPredeterminadoPropósito
XRefRecoveryModexrrmOnFailureDesactiva la recuperación, la ejecuta solo después de que el análisis normal falle, o la fuerza antes del análisis normal
XRefRecoveryMaxScanBytes8 GiBTamaño máximo estricto de origen aceptado por el recorrido de recuperación por bloques
XRefRecoveryMaxObjects2,000,000Cantidad máxima estricta de candidatos de objetos indirectos validados aceptados por la recuperación
ParserRecoveryEventLimit1,024Má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

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

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

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;

APIs relacionadas