Odborný článok

Implementačné limity PDF/A a kontroly kódovania fontov

PDFium Component validuje implementačné limity ISO 19005-1 Annex C — tokeny názvov do 127 bajtov, 8191 elementov poľa, 4095 položiek slovníka a 28 úrovní vnorenia kontajnera — a nahlási symbolický TrueType font, ktorý nesie položku /Encoding. obe kontroly bežia na ceste bytového skenovania, takže Delphi alebo Lazarus aplikácia dostane verdikt bez toho, aby vôbec načítala PDFium DLL

To sú zlyhania, ktoré ľudí najviac mátia, pretože dokument vyzerá v poriadku. Renderuje sa, tlačí, každý font je vložený, výstupný zámer je prítomný. Potom ho validátor odmietne kvôli slovníku, ktorý má 4096 položiek, a nič vo viditeľnom dokumente nevysvetľuje prečo

Čo limity Annex C skutočne chránia?

Interoperabilitu s implementáciami, ktoré predchádzajú vášmu generátoru. Annex C prenáša implementačné limity PDF Reference do každej časti PDF/A a čísla nie sú náhodné — opisujú to, čo bol zodpovedajúci čítač historicky povinný zvládnuť. Súbor, ktorý ich presahuje, sa môže otvoriť dokonale v modernom prehliadači a zlyhať v archivačnom čítači, na ktorom si záznamový systém standardizoval pred pätnástimi rokmi, čo je presne scenár, ktorý PDF/A existuje, aby zabránil

Štyri limity sú inkluzívne. Token názvu s presne 127 bajtmi prechádza; 128 nie. Pole s presne 8191 elementmi prechádza; 8192 nie. PDFium Component z toho dôvodu pinuje obe strany každej hranice v svojom testovacom súbore, pretože off-by-one v kontrole limitu produkuje najhorší druh validátora: taký, ktorý odmieta zodpovedajúce súbory a napriek tomu mu veria

uses FPdfPdfa;

var
  Src: TFileStream;
  Res: TPdfAValidationResult;
begin
  Src := TFileStream.Create('archive.pdf', fmOpenRead or fmShareDenyWrite);
  try
    Res := ValidatePdfACompliance(Src);
    if pvaiArrayOverLimit in Res.Issues then
      Memo1.Lines.Add('An array carries more than 8191 elements');
    if pvaiDictOverLimit in Res.Issues then
      Memo1.Lines.Add('A dictionary carries more than 4095 entries');
    if pvaiNestingOverLimit in Res.Issues then
      Memo1.Lines.Add('Containers nest deeper than 28 levels');
    if pvaiNameOverLimit in Res.Issues then
      Memo1.Lines.Add('A name token is longer than 127 bytes');
  finally
    Src.Free;
  end;
end;

Ktoré generátory tieto limity skutočne trafia?

Také, ktoré stavajú štruktúru programovo, čo je väčšina biznis výstupu. Formulár s niekoľkými tisíckami polí produkuje pole /Annots alebo pole AcroForm /Fields, ktoré prerastie 8191. Strana, ktorej slovník zdrojov hromadí jednu položku na vygenerovaný obrázok alebo inštanciu fontu, prekročí 4095. Hlboko generované stromy štruktúry — značený dokument stavaný rekurziou nad vnoreným dátovým modelom — prejdú cez 28 úrovní bez toho, aby si toho niekto všimol, pretože na hĺbku vnorenia sa nikto nepozerá

Dlhé názvy prichádzajú z iného zvyku: kódovanie dát do tokenov názvov. Názov farebnej zložky postavený z identifikátora zákazníka, skupina voliteľného obsahu pomenovaná podľa celej cesty k súboru, formulárové pole, ktorého plne kvalifikovaný názov spája šesť úrovní hierarchie. Názvy sa generujú lacno a ľahko sa stanú dlhými a 127 bajtov zmizne rýchlejšie, než by čakali, ak je do hry zapletený UTF-8 kódovaný štítok

Oprava je v každom prípade štrukturálna. Rozdeľte pole, rozdeľte slovník, splošte vnorenie, skráťte názov — preflight odporúčanie pre každý problém menuje konkrétny limit namiesto toho, aby hovorilo, že súbor je neplatný. Marker injection tu nepomôže: toto nie sú metadatové nároky, to je tvar objektového grafu

