Izvezite dokument iz programa Microsoft Word ili Excel opcijom Spremi kao PDF i datoteka na disku je, češće nego ne, hibridno-referentna datoteka. Ona nosi svoje informacije o unakrsnim referencama dvaput: jednom kao klasičnu tablicu fiksne širine koja je završavala svaki PDF do verzije 1.4, i jednom kao komprimirani tok unakrsnih referenci o kojem zapravo ovisi veći dio dokumenta. Jedinstveni ključ u traileru, /XRefStm, povezuje ova dva prikaza, i hoće li alat vidjeti cijeli dokument svodi se na to slijedi li taj ključ
Ovaj članak promatra hibridne datoteke sa strane potrošnje: kako izgledaju bajtovi na kraju datoteke, kako se dva prikaza razilaze tijekom uređivanja, te kako Delphi cjevovod može otkriti i usmjeriti hibridne unose. Kako učitavač spaja prikaze i zašto redoslijed nije podložan pregovorima predmet je našeg HotPDF članka o učitavanju hibridno-referentnih datoteka; ovaj se bavi prvenstveno prepoznavanjem samog rasporeda
Zašto Office izvozi dvaput pišu indeks
PDF 1.5 uveo je dvije značajke koje su promijenile oblik datoteke: tokove unakrsnih referenci, koji pohranjuju indeks objekata kao komprimirane binarne podatke umjesto kao tekstualnu tablicu, te tokove objekata, koji pakiraju brojne male objekte u jedan Flate-komprimirani spremnik. Pisač koji ih koristi proizvodi manje datoteke, ali čitač PDF 1.4 verzije ne može otvoriti rezultat jer su strukture na koje se oslanja, xref ključna riječ i trailer rječnik, nestale
ISO 32000-1 §7.5.8.4 definira kompromis. Hibridno-referentna datoteka zapisuje oboje: klasičnu tablicu unakrsnih referenci koja adresira objekte do kojih stari čitač mora doći, među njima katalog i stablo stranica, te tok unakrsnih referenci koji indeksira sve ostalo. Objekti složeni u tokove objekata označeni su kao slobodni u klasičnoj tablici, pa ih 1.4 čitač preskače bez žalbi; njihove stvarne lokacije postoje samo u toku. Klasični trailer zatim nosi ključ /XRefStm koji sadrži bajtni pomak tog toka. Stari preglednik nikada ne čita ključ i iscrtava datoteku iz tabličnog prikaza. Moderni preglednik ga slijedi i vidi cijeli dokument. Word i Excel godinama emitiraju upravo ovakav raspored, zbog čega hibridne datoteke nisu egzotični rubni slučaj već veliki udio onoga što poslovni cjevovodi primaju
Kako izgleda kraj hibridne datoteke
Raspored je najlakše razumjeti iz bajtova. Ovdje je kraj male hibridne datoteke sa skraćenim pomacima; u stvarnom Office izvozu vrijednost /XRefStm je tipično veliki pomak blizu kraja datoteke. Redoslijed čitanja je hod od kraja prema početku opisan u našem pregledu strukture PDF datoteke: pronađi %%EOF, pročitaj startxref, skoči na tablicu
% ... body objects, including object streams and, at byte 116,
% the cross-reference stream (a stream object with /Type /XRef) ...
xref % classic section: what startxref points at
0 4
0000000000 65535 f % slot 0: head of the free list, always present
0000000017 00000 n % object 1: the catalog, visible to any reader
0000000000 65535 f % object 2: marked free -- lives in an object stream
0000000000 65535 f % object 3: same; only the stream view locates it
trailer
<<
/Size 4
/Root 1 0 R
/XRefStm 116 % byte offset of the cross-reference stream
>>
startxref
7164 % byte offset of the 'xref' keyword above
%%EOF
Dva detalja u ovom ispisu nose cijeli mehanizam. Prvo, startxref namjerno pokazuje na klasični odjeljak: to je adresa na koju stari čitač mora sletjeti. Tok unakrsnih referenci dostupan je samo putem ključa /XRefStm unutar rječnika trailera, tako da parser koji nikada ne traži taj ključ nikada i ne sazna da tok postoji. Drugo, objekti 2 i 3 su laži benigne vrste. Klasična tablica ih deklarira slobodnima, ali to su stvarni objekti koji sjede unutar komprimiranog spremnika; oznaka slobodnog mjesta je ono što sprječava 1.4 čitača da se spotakne o unose koje ne može koristiti. Potrošač koji vjeruje samo klasičnom prikazu zaključuje da veći dio ovog dokumenta ne postoji
Kako se dva prikaza razilaze
Hibridna datoteka svježe proizašla iz Worda interno je dosljedna: oba prikaza opisuju isti dokument, svaki unutar svog deklariranog opsega. Problemi počinju kada datoteku uređuje alat koji razumije samo jedan od prikaza. Uzmite u obzir uslužni program za pečatiranje koji dodaje inkrementalno ažuriranje u klasičnom stilu: nove objekte, novi xref odjeljak, lanac /Prev do prethodnog odjeljka i novi trailer. Ako taj trailer odbaci ključ /XRefStm, prikaz toka postaje napušten; ako staru vrijednost kopira naprijed, prikaz toka i dalje opisuje dokument onakvim kakav je bio prije uređivanja. U svakom slučaju, dva indeksa se sada ne slažu oko toga što datoteka sadrži
Rezultirajuća datoteka ima osebujan potpis kvara: objekti vidljivi u jednom prikazu nedostaju ili su zastarjeli u drugom. Čitač koji razrješava putem prikaza toka pronalazi staru verziju ažuriranog objekta, ili uopće ne nalazi unos za dodani objekt. Čitač u tabličnom prikazu vidi uređivanje, ali gubi trag o komprimiranim objektima koje locira isključivo tok. U praksi se to pojavljuje kao polja obrasca koja prežive u jednom pregledniku, a nestanu u drugom, kao bilješke za koje se čini da ih je prolaz pečatiranja izbrisao, ili pretrage koje završe na potpuno pogrešnom objektu
Ono što otkrivanje pogrešaka kod ovih datoteka čini skupim jest to što ih Adobe Acrobat obično otvara bez prigovora: kada se indeks ne slaže s bajtovima, on tiho obnavlja podatke unakrsnih referenci skenirajući zaglavlja objekata, pa tko god je proizveo oštećenu datoteku ne vidi ništa sporno. Kvar izlazi na površinu kasnije, kada datoteka stigne do strogog potrošača, preflight validatora, usluge potpisivanja, zadatka arhivskog unosa, koji vjeruje deklariranoj strukturi i prijavljuje nedostajuće objekte ili nepodudaranje unakrsnih referenci. "Otvara se u redu u Acrobatu" tako započinje gotovo svaki ticket vezan za hibridnu desinhronizaciju
Otkrivanje hibridne datoteke u običnom Delphiju
Klasifikacija unosa ne zahtijeva PDF biblioteku. Ključ /XRefStm može se pojaviti samo unutar rječnika klasičnog trailera, a aktivni trailer nalazi se unutar zadnjih nekoliko kilobajta datoteke, jer specifikacija zahtijeva da se %%EOF pojavi blizu fizičkog kraja. Čitanje ograničenog repnog prozora i njegovo pretraživanje dovoljno je za trijažu:
uses
System.SysUtils, System.Classes, System.StrUtils, System.Math;
function IsHybridReferencePdf(const FileName: string): Boolean;
const
TailWindow = 2048;
var
Stream: TFileStream;
Buf: TBytes;
Tail: string;
Len, TrailerPos, NextPos, KeyPos, StartXrefPos: Integer;
begin
Result := False;
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
if Stream.Size < 48 then
Exit;
Len := Min(TailWindow, Integer(Stream.Size));
SetLength(Buf, Len);
Stream.Position := Stream.Size - Len;
Stream.ReadBuffer(Buf[0], Len);
finally
Stream.Free;
end;
// Every keyword involved is 7-bit ASCII, so a byte-wise decode is safe
Tail := TEncoding.ANSI.GetString(Buf);
// Find the LAST 'trailer' keyword: with incremental updates,
// the newest trailer is the one that governs the file
TrailerPos := 0;
NextPos := Pos('trailer', Tail);
while NextPos > 0 do
begin
TrailerPos := NextPos;
NextPos := PosEx('trailer', Tail, NextPos + 1);
end;
if TrailerPos := 0 then
Exit; // no classic trailer: a pure xref-stream file, not hybrid
// A hybrid trailer carries /XRefStm between 'trailer' and 'startxref'
KeyPos := PosEx('/XRefStm', Tail, TrailerPos);
StartXrefPos := PosEx('startxref', Tail, TrailerPos);
Result := (KeyPos > 0) and
((StartXrefPos = 0) or (KeyPos < StartXrefPos));
end;
Tri ishoda poklapaju se s tri rasporeda. Isključivo klasična datoteka ima trailer, ali nema /XRefStm: False. Datoteka koja se u potpunosti oslanja na tokove unakrsnih referenci uopće nema ključnu riječ trailer, njeni ključevi trailera žive u rječniku toka: također False, što je ispravno jer je takva datoteka komprimirana, a ne hibridna. Samo dvostruko indeksirani raspored vraća True
Za produkcijsku upotrebu, dva ojačanja vrijedna su dodatnih linija koda. Raščlanite cijeli broj iza /XRefStm, skočite na taj pomak i potvrdite da tamo doista stoji objekt toka s /Type /XRef; skraćena datoteka može nositi ključ iako toka više nema, što spada u drugačiju kategoriju od zdravog hibrida. Veličinu prozora pak tretirajte kao parametar: 2 KB pokriva običan Office izlaz, ali neuobičajeno veliki rječnik trailera može izbaciti ključnu riječ izvan dosega, a proširenje prozora je bolje rješenje od slučajnog proglašavanja datoteke klasičnom
Usmjeravanje hibridnih datoteka kroz Delphi cjevovod
Otkrivanje vam kupuje odluku o usmjeravanju. Za datoteke koje se samo čitaju, iscrtavaju ili provjeravaju, upotrijebite učitavač koji razrješava oba prikaza, a zatim provjerite ponašanje, a ne bajtove. PDFium komponenta parsira /XRefStm lanac tijekom učitavanja, pa je tablica objekata koju vaš kod vidi spojena tablica, a provjere opisane u našem članku o provjeri valjanosti objektnih i unakrsno-referentnih tokova primjenjuju se nepromijenjene. Ako je desinhronizirani hibrid dovoljno oštećen da odbije učitavanje, engine to prijavljuje kroz svoj skup pogrešaka, FPDF_ERR_SUCCESS, FPDF_ERR_UNKNOWN, FPDF_ERR_FILE, FPDF_ERR_FORMAT, FPDF_ERR_PASSWORD, FPDF_ERR_SECURITY i FPDF_ERR_PAGE, pri čemu je FPDF_ERR_FORMAT onaj koji nastaje zbog strukturnih oštećenja. Ipak, nemojte se oslanjati na taj signal: PDFium je popustljiv po dizajnu i tiho obnavlja većinu nedosljednih datoteka, pa uspješno učitavanje dokazuje tek da je datoteka bila popravljiva, a ne i da se njena dva prikaza slažu. Smislena provjera dosljednosti je usporedba onoga što pronalazi cjeloviti prolaz kroz objekte u odnosu na ono što deklarira /Size u traileru
Za datoteke koje vaš cjevovod mijenja, najsigurnija politika je spriječiti ih da uopće ostanu hibridne. Učitavanje praćeno potpunim spremanjem putem HotPDF-a prepisuje dokument s jedinstvenom, interno dosljednom unakrsnom referencom u jednom obliku: bez /XRefStm, bez drugog prikaza koji može ispasti iz sinhronizacije, svaki objekt posjeduje točno jedan indeksni unos. Takva normalizacija je ono što želite prije arhivskog unosa, prije strogog nizvodnog RIP-a ili usluge potpisivanja, i nakon svakog uređivanja primijenjenog na hibridni unos. Funkcionira jer je učitavač ispravno spojio prikaze prilikom ulaza, mehanizam koji HotPDF članak o hibridnim referencama detaljno prolazi
Jedina klasa datoteka koju treba ostaviti na miru su digitalno potpisani dokumenti. Potpuno prepisivanje premješta svaki bajt, što poništava bilo koji potpis izračunat nad izvornim rasponima. Promjena na potpisanom hibridu mora ući kao ispravno inkrementalno ažuriranje koje održava oba prikaza; datoteka koju treba samo čitati trebala bi proći netaknuta. Normalizacija je za datoteke koje posjedujete; potpisanim datotekama samo se dodaje na kraj
Hibridno-referentni PDF-ovi nisu loše oblikovani; oni su vlastiti most kompatibilnosti samog formata i Office aplikacije će ih nastaviti proizvoditi sve dok PDF 1.4 čitači opstaju u instalacijskoj bazi. Cjevovod koji može uočiti /XRefStm ključ, potvrditi valjanost spojenog dokumenta pomoću PDFium komponente i regenerirati čist jedinstveno indeksirani izlaz pomoću HotPDF komponente tretira ih kao ono što jesu: obični unosi s jednim dodatnim putokazom u traileru