Technical Article

U?itavanje PDF-ova s hibridnim referencama iz Worda i Excela u Delphi-ju

Otvorite PDF koji je proizveo Microsoft Word ili Excel, listajte kroz njega i ni?ta ne izgleda neobi?no. U?itajte ga u Delphi program, pro?itajte broj stranica i broj je to?an. Zatim ga ponovno spremite s uklju?enim ?ifriranjem i zadatak ne uspijeva s pogre?kom EListError, ili se izlaz otvara uz upozorenje o o?te?enoj unakrsnoj referenci. Datoteka nikada nije bila o?te?ena. Radi se o datoteci s hibridnim referencama, a upravo je struktura koja omogu?uje petnaest godina starom pregledniku da je otvori ista ona koja pora?ava u?itava? koji prestaje ?itati prerano

Ovo je jedan od naj?e??ih na?ina na koje cjevovod PDF-a koji je pro?ao svaki interni test nailazi na datoteku koju ne mo?e obraditi u oba smjera. Svi ulazi generirani su unutar tvrtke, pa nikada nisu bili hibridni. Prva hibridna datoteka sti?e onog dana kada kupac proslijedi ra?un izvezen iz prora?unske tablice

?to Word i Excel zapravo zapisuju

ISO 32000-1 opisuje izgled hibridnih referenci u ?7.5.8.4. Aplikacija koja ?eli zna?ajke PDF-a 1.5 poput tokova objekata, a istovremeno omogu?uje ?ita?u PDF-a 1.4 da otvori datoteku, dvaput zapisuje informacije o unakrsnim referencama. Postoji klasi?na tablica unakrsnih referenci, ASCII redovi fiksne ?irine koji su zavr?avali svaki PDF do verzije 1.4, i postoji tok unakrsnih referenci koji indeksira ostatak. Najava klasi?nog odjeljka nosi unos /XRefStm ?ija je vrijednost pomak bajta tog toka

Podjela rada je namjerna. Objekti koje stari ?ita? mora dosegnuti, me?u kojima su katalog i stablo stranica, adresibilni su iz klasi?ne tablice. Objekti koji su skupljeni u komprimirane tokove objekata ozna?eni su kao slobodni u klasi?noj tablici, s unosom tipa f, tako da ih ?ita? 1.4 preska?e i nikada se ne spotakne o strukturu koju ne mo?e analizirati. Njihove stvarne lokacije ?ive samo u toku unakrsnih referenci. Potpis takve datoteke je njezin kraj: kratki klasi?ni odjeljak, ?esto ni?ta vi?e od xref pra?enog zaglavljem pododjeljka 0 0, ?ija najava upu?uje na /XRefStm gdje se nalaze stvarni podaci za oporavak

Za?to to?an broj stranica ne dokazuje ni?ta

Budu?i da su katalog i stablo stranica namjerno dostupni iz klasi?ne tablice, u?itava? koji ?ita samo tu tablicu pronalazi /Root, prolazi stablom stranica i javlja to?an broj stranica. Prisutno je sve ?to starom ?ita?u treba, pa se datoteka ?ini zdravom. Objekti koji nedostaju su oni zapakirani u tokove objekata: rje?nici polja AcroForm, strukturni elementi ozna?enog PDF-a, dugi niz malih rje?nika koji nikada nisu morali biti vidljivi naslije?enom pregledniku

Prazninu ne primje?ujete sve dok ne?to ne dotakne te objekte, a potpuno ponovno spremanje doti?e sve njih. Prolazak kroz dokument radi ponovnog ?ifriranja ili ponovnog pisanja upravo je operacija koja tra?i svaki broj objekta redom, zbog ?ega se simptom pojavljuje pri spremanju, a ne pri u?itavanju, daleko od svog uzroka

Zamka je detektor koji vidi xref i zaustavlja se

Jeftin na?in za odre?ivanje na?ina indeksiranja datoteke jest pra?enje startxref i pregled prvih bajtova na koje upu?uje. Klju?na rije? xref ozna?ava klasi?nu tablicu; objekt toka ozna?ava tok unakrsnih referenci. Taj je test to?an za svaku datoteku koja se obvezuje na jednu shemu. Pogre?an je za hibridnu datoteku, ?iji startxref cilja na klasi?ni odjeljak isklju?ivo radi zadovoljavanja starih ?ita?a, dok je /XRefStm u najavi tog odjeljka mjesto gdje je zapravo indeksiran najve?i dio dokumenta. Detektor koji vra?a "classic" na prvi xref koji susrene nikada ne ?ita /XRefStm, a svaki objekt koji ?ivi samo u toku postaje nevidljiv

var
  Pdf: THotPDF;
  PageCount: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    PageCount := Pdf.LoadFromFile('Invoice_XLS.pdf');  // count is correct
    // inspect or edit the loaded document here
    Pdf.SaveLoadedDocument('Invoice_secured.pdf');     // walks every object
  finally
    Pdf.Free;
  end;
end;

