ConvertToPDFA transforma um documento comum num documento de arquivo numa única chamada: remove o que a parte escolhida proíbe, adiciona o que a parte exige, indica a parte que o documento reclama, e depois verifica o resultado. A reclamação só é reportada como satisfeita quando a verificação passa, e GetPDFAConversionReport lista o que foi feito e o que ainda impede
Essa última propriedade é a decisão de desenho que vale a pena aprofundar. Um conversor que apõe a reclamação sem verificar é pior do que nenhum conversor, porque um ficheiro que diz ser de arquivo e não é passa diretamente pelos próprios sistemas que de outro modo o apanhariam. A falha aparece anos depois, numa auditoria, num documento que ninguém consegue regenerar
Porque razão um PDF com bom aspeto falha uma verificação PDF/A?
Na maioria das vezes porque os dois sítios onde um PDF diz quem o escreveu discordam. Um validador lê tanto o dicionário de informações do documento como o pacote XMP e rejeita um ficheiro em que difiram — e a maioria dos ficheiros que falham neste ponto simplesmente nunca tiveram a metade XMP escrita
RepairDocumentMetadata põe-os de acordo e devolve quantas entradas reparou. Onde apenas uma metade transporta um valor, a outra é preenchida a partir dela, pelo que nada do que já estava registado é descartado. Ninguém tem de decidir qual a cópia autoritativa, porque na prática uma cópia está vazia
Há um segundo reparo na mesma chamada que apanha um caso mais subtil. Um documento definido para um modo PDF/A tem a identificação de normas restaurada se tiver sido perdida, o que acontece sempre que um chamador fornece um pacote XMP próprio. Sem essa identificação, um validador lê o ficheiro como um PDF comum e reporta todas as regras da parte reclamada como não satisfeitas — uma falha de aspeto espetacular com uma causa pequena
var
Lib: TPDFlib;
Repaired: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('incoming.pdf', '');
Repaired := Lib.RepairDocumentMetadata;
Log(Format('%d metadata entries brought into agreement', [Repaired]));
Lib.SaveToFile('incoming-fixed.pdf');
finally
Lib.Free;
end;
end;
Escolher a parte antes de converter
SetPDFAMode e ConvertToPDFA partilham a mesma numeração de modos, e três dos valores são recentes. O modo 9 é PDF/A-4, a parte construída sobre PDF 2.0. O modo 10 é PDF/A-4e, que adicionalmente permite 3D e multimédia enriquecida, e o modo 11 é PDF/A-4f, que permite um ficheiro embutido de qualquer formato
A parte 4 identifica-se de forma diferente das partes anteriores: por número de parte e pelo ano de publicação da parte, sem letra de conformidade para PDF/A-4 simples e com a letra E ou F para as duas extensões. A verificação reconhece a parte 4, julga os seus ficheiros contra PDF 2.0 em vez de 1.7, e reporta um ficheiro da parte 4 que não indica o seu ano de revisão
Cada ficheiro embutido num documento da parte 4 indica como se relaciona com o documento, como as partes 3 e 4 ambas exigem. Esta é a regra que costumava apanhar anexos comuns: a relação era escrita apenas para os anexos depois do primeiro e nunca para o último, pelo que um documento com um único anexo — o caso comum — não transportava nenhuma e falhava a validação exatamente nesse ponto
var
Verdict: Integer;
begin
Lib.LoadFromFile('report.pdf', '');
Verdict := Lib.ConvertToPDFA(9); // 9 = PDF/A-4, 10 = 4e, 11 = 4f
Memo1.Lines.Text := Lib.GetPDFAConversionReport;
if Verdict = 1 then
Lib.SaveToFile('report-pdfa4.pdf')
else
Log('conversion incomplete - see the report for what stands in the way');
end;
Para que serve o relatório de conversão
Para decidir o que fazer a seguir. Uma conversão bem-sucedida não precisa de relatório; uma conversão que não o consegue é toda a razão de o relatório existir. Alguns obstáculos são removíveis por um conversor e outros não — encriptação, conteúdo proibido que transporta significado, um programa de tipo de letra que simplesmente não está em lado nenhum na máquina. O relatório distingue o que foi feito do que resta, o que transforma "conversão falhou" num item de trabalho
Trate o veredito como a porta num pipeline de lote. Converta, leia o veredito e encaminhe o ficheiro: arquive os que passaram, coloque os restantes em fila para um humano com o relatório em anexo. O que não deve fazer é guardar a saída de uma conversão falhada no arquivo porque tem melhor aspeto do que a entrada — agora transporta uma reclamação que a verificação se recusou a confirmar
Ler a marca que um ficheiro já transporta
Antes de converter seja o que for, saiba o que o documento diz sobre si próprio. Uma verificação PDF/A que não consegue ler a marca de normas existente julga todos os ficheiros contra a parte 1, seja qual for o que declaram, o que significa que um documento PDF/A-2 ou PDF/A-2 perfeitamente válido é reportado como não transportando marca nenhuma e como sendo de uma versão demasiado alta — o oposto da verdade
A marca é lida quer o produtor a tenha escrito como um elemento XMP quer como um atributo. Ambas as formas são XMP comum, e aceitar apenas uma delas deixa ficheiros de outros produtores com aspeto de não marcados. Se alguma vez se perguntou porque razão um documento que valida noutro sítio falha no seu próprio pipeline, este é um bom sítio para procurar primeiro
Higienizar antes de arquivar, e o bug que vale a pena conhecer
A conversão para arquivo e a higienização costumam correr em conjunto, porque o conteúdo que uma política de segurança quer remover sobrepõe-se fortemente ao conteúdo que o PDF/A proíbe. SanitizeDocument remove JavaScript, e remover o último script também remove a árvore de nomes vazia que deixa para trás — uma árvore que de outro modo continuaria a dizer a um leitor que o documento transportava scripts
Essa segunda metade foi aprendida pela pior forma: um erro off-by-one na lista de pacotes fazia com que a higienização reportasse a remoção de scripts sem remover nenhum, pelo que um documento que tinha sido higienizado continuava a executar os seus scripts ao ser aberto. É um bom argumento para o princípio geral em que todo este artigo se baseia — verificar o resultado em vez de confiar na operação, no seu próprio pipeline tanto como na biblioteca
Para o trabalho de arquivo envolvente, veja os guias de preflight PDF/A e PDF/UA, de redação verdadeira e remoção de conteúdo e de esquemas de extensão XMP PDF/A-3 para Factur-X, que aborda o lado dos metadados quando o documento arquivado transporta também dados estruturados de fatura
O PDFlibPas é uma biblioteca PDF nativa em Pascal para Delphi, C++Builder e Lazarus, pelo que conversão, reparação e validação acontecem todas dentro do seu próprio processo sem nenhuma ferramenta externa na cadeia — veja a página do produto PDFlibPas para as partes PDF/A suportadas e plataformas