Dans les flux de travail d'impression d'entreprise, d'archivage et de conformité des documents, un fichier PDF ne peut pas simplement être "rendu". Il doit être audité. Un PDF peut contenir des groupes de transparence non aplatis qui font planter les anciens processeurs d'images raster (RIP), du JavaScript intégré qui pose un risque de sécurité, ou des images basse résolution qui auront un rendu terrible une fois imprimées à 300 DPI.
Ce processus d'inspection d'un PDF avant qu'il n'entre dans un flux de production est connu sous le nom de Contrôle en amont (Preflighting). Dans cet article, nous allons explorer comment créer un outil automatisé de contrôle en amont et d'audit des risques dans Delphi en exploitant les capacités d'analyse de bas niveau de PDFium.
Contrôles en amont clés
Un audit des risques standard vérifie généralement les éléments suivants dans un PDF :
- Éléments interactifs : Actions JavaScript, actions de lancement (Launch actions, exécution de programmes externes) et AcroForms.
- Métriques de ressources : Présence d'images basse résolution ou polices intégrées manquantes.
- État de la sécurité : Chiffrement du document, exigences de mot de passe et autorisations d'accès (par exemple, impression désactivée).
- Normes de document : Validation des marqueurs de conformité PDF/A ou PDF/X dans les métadonnées du document.
Extraction des métadonnées et des annotations PDF avec PDFium
PDFium fournit une API C robuste que Delphi peut consommer. Pour effectuer un audit de contrôle en amont, nous ne nous contentons pas de rendre la page ; nous parcourons l'arborescence des objets PDF. Voyons comment itérer à travers les pages du document et inspecter les annotations pour trouver des actions JavaScript potentiellement risquées.
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;
Vérification de la résolution d'image
Une autre étape critique du contrôle en amont pour les flux de travail d'impression consiste à s'assurer qu'aucune image ne tombe en dessous d'un seuil DPI spécifique. PDFium vous permet d'extraire des objets image directement à partir du flux de page. En divisant les dimensions en pixels de l'image extraite par les dimensions physiques (en points) qu'elle occupe sur la page PDF, vous pouvez calculer le DPI effectif.
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;
Intégration avec PDFium Component
Construire un moteur de contrôle en amont robuste à partir de zéro à l'aide de l'API C brute de PDFium nécessite un code standard (boilerplate) important et une connaissance approfondie de la spécification PDF. L'utilisation d'un wrapper simplifie énormément cela. Avec un wrapper Delphi de haut niveau, vous pouvez transformer des itérations de pointeurs C complexes en un code propre orienté objet.
En automatisant la phase de contrôle en amont, vous évitez que de mauvais fichiers ne bloquent votre pipeline de production, ce qui permet d'économiser du temps et des ressources de rendu.
Remarque : L'analyse avancée des PDF et les fonctionnalités de contrôle en amont sont entièrement prises en charge par le composant VCL PDFium Component.