Ograniczone odzyskiwanie odsyłaczy krzyżowych

HotPDF potrafi odzyskać rzeczywisty graf obiektów i drzewo stron, gdy plik PDF ma brakującą, nieprawidłową lub nieaktualną deklarację startxref albo nieużywalne wiersze xref

Recovery sequence

  1. Normalny zgodny ze specyfikacją program wczytujący jest uruchamiany jako pierwszy w domyślnym trybie xrrmOnFailure
  2. Odzyskiwanie skanuje źródło w fragmentach po 1 MiB z krótkim przeniesieniem między fragmentami i rejestruje zwalidowane obiekty pośrednie oraz kotwice xref
  3. Znaczniki zagnieżdżone wewnątrz zwalidowanego obiektu pośredniego są odrzucane, w tym ciągi, komentarze, słowniki i dane binarne strumienia zawierające tekst taki jak 99 0 obj lub xref
  4. Prawidłowe tabele lub strumienie xref są próbowane od najnowszego do najstarszego przez istniejący program wczytujący przyrostowy, hybrydowy i strumieni obiektów
  5. Co najwyżej 4096 kotwic sekcji xref jest zatrzymywanych, co zapobiega mnożeniu prób analizy przez wrogie powtórzenia znaczników
  6. Jeśli żadna sekcja xref nie utworzy rzeczywistego drzewa stron, przesunięcia obiektów bezpośrednich są przebudowywane, a zduplikowane numery obiektów używają najnowszej fizycznej definicji
  7. Odzyskiwanie kończy się powodzeniem tylko wtedy, gdy rozstrzygają się rzeczywisty Katalog, drzewo Pages i co najmniej jeden liść strony

Deklaracje

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;

Konfiguracja

CzłonekDomyślniePrzeznaczenie
XRefRecoveryModexrrmOnFailureWyłącza odzyskiwanie, uruchamia je tylko po awarii normalnego parsowania albo wymusza przed normalnym parsowaniem
XRefRecoveryMaxScanBytes8 GiBTwardy maksymalny rozmiar źródła akceptowany przez skan odzyskiwania w chunkach
XRefRecoveryMaxObjects2 000 000Twardy maksimum zwalidowanych kandydatów na obiekty pośrednie akceptowanych przez odzyskiwanie
ParserRecoveryEventLimit1 024Maksimum ustrukturyzowanych zdarzeń przechowywanych dla jednego wczytania; zero wyłącza retencję zdarzeń

Recovery information

GetLoadedXRefRecoveryInfo zwraca True, gdy próbowano odzyskiwania, i kopiuje najnowszy rekord THPDFXRefRecoveryInfo

Merge precedence information

GetLoadedXRefMergeInfo zwraca True, gdy wczytywanie strumienia xref lub odwołania hybrydowego napotkało stan scalania warty zgłoszenia

Informacje o precepcji scalania

GetLoadedXRefMergeInfo zwraca True, gdy wczytywanie xref-stream albo hybrydowe napotkało stan scalania wartego raportowania

Informacje o integralności

GetLoadedXRefIntegrityInfo raportuje aktywny łańcuch listy wolnej, nieprawidłowe łącza, cykle, niepodpięte wpisy wolne, błędy przejść generacji, zduplikowane definicje żywych obiektów oraz starsze wpisy przysłonięte przez najnowszą rewizję

Szczegóły przysłonięcia obejmują aktywne i odrzucone typy wpisów, offsety albo pola magazynu, generacje i głębokość rewizji, ze sztywnym sufitem 256 wpisów szczegółów

Saving recovered documents

Odzyskany dokument zawsze używa ścieżki pełnego przepisania w SaveLoadedDocument, nawet gdy żaden obiekt nie był edytowany, więc HotPDF nigdy nie kopiuje uszkodzonych bajtów źródłowych jako rzekomo naprawionego wyjścia

Przykład

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;

Powiązane API