S uklju?enim detektorom ranog izlaza, u?itavanje izgleda u redu, a ponovno spremanje je mjesto gdje se odsutni objekti objavljuju. Rje?enje nije ?itanje vi?e bajtova na po?etku; radi se o prepoznavanju hibridne najave i pra?enju /XRefStm prije nego ?to se odlu?i da je datoteka gotova

Redoslijed spajanja nije podlo?an pregovorima

Nakon ?to su pro?itana oba indeksa, oni se mogu kombinirati samo u jednom smjeru. Tok unakrsnih referenci mora se spojiti prvi, a klasi?ni unosi popuniti oko njega. Razlog je mala obmana u samoj sr?i formata. Hibridna datoteka ozna?ava svoje komprimirane objekte kao slobodne u klasi?noj tablici kako bi ih stari ?ita?i zanemarili. U?itava? koji po?tuje pravilo prvenstva i najprije ?ita klasi?nu tablicu zabilje?it ?e te brojeve objekata kao slobodne, a zatim odbaciti unose toka koji ih zapravo lociraju, jer su mjesta ve? zauzeta. Okrenite redoslijed i unosi tipa 2 iz toka, od kojih je svaki broj toka objekta plus indeks, osvajaju mjesta koja trebaju posjedovati, a klasi?ni unosi se smje?taju oko njih

Ista disciplina ?titi od toga da starija revizija uskrsne izbrisani objekt. Inkrementalna a?uriranja povezuju se unatrag kroz /Prev, a slobodni unos tipa 0 je sentinel da je noviji odjeljak povukao broj objekta. Kasnijem, starijem odjeljku u lancu ne smije se dopustiti da prepi?e taj sentinel zastarjelom lokacijom. Tretirajte prvi vi?eni unos kao mjerodavan za slobodne markere i izbrisani objekt ostaje izbrisan; tretirajte ga nemarno i vlastita povijest datoteke ponovno o?ivljava sadr?aj koji je najnovija revizija uklonila

?to to zna?i u HotPDF

Pogon umjesto vas rje?ava datoteke s hibridnim referencama, i to ?ini na svakoj putanji koja mora analizirati podatke unakrsnih referenci. U?itajte dokument pomo?u LoadFromFile or LoadFromStream, make your changes, and call SaveLoadedDocument; ili pokrenite jednokratnu operaciju kao ?to je EncryptFile koja ?ita ulaz i pi?e izlaz. U oba slu?aja oporavak ?ita /XRefStm, spaja odjeljak toka ispred klasi?nih unosa i rje?ava objekte koji ?ive u tokovima prije nego ?to ih zapisivanje nabroji. Putanja ?ifriranja AES-256 mjesto je gdje se problem prvi put pokazao, jer ?ifriranje dokumenta ponovno zapisuje svaki objekt i stoga zahtijeva da svaki objekt ve? bude lociran

// One-shot: read the hybrid input, write an AES-256 encrypted copy
Pdf.EncryptFile('Letter_DOC.pdf', 'Letter_secured.pdf',
  'owner-secret', '', aes256, [prPrint, prFillAnnotations]);

Detalj koji vrijedi zapamtiti nalazi se uzvodno od API-ja. Datoteke koje pristi?u iz Worda, Excela, PowerPointa i dugog niza cjevovoda "Spremi kao PDF" uobi?ajeno su hibridne, pa u?itava? koji testirate samo na vlastitom izlazu generatora mo?da nikada ne?e nai?i na njih u testiranju. Popunite svoje testne primjere dokumentima izvezenim iz stvarnih Office aplikacija, a ne samo datotekama koje je proizveo va? vlastiti kod

Provjera sumnjive datoteke

Dvije provjere brzo rje?avaju pitanje. Otvorite datoteku u heksadecimalnom prikazu i pro?itajte bajtove nakon zavr?nog startxref; hibridna datoteka prikazuje kratki klasi?ni odjeljak ?iji rje?nik najave sadr?i /XRefStm. Ili usporedite broj objekata koji prijavljuje potpuna analiza s najve?im brojem objekta koji /Size deklarira u najavi. Veliki razmak zna?i da se objekti skrivaju u tokovima koje u?itava? nije otvorio, ?to je isti nedostatak koji se kasnije pretvara u zatajenje pri spremanju

Pi??eva strana ove pri?e, odnosno na?in na koji se tokovi objekata i komprimirane unakrsne reference uop?e proizvode, pokrivena je u na?em ?lanku o tokovima objekata i inkrementalnim a?uriranjima. Kada je doti?na hibridna datoteka tako?er vrlo velika, tehnike u?itavanja u vodi?u za Direct File API za velike PDF tijekove rada omogu?uju vam da je pregledate bez u?itavanja cijele datoteke u memoriju. Obje se prirodno povezuju s ovdje opisanim oporavkom, koji se isporu?uje kao dio softvera HotPDF Component za Delphi i C++Builder, zajedno s API-jima za u?itavanje, ure?ivanje, ?ifriranje i potpisivanje koji su obra?eni drugdje na ovom blogu