mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-10-08 11:45:00 +02:00
corrected the issue regarding the headers in the pdfa files
This commit is contained in:
140
my_pdfa_test.c
Normal file
140
my_pdfa_test.c
Normal 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
BIN
my_test_executable
Executable file
Binary file not shown.
29
pdfio-file.c
29
pdfio-file.c
@@ -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
BIN
test-pdfa-1b.pdf
Normal file
Binary file not shown.
BIN
test-pdfa-2b.pdf
Normal file
BIN
test-pdfa-2b.pdf
Normal file
Binary file not shown.
BIN
test-pdfa-2u.pdf
Normal file
BIN
test-pdfa-2u.pdf
Normal file
Binary file not shown.
BIN
test-pdfa-3b.pdf
Normal file
BIN
test-pdfa-3b.pdf
Normal file
Binary file not shown.
BIN
test-pdfa-3u.pdf
Normal file
BIN
test-pdfa-3u.pdf
Normal file
Binary file not shown.
BIN
test-pdfa-4.pdf
Normal file
BIN
test-pdfa-4.pdf
Normal file
Binary file not shown.
49
test-pdfa-fail.pdf
Normal file
49
test-pdfa-fail.pdf
Normal 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
BIN
testcompilance
Executable file
Binary file not shown.
BIN
testpdfacompilance
Executable file
BIN
testpdfacompilance
Executable file
Binary file not shown.
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user