corrected the issue regarding the headers in the pdfa files

This commit is contained in:
vididvidid
2025-09-30 07:09:56 +00:00
parent ef3a6cb1c0
commit b1550fdc10
13 changed files with 207 additions and 138 deletions

140
my_pdfa_test.c Normal file
View File

@@ -0,0 +1,140 @@
// File: my_pdfa_test.c (Final version with embedded font)
#include "pdfio.h"
#include "pdfio-content.h"
#include <stdio.h>
#include <string.h>
//
// Local functions...
//
static bool my_error_cb(pdfio_file_t *pdf, const char *message, void *data);
static bool create_pdfa_test_file(const char *filename, const char *pdfa_version);
static int test_pdfa(void);
//
// 'my_error_cb()' - A simple error callback to print detailed messages.
//
static bool // O - true to continue, false to stop
my_error_cb(pdfio_file_t *pdf, // I - PDF file
const char *message, // I - Error message
void *data) // I - Callback data (unused)
{
(void)pdf; // Unused
(void)data; // Unused
fprintf(stderr, "PDFio Error: %s\n", message);
return (false); // Stop on any error
}
//
// 'create_pdfa_test_file()' - A helper function to generate a simple PDF/A file.
//
static bool // O - true on success, false on error
create_pdfa_test_file(
const char *filename, // I - Name of the PDF file to create
const char *pdfa_version) // I - PDF/A version string (e.g., "PDF/A-1b")
{
pdfio_file_t *pdf; // Output PDF file
pdfio_rect_t media_box = { 0.0, 0.0, 612.0, 792.0 };
// Media box for US Letter
pdfio_obj_t *font; // Font object
pdfio_dict_t *page_dict; // Page dictionary
pdfio_stream_t *st; // Page content stream
char text[256]; // Text to write to page
snprintf(text, sizeof(text), "This is a compliance test for %s.", pdfa_version);
printf(" Creating '%s' for %s compliance check...\n", filename, pdfa_version);
if ((pdf = pdfioFileCreate(filename, pdfa_version, &media_box, NULL, my_error_cb, NULL)) == NULL)
{
fprintf(stderr, " ERROR: pdfioFileCreate failed for '%s'.\n", filename);
return (false);
}
// --- THIS IS THE KEY CHANGE ---
// Instead of using a base font, we now load and embed a font from a file.
if ((font = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", false)) == NULL)
{
fprintf(stderr, " ERROR: Unable to embed font 'testfiles/OpenSans-Regular.ttf'.\n");
pdfioFileClose(pdf);
return (false);
}
page_dict = pdfioDictCreate(pdf);
pdfioPageDictAddFont(page_dict, "F1", font);
st = pdfioFileCreatePage(pdf, page_dict);
pdfioContentSetTextFont(st, "F1", 12.0);
pdfioContentTextBegin(st);
pdfioContentTextMoveTo(st, 72.0, 720.0);
pdfioContentTextShow(st, false, text);
pdfioContentTextEnd(st);
pdfioStreamClose(st);
pdfioFileClose(pdf);
printf(" Successfully created '%s'.\n", filename);
return (true);
}
//
// 'test_pdfa()' - The main test runner for the PDF/A feature.
//
static int // O - 0 on success, 1 on error
test_pdfa(void)
{
int status = 0;
pdfio_file_t *fail_pdf;
pdfio_rect_t media_box = { 0.0, 0.0, 612.0, 792.0 };
puts("---- Running PDF/A Generation Tests ----\n");
if (!create_pdfa_test_file("test-pdfa-1b.pdf", "PDF/A-1b")) status = 1;
if (!create_pdfa_test_file("test-pdfa-2b.pdf", "PDF/A-2b")) status = 1;
if (!create_pdfa_test_file("test-pdfa-2u.pdf", "PDF/A-2u")) status = 1;
if (!create_pdfa_test_file("test-pdfa-3b.pdf", "PDF/A-3b")) status = 1;
if (!create_pdfa_test_file("test-pdfa-3u.pdf", "PDF/A-3u")) status = 1;
if (!create_pdfa_test_file("test-pdfa-4.pdf", "PDF/A-4")) status = 1;
puts("\n---- Running PDF/A Encryption Block Test ----\n");
printf(" Creating PDF/A file to test encryption failure...\n");
if ((fail_pdf = pdfioFileCreate("test-pdfa-fail.pdf", "PDF/A-1b", &media_box, NULL, my_error_cb, NULL)) == NULL)
{
fprintf(stderr, " ERROR: pdfioFileCreate failed for encryption test.\n");
return (1);
}
if (pdfioFileSetPermissions(fail_pdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_RC4_128, "owner", "user"))
{
fputs(" ERROR: pdfioFileSetPermissions succeeded but should have FAILED!\n", stderr);
status = 1;
}
else
{
puts(" SUCCESS: Correctly blocked encryption for PDF/A file as expected.");
}
pdfioFileClose(fail_pdf);
puts("\n-------------------------------------------");
if (status == 0)
puts("✅ All PDF/A tests passed.");
else
puts("❌ One or more PDF/A tests FAILED.");
puts("-------------------------------------------\n");
return (status);
}
//
// 'main()' - Main entry for the test program.
//
int // O - Exit status
main(void)
{
return (test_pdfa());
}

BIN
my_test_executable Executable file

Binary file not shown.

View File

@@ -1114,8 +1114,9 @@ pdfioFileOpen(
char message[8192]; // Message string
temp.filename = (char *)filename;
snprintf(message, sizeof(message), "Unable to allocate memory for PDF file - %s", strerror(errno));
snprintf(message, sizeof(message), "Unable to allocate memory for PDF file: %s", strerror(errno));
(error_cb)(&temp, message, error_cbdata);
return (NULL);
}
@@ -1328,28 +1329,30 @@ pdfioFileSetPermissions(
if (!pdf)
return (false);
// 1. First, check if this is a PDF/A file trying to use encryption. This check must be first.
if (pdf->pdfa != _PDFIO_PDFA_NONE && encryption != PDFIO_ENCRYPTION_NONE)
{
_pdfioFileError(pdf, "Encryption is not allowed for PDF/A files.");
return (false);
}
// 2. If no encryption is being applied anyway, we are done.
if (encryption == PDFIO_ENCRYPTION_NONE)
return (true);
// 3. Check if it's too late in the file creation process to set permissions.
if (pdf->num_objs > 3) // First three objects are pages, info, and root
{
_pdfioFileError(pdf, "You must call pdfioFileSetPermissions before adding any objects.");
return (false);
}
if (encryption == PDFIO_ENCRYPTION_NONE)
return (true);
// 4. If all checks pass, proceed with locking the document.
pdf->encrypt_metadata = true;
return (_pdfioCryptoLock(pdf, permissions, encryption, owner_password, user_password));
}
//
// 'pdfioFileSetSubject()' - Set the subject for a PDF file.
//
@@ -1535,10 +1538,9 @@ create_common(
if (!error_cb)
{
error_cb = _pdfioFileDefaultError;
error_cbdata = NULL;i
(error_cb)(&temp,message,error_cbdata)
error_cbdata = NULL;
return (NULL)
return (NULL);
}
// Allocate a PDF file structure...
@@ -1602,7 +1604,7 @@ create_common(
else
{
actual_version = version;
pdf->pdfa = _PDFIO_PDFA_NONe;
pdf->pdfa = _PDFIO_PDFA_NONE;
}
pdf->version = strdup(actual_version);
@@ -1638,14 +1640,19 @@ create_common(
// Write a standard PDF header...
if (!strncmp(version, "PCLm-", 5))
{
// PCLm has a special header format
if (!_pdfioFilePrintf(pdf, "%%PDF-1.4\n%%%s\n", version))
goto error;
}
else if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version))
else
{
goto error;
// For all other PDFs, including all PDF/A versions, write the header
// with the binary comment.
if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", pdf->version))
goto error;
}
// Create the pages object...
if ((dict = pdfioDictCreate(pdf)) == NULL)
goto error;

BIN
test-pdfa-1b.pdf Normal file

Binary file not shown.

BIN
test-pdfa-2b.pdf Normal file

Binary file not shown.

BIN
test-pdfa-2u.pdf Normal file

Binary file not shown.

BIN
test-pdfa-3b.pdf Normal file

Binary file not shown.

BIN
test-pdfa-3u.pdf Normal file

Binary file not shown.

BIN
test-pdfa-4.pdf Normal file

Binary file not shown.

49
test-pdfa-fail.pdf Normal file
View File

@@ -0,0 +1,49 @@
%PDF-1.4
%<25><><EFBFBD><EFBFBD>
4 0 obj
<</Length 959 /Subtype/XML/Type/Metadata>>
stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
<xmp:CreateDate>2025-09-30T06:11:15Z</xmp:CreateDate>
<xmp:MetadataDate>2025-09-30T06:11:15Z</xmp:MetadataDate>
</rdf:Description>
<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
<pdf:Producer>pdfio/1.6.0</pdf:Producer>
</rdf:Description>
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:format>application/pdf</dc:format>
</rdf:Description>
<rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">
<pdfaid:part>1</pdfaid:part>
<pdfaid:conformance>B</pdfaid:conformance>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="r"?>
endstream
endobj
2 0 obj
<</CreationDate(D:20250930061115Z)/Producer(pdfio/1.6.0)>>
endobj
1 0 obj
<</Count 0/Kids[]/Type/Pages>>
endobj
3 0 obj
<</Metadata 4 0 R/OutputIntents[<</Info(CMYK Printing)/OutputCondition(CMYK)/OutputConditionIdentifier(CGATS001)/S/GTS_PDFA1/Type/OutputIntent>>]/Pages 1 0 R/Type/Catalog>>
endobj
xref
0 5
0000000000 65535 f
0000001130 00000 n
0000001056 00000 n
0000001176 00000 n
0000000015 00000 n
trailer
<</ID[<7498FA525DF95B5E7A90092930B04369><7498FA525DF95B5E7A90092930B04369>]/Info 2 0 R/Root 3 0 R/Size 5>>
startxref
1364
%%EOF

BIN
testcompilance Executable file

Binary file not shown.

BIN
testpdfacompilance Executable file

Binary file not shown.

View File

@@ -1,127 +0,0 @@
//
// Test program from pdf-a
//
// This file is specifically designed to test the PDF/A creation feature
//
#include "pdfio.h"
#include "pdfio-content.h"
#include <stdio.h>
#include <string.h>
// Local Function
static bool create_pdfa_test_file(const char *filename, const char *pdfa_version);
static int test_pdfa(void);
// 'create_pdfa_test_file()' -> A helper function to generate a simple
// PDF/A file
static bool // 0 - true on success, false on error
create_pdfa_test_file(
const char *filename, // I - Name of the pdf file to create
const char *pdfa_version) // I - PDF/A version string (e.g., "PDF/A-1b")
{
pdfio_file_t *pdf; // Ouput PDF File
pdfio_rect_t media-box = { 0.0, 0.0, 612.0, 792.0 }; // Media box for US Letter
pdfio_obj_t *font; // Font Object
pdfio_dict_t *page_dict; // Page Dictionary
pdfio_stream_t *st; // Page content stream
char text[256]; // Text to write to page
// Let the user know what we're doing
snprintf(text, sizeof(text), "This is a compliance test for %s.", pdfa_version);
printf(" Creating '%s' for %s compilance check ... \n", filename, pdfa_version);
// Create the PDF/A file using the specified version string
if ((pdf = pdfioFileCreate(filename, pdfa_version, &media_box, NULL, NULL, NULL)) == NULL)
{
fprintf(stderr, " ERROR: Unable to create '%s'.\n",filename);
return (false);
}
// Add some basic content to make it a valid, non-empty PDF
font = pdfioFileCreateFontObjFromBase(pdf,"Helvetica");
page_dict = pdfioDictCreate(pdf);
pdfioPageDictAddFont(page_dict, "F1", font);
st = pdfioFileCreatePage(pdf, page_dict);
pdfioContentSetTextFont(st, "F1", 12.0);
pdfioContentTextBegin(st);
pdfioContentTextMoveTo(st, 72.0, 720.0);
pdfioContentTextShow(st, false, text);
pdfioContentTextEnd(st);
// Close the stream and the file to finalize and save it
pdfioStreamClose(st);
pdfioFileClose(pdf);
printf(" Successfully created '%s'.\n", filename);
return (true);
}
// 'test_pdfa()' - The main test runner for the PDF/A feature.'
static int // 0 - 0 on success, 1 on error
test_pdfa(void)
{
int status = 0; // Overall test status
pdfio_file_t *fail_pdf; // PDF for failure test
pdfio_rect_t media_box = {0.0, 0.0, 612.0, 792.0 };
puts (" ----- Running PDF/A Generation Tests --- \n");
// --- Positive Test Cases: Generate one file for each conformance level ---
if (!create_pdfa_test_file("test-pdfa-1b.pdf", "PDF/A-1b")) status = 1;
if (!create_pdfa_test_file("test-pdfa-2b.pdf", "PDF/A-2b")) status = 1;
if (!create_pdfa_test_file("test-pdfa-2u.pdf", "PDF/A-2u")) status = 1;
if (!create_pdfa_test_file("test-pdfa-3b.pdf", "PDF/A-3b")) status = 1;
if (!create_pdfa_test_file("test-pdfa-3u.pdf", "PDF/A-3u")) status = 1;
if (!create_pdfa_test_file("test-pdfa-4.pdf", "PDF/A-4")) status = 1;
// --- Navigate test case: Ensure encryption is blocked --
puts("\n--- Running PDF/A Encryption Block Test ---\n");
printf(" Creating PDF/A file to test encryption failure .. \n");
if ((fail_pdf = pdfioFileCreate("test-pdfa-fail.pdf", "PDF/A-1b", &media_box, NULL,NULL,NULL)) == NULL)
{
fputs(" ERROR: Unable to create temporary file for encryption test.\n", stderr);
return (1);
}
// This call MUST fail because encryption is not allowed in PDF/A
if (pdfioFileSetPermissions(fail_pdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_RC4_128, "owner", "user"))
{
fputs(" ERROR: pdfioFileSetPermission succeeded but should have FAILED!\n",stderr);
status = 1; // Mark the test suite as failed
}
else
{
puts(" SUCCESS: COrrectly blocked encryption for PDF/A file as expected.");
}
pdfioFileClose(fail_pdf);
//--- Final Summary----
puts("\n-------------------------");
if (status == 0)
puts(" All PDF/A test passed.");
else
puts(" One or more PDF/A tests FAILED.");
puts("\n--------------------------------\n");
return (status);
}
// 'main()'
int // 0 - Exit status
main(void)
{
return (test_pdfa());
}