Įmonių spausdinimo, archyvavimo ir dokumentų atitikties darbo eigose PDF failo negalima tiesiog „atvaizduoti“. Jį būtina audituoti. PDF faile gali būti nesuplokštintų skaidrumo grupių, kurios užlaužia (angl. crash) senus rastrinių vaizdų procesorius (RIP), įterptojo „JavaScript“, keliančio saugumo riziką, arba mažos raiškos vaizdų, kurie spausdinant 300 DPI raiška atrodys prastai.
Šis PDF patikrinimo procesas prieš jam patenkant į gamybos darbo eigą yra žinomas kaip išankstinis patikrinimas (angl. Preflighting). Šiame straipsnyje apžvelgsime, kaip „Delphi“ aplinkoje sukurti automatizuotą išankstinio patikrinimo ir rizikos audito įrankį, pasitelkiant žemo lygio „PDFium“ analizės galimybes.
Pagrindiniai išankstinio patikrinimo žingsniai
Standartinis rizikos auditas paprastai tikrina šiuos PDF elementus:
- Interaktyvūs elementai: „JavaScript“ veiksmai, paleidimo (angl. Launch) veiksmai (vykdantys išorines programas) ir „AcroForms“.
- Išteklių metrika: mažos raiškos vaizdai arba trūkstami įterptieji šriftai.
- Saugumo būsena: dokumento šifravimas, slaptažodžio reikalavimai ir prieigos teisės (pvz., išjungtas spausdinimas).
- Dokumentų standartai: PDF/A arba PDF/X atitikties žymeklių patvirtinimas dokumento metaduomenyse.
PDF metaduomenų ir anotacijų išskyrimas su „PDFium“
„PDFium“ teikia patikimą C API, kurią galima naudoti „Delphi“ aplinkoje. Norėdami atlikti išankstinį auditą, mes ne tik atvaizduojame puslapį, bet ir pereiname per PDF objektų medį. Pažiūrėkime, kaip pereiti per dokumento puslapius ir patikrinti anotacijas ieškant galimai rizikingų „JavaScript“ veiksmų.
uses
System.SysUtils, pdfium_lib;
procedure AuditPdfSecurity(const FileName: string);
var
Doc: FPDF_DOCUMENT;
PageCount, i, j: Integer;
Page: FPDF_PAGE;
AnnotCount: Integer;
Annot: FPDF_ANNOTATION;
AnnotSubType: FPDF_ANNOTATION_SUBTYPE;
Action: FPDF_ACTION;
ActionType: ULONG;
begin
FPDF_InitLibrary();
try
// Load the document without a password
Doc := FPDF_LoadDocument(PAnsiChar(AnsiString(FileName)), nil);
if Doc = nil then
raise Exception.Create('Failed to load document or password required.');
try
PageCount := FPDF_GetPageCount(Doc);
Writeln(Format('Auditing %d pages...', [PageCount]));
for i := 0 to PageCount - 1 do
begin
Page := FPDF_LoadPage(Doc, i);
if Page <> nil then
begin
AnnotCount := FPDFPage_GetAnnotCount(Page);
for j := 0 to AnnotCount - 1 do
begin
Annot := FPDFPage_GetAnnot(Page, j);
if Annot <> nil then
begin
AnnotSubType := FPDFAnnot_GetSubtype(Annot);
// Check for Link Annotations that might have malicious actions
if AnnotSubType = FPDF_ANNOT_LINK then
begin
Action := FPDFAnnot_GetLinkAction(Annot);
if Action <> nil then
begin
ActionType := FPDFAction_GetType(Action);
// 2 represents PDFACTION_URI, 3 represents PDFACTION_SOUND, 4 represents PDFACTION_MOVIE
// We specifically look out for PDFACTION_LAUNCH or PDFACTION_JAVA_SCRIPT
if (ActionType = PDFACTION_JAVA_SCRIPT) or (ActionType = PDFACTION_LAUNCH) then
begin
Writeln(Format('WARNING: Malicious action detected on page %d', [i + 1]));
end;
end;
end;
FPDFPage_CloseAnnot(Annot);
end;
end;
FPDF_ClosePage(Page);
end;
end;
finally
FPDF_CloseDocument(Doc);
end;
finally
FPDF_DestroyLibrary();
end;
end;
Vaizdų raiškos tikrinimas
Kitas svarbus išankstinio patikrinimo žingsnis spausdinimo darbo eigoms yra užtikrinti, kad joks vaizdas nebūtų žemesnės nei nurodytos DPI ribos. „PDFium“ leidžia išskirti vaizdų objektus tiesiogiai iš puslapio srauto. Padalijus išskirto vaizdo pikselių matmenis iš fizinių matmenų (taškais), kuriuos jis užima PDF puslapyje, galima apskaičiuoti efektyvųjį DPI.
procedure AuditPageImages(Page: FPDF_PAGE);
var
ObjCount, i: Integer;
PageObj: FPDF_PAGEOBJECT;
ImgWidth, ImgHeight: Integer;
begin
ObjCount := FPDFPage_CountObjects(Page);
for i := 0 to ObjCount - 1 do
begin
PageObj := FPDFPage_GetObject(Page, i);
if FPDFPageObj_GetType(PageObj) = FPDF_PAGEOBJ_IMAGE then
begin
FPDFImageObj_GetBitmap(PageObj); // Returns an FPDF_BITMAP you can inspect
// Retrieve metadata using FPDFImageObj_GetImageMetadata
// Calculate effective DPI based on quad coordinates
end;
end;
end;
Integravimas su „PDFium Component“
Kuriant patikimą išankstinio patikrinimo variklį nuo nulio naudojant neapdorotą „PDFium C API“, reikia parašyti daug standartinio kodo (angl. boilerplate code) ir turėti gilių žinių apie PDF specifikaciją. Naudojant apvalkalą (angl. wrapper), tai labai supaprastėja. Turėdami aukšto lygio „Delphi“ apvalkalą, sudėtingas C rodyklių iteracijas galite paversti švariu, objektiniu kodu.
Automatizuodami išankstinio patikrinimo fazę, užkirstate kelią blogiems failams sugadinti jūsų gamybos konvejerį, taip sutaupydami ir laiko, ir atvaizdavimo išteklių.
Pastaba: pažangios PDF analizės ir išankstinio patikrinimo galimybės yra visiškai palaikomos „PDFium Component VCL“ komponente.