Dalam alur kerja pencetakan perusahaan, pengarsipan, dan kepatuhan dokumen, file PDF tidak bisa begitu saja "dirender." File tersebut harus diaudit. Sebuah PDF mungkin berisi grup transparansi yang tidak diratakan yang dapat membuat prosesor gambar raster (RIP) lama menjadi crash, JavaScript tertanam yang menimbulkan risiko keamanan, atau gambar resolusi rendah yang akan terlihat sangat buruk saat dicetak pada 300 DPI.
Proses pemeriksaan PDF sebelum memasuki alur kerja produksi ini dikenal sebagai Preflighting. Dalam artikel ini, kita akan menjelajahi cara membangun alat audit risiko dan preflight otomatis di Delphi dengan memanfaatkan kemampuan pem-parsing-an tingkat rendah PDFium.
Pemeriksaan Preflight Utama
Audit risiko standar biasanya memeriksa elemen-elemen berikut di dalam PDF:
- Elemen Interaktif: Tindakan JavaScript, tindakan Peluncuran (mengeksekusi program eksternal), dan AcroForms.
- Metrik Sumber Daya: Kehadiran gambar resolusi rendah atau font tertanam yang hilang.
- Status Keamanan: Enkripsi dokumen, persyaratan kata sandi, dan izin akses (misalnya, pencetakan dinonaktifkan).
- Standar Dokumen: Validasi penanda kesesuaian PDF/A atau PDF/X dalam metadata dokumen.
Mengekstrak Metadata dan Anotasi PDF dengan PDFium
PDFium menyediakan API C yang tangguh yang dapat dipakai oleh Delphi. Untuk melakukan audit preflight, kita tidak hanya merender halaman; kita berjalan menelusuri pohon objek PDF. Mari kita lihat cara menelusuri halaman dokumen dan memeriksa anotasi untuk menemukan tindakan JavaScript yang berpotensi berisiko.
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;
Memeriksa Resolusi Gambar
Langkah preflight penting lainnya untuk alur kerja cetak adalah memastikan tidak ada gambar yang berada di bawah ambang batas DPI tertentu. PDFium memungkinkan Anda untuk mengekstrak objek gambar langsung dari aliran halaman. Dengan membagi dimensi piksel gambar yang diekstrak dengan dimensi fisiknya (dalam satuan point) yang ditempatinya di halaman PDF, Anda dapat menghitung DPI efektif.
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;
Mengintegrasikan dengan PDFium Component
Membangun mesin preflight yang tangguh dari awal menggunakan API C PDFium mentah memerlukan kode boilerplate yang signifikan dan pengetahuan mendalam tentang spesifikasi PDF. Menggunakan pembungkus sangat menyederhanakan hal ini. Dengan pembungkus Delphi tingkat tinggi, Anda dapat mengubah iterasi pointer C yang kompleks menjadi kode berorientasi objek yang bersih.
Dengan mengotomatiskan fase preflight, Anda mencegah file buruk mengganggu jalur produksi Anda, menghemat waktu dan sumber daya perenderan.
Catatan: Pem-parsing-an PDF lanjutan dan kemampuan preflight didukung penuh oleh Komponen VCL PDFium Component.