Recuperación acotada de referencias cruzadas

HotPDF puede recuperar un grafo de objetos real y un árbol de páginas cuando un PDF tiene una declaración startxref ausente, no válida o obsoleta, o filas xref inutilizables

Secuencia de recuperación

  1. El cargador normal conforme a la especificación se ejecuta primero en el modo predeterminado xrrmOnFailure
  2. La recuperación explora el origen en bloques de 1 MiB con un acarreo corto entre bloques y registra objetos indirectos validados y anclajes xref
  3. Los marcadores anidados dentro de un objeto indirecto validado se rechazan, incluidos strings, comentarios, diccionarios y datos binarios de flujo que contienen texto como 99 0 obj o xref
  4. Las tablas o flujos xref válidos se prueban del más nuevo al más antiguo a través del 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 se resuelven un Catalog real, un árbol de Pages y al menos una hoja de página

Declaraciones

type
  THPDFXRefRecoveryMode = (
    xrrmDisabled,
    xrrmOnFailure,
    xrrmForce
  );

  THPDFXRefRecoveryStatus = (
    xrrsNotNeeded,
    xrrsSucceeded,
    xrrsDisabled,
    xrrsScanLimitExceeded,
    xrrsObjectLimitExceeded,
    xrrsXRefLimitExceeded,
    xrrsFailed
  );

  THPDFXRefRecoveryMethod = (
    xrrmethodNone,
    xrrmethodRelocatedSection,
    xrrmethodRebuiltObjectOffsets
  );

  THPDFParserRecoveryConfidence = (
    prcNone,
    prcLow,
    prcMedium,
    prcHigh,
    prcVerified
  );

  THPDFParserRecoveryEvent = record
    Kind: THPDFParserRecoveryEventKind;
    Confidence: THPDFParserRecoveryConfidence;
    FirstByte: Int64;
    EndByte: Int64;
    ObjectNumber: Integer;
    GenerationNumber: Integer;
    Message: AnsiString;
  end;

  THPDFXRefMergeInfo = record
    HybridRevisionCount: Integer;
    HybridOverlapCount: Integer;
    OlderRevisionShadowedEntryCount: Integer;
    DuplicateEntryCount: Integer;
    NewestRevisionPrecedenceApplied: boolean;
    HybridStreamPrecedenceApplied: boolean;
  end;

property XRefRecoveryMode: THPDFXRefRecoveryMode;
property XRefRecoveryMaxScanBytes: Int64;
property XRefRecoveryMaxObjects: Integer;
property ParserRecoveryEventLimit: Integer;
property LoadedParserRecoveryEventCount: Integer;
property LoadedParserRecoveryEventDroppedCount: Integer;

function GetLoadedXRefRecoveryInfo(
  out Info: THPDFXRefRecoveryInfo
): boolean;

function GetLoadedParserRecoveryEvents:
  THPDFParserRecoveryEventArray;

function GetLoadedParserRecoveryEvent(
  Index: Integer;
  out EventInfo: THPDFParserRecoveryEvent
): boolean;

function GetLoadedXRefMergeInfo(
  out Info: THPDFXRefMergeInfo
): boolean;

function GetLoadedXRefIntegrityInfo(
  out Info: THPDFXRefIntegrityInfo
): boolean;

Configuración

MiembroPredeterminadoPropósito
XRefRecoveryModexrrmOnFailureDeshabilita la recuperación, la ejecuta solo cuando el análisis normal falla, o la fuerza antes del análisis normal
XRefRecoveryMaxScanBytes8 GiBTamaño máximo duro del fuente aceptado por el escaneo de recuperación por trozos
XRefRecoveryMaxObjects2,000,000Máximo duro de candidatos a objeto indirecto validados que acepta la recuperación
ParserRecoveryEventLimit1,024Máximo de eventos estructurados retenidos por una carga; cero deshabilita 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

Eventos de recuperación estructurados

GetLoadedParserRecoveryEvents devuelve una instantánea propiedad del llamador del stream de eventos retenido, mientras que GetLoadedParserRecoveryEvent lee una entrada sin asignar una copia de array

Información de precedencia de fusión

GetLoadedXRefMergeInfo devuelve True cuando la carga por flujo xref o referencia híbrida encontró estado de fusión digno de informe

Información de integridad

GetLoadedXRefIntegrityInfo informa de la cadena activa de listas libres, los enlaces no válidos, los ciclos, las entradas libres sin enlazar, los errores de transición de generación, las definiciones vivas duplicadas y las entradas anteriores ocultadas 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