Prečo symbolický TrueType font nesmie niesť /Encoding

Pretože ISO 19005-1 §6.3.7 pripúšťa pre symbolické TrueType fonty iba vstavaný cmap fontu a položka /Encoding by tomu odporovala. Symbolický font mapuje kódy na glyphy podľa vlastných pravidiel — to je to, čo symbolický znamená. Pridajte tabuľku kódovania a teraz existujú dve odpovede na otázku „ktorý glyph vyberá bajt 0x41", bez pravidla v súbore, ktoré by rozhodlo, ktorá vyhráva. Rozličné čítačky to řešia rozlične a dokument, ktorý sa v jednom prehliadači renderuje ako text, sa v druhom renderuje ako dingbats

PDFium Component číta príznak symbolic z /FontDescriptor, či je deskriptor zapísaný inline v slovníku fontu alebo referencovaný nepriamo. Nesymbolický TrueType font si ponechá svoje požadované /WinAnsiEncoding alebo /MacRomanEncoding bez toho, aby bol označený, pretože pre nesymbolické fonty je kódovanie presne to, o čo štandard stojí. Kontrola sa spúšťa na rozpore a nie na prítomnosti kódovania

if pvaiSymbolicTrueTypeEncoding in Res.Issues then
  Memo1.Lines.Add(
    'A symbolic TrueType font carries /Encoding; PDF/A admits only its ' +
    'built-in cmap (ISO 19005-1 6.3.7)');

Praktickým zdrojom tohto defektu je subsetting fontov produkentom, ktorý so všetkými TrueType fontami zaobchádza rovnako. Symbol, Wingdings, čiarové kódy a ikonové fonty sú bežnými nosičmi — presne fonty, ktoré biznis dokument používa pre zaškrtávacie políčka, logá a čiarové kódy, a presne tie, ktoré si nikto znova nepreskúšava, keď dokument zlyhá validáciou kvôli „fontom"

Ako problémy prichádzajú do preflight reportu

Štyri limity kontajnera sú klasifikované pod štruktúrou; problém kódovania symbolického TrueType je klasifikovaný pod obsahom. To rozdelenie záleží, keď report smeruje dvom rôznym ľuďom: štrukturálne zistenia zvyčajne patria tomu, kto napísal generátor, a obsahové zistenia tomu, kto dodal assety

Každý problém nesie odporúčanie, ktoré menuje liek v konkrétnych termínoch — skráťte tokeny názvov na 127 bajtov alebo menej, rozdeľte polia tak, aby žiadne nenesie viac než 8191 elementov, odstráňte /Encoding zo symbolických TrueType fontov. Report, ktorý hovorí „nie je zhodný s PDF/A", vyšetruje spúšťa. Report, ktorý hovorí, ktorý limit bol prekročený a o aký, ho ukončuje

Validácia bez DLL a prečo tu to záleží

Všetky vyššie uvedené kontroly bežia proti bajtom súboru, takže fungujú v službe, ktorá nemá nasadený PDFium binár, v kroku buildu alebo na stroji, kde je načítanie natívneho DLL politickým problémom. To je zámerne dizajnová línia v PDFium Component: kontroly, ktoré sa dajú odpovedať zo štruktúry, sa odpovedajú zo štruktúry a DLL sa rezervuje pre tie, ktoré skutočne potrebujú renderovací engine

Pre okolitý workflow — spustenie validácie nad priečinkom, produkcia reportov a rozhodnutie, čo so zisteniami — pozri návody k PDF/A preflight validácii v Delphi a CLI pre dávkový preflight report. Pre voľbu archivačného profilu, ktorá sedí nad všetkými týmito kontrolami, poznámky k archivačnej zhode PDF/A pokrývajú, ktorú časť a úroveň zamerať, skôr než začnete opravovať zistenia

PDFium Component obaľuje engine PDFium pre Delphi, C++Builder a Lazarus s VCL API vysokej úrovne a sadou validátorov zhody, ktoré bežia s DLL aj bez neho — podporované štandardy a platformy nájdete na produktovej stránke PDFium Component