Compare commits

..

No commits in common. "57a01a73173eaadc37e0dbe206f5e35587cdd6bf" and "cad8f450ab0d267db33e47c6a171bb0c372a87d8" have entirely different histories.

8 changed files with 26 additions and 54 deletions

View File

@ -27,8 +27,6 @@ v1.5.3 - YYYY-MM-DD
- Fixed decryption of UTF-16 strings (Issue #42) - Fixed decryption of UTF-16 strings (Issue #42)
- Fixed decryption of PDF files with large permission values. - Fixed decryption of PDF files with large permission values.
- Fixed support for EncryptMetadata key in the encryption dictionary. - Fixed support for EncryptMetadata key in the encryption dictionary.
- Fixed `pdfioObjCopy` and `pdfioPageCopy` to properly identify the source PDF
file being used (Issue #125)
v1.5.2 - 2025-04-12 v1.5.2 - 2025-04-12

View File

@ -8,8 +8,8 @@
// //
// Usage: // Usage:
// //
// ./pdfiomerge [-o OUTPUT.pdf] INPUT.pdf [... INPUT.pdf] // ./pdfmerge [-o OUTPUT.pdf] INPUT.pdf [... INPUT.pdf]
// ./pdfiomerge INPUT.pdf [... INPUT.pdf] >OUTPUT.pdf // ./pdfmerge INPUT.pdf [... INPUT.pdf] >OUTPUT.pdf
// //
#include <pdfio.h> #include <pdfio.h>
@ -47,7 +47,7 @@ main(int argc, // I - Number of command-line arguments
} }
else if (!strncmp(argv[i], "--", 2)) else if (!strncmp(argv[i], "--", 2))
{ {
fprintf(stderr, "pdfiomerge: Unknown option '%s'.\n", argv[i]); fprintf(stderr, "pdfmerge: Unknown option '%s'.\n", argv[i]);
return (usage(stderr)); return (usage(stderr));
} }
else if (argv[i][0] == '-') else if (argv[i][0] == '-')
@ -59,14 +59,14 @@ main(int argc, // I - Number of command-line arguments
case 'o' : // -o OUTPUT.pdf case 'o' : // -o OUTPUT.pdf
if (outpdf) if (outpdf)
{ {
fputs("pdfiomerge: Only one output file can be specified.\n", stderr); fputs("pdfmerge: Only one output file can be specified.\n", stderr);
return (usage(stderr)); return (usage(stderr));
} }
i ++; i ++;
if (i >= argc) if (i >= argc)
{ {
fputs("pdfiomerge: Missing output filename after '-o'.\n", stderr); fputs("pdfmerge: Missing output filename after '-o'.\n", stderr);
return (usage(stderr)); return (usage(stderr));
} }
@ -75,7 +75,7 @@ main(int argc, // I - Number of command-line arguments
break; break;
default : default :
fprintf(stderr, "pdfiomerge: Unknown option '-%c'.\n", *opt); fprintf(stderr, "pdfmerge: Unknown option '-%c'.\n", *opt);
return (usage(stderr)); return (usage(stderr));
} }
} }

View File

@ -64,10 +64,9 @@ _pdfioFileAddMappedObj(
pdf->num_objmaps ++; pdf->num_objmaps ++;
map->obj = dst_obj; map->obj = dst_obj;
map->src_pdf = src_obj->pdf;
map->src_number = src_obj->number; map->src_number = src_obj->number;
memcpy(map->src_id, src_obj->pdf->file_id, sizeof(map->src_id));
// Sort as needed... // Sort as needed...
if (pdf->num_objmaps > 1 && compare_objmaps(map, pdf->objmaps + pdf->num_objmaps - 2) < 0) if (pdf->num_objmaps > 1 && compare_objmaps(map, pdf->objmaps + pdf->num_objmaps - 2) < 0)
qsort(pdf->objmaps, pdf->num_objmaps, sizeof(_pdfio_objmap_t), (int (*)(const void *, const void *))compare_objmaps); qsort(pdf->objmaps, pdf->num_objmaps, sizeof(_pdfio_objmap_t), (int (*)(const void *, const void *))compare_objmaps);
@ -686,7 +685,7 @@ _pdfioFileFindMappedObj(
return (NULL); return (NULL);
// Otherwise search for a match... // Otherwise search for a match...
memcpy(key.src_id, src_pdf->file_id, sizeof(key.src_id)); key.src_pdf = src_pdf;
key.src_number = src_number; key.src_number = src_number;
if ((match = (_pdfio_objmap_t *)bsearch(&key, pdf->objmaps, pdf->num_objmaps, sizeof(_pdfio_objmap_t), (int (*)(const void *, const void *))compare_objmaps)) != NULL) if ((match = (_pdfio_objmap_t *)bsearch(&key, pdf->objmaps, pdf->num_objmaps, sizeof(_pdfio_objmap_t), (int (*)(const void *, const void *))compare_objmaps)) != NULL)
@ -1047,10 +1046,6 @@ pdfioFileOpen(
*end; // End of line *end; // End of line
ssize_t bytes; // Bytes read ssize_t bytes; // Bytes read
off_t xref_offset; // Offset to xref table off_t xref_offset; // Offset to xref table
time_t curtime; // Creation date/time
unsigned char *id_value; // ID value
size_t id_valuelen; // Length of ID value
_pdfio_sha256_t ctx; // Hashing context
PDFIO_DEBUG("pdfioFileOpen(filename=\"%s\", password_cb=%p, password_cbdata=%p, error_cb=%p, error_cbdata=%p)\n", filename, (void *)password_cb, (void *)password_cbdata, (void *)error_cb, (void *)error_cbdata); PDFIO_DEBUG("pdfioFileOpen(filename=\"%s\", password_cb=%p, password_cbdata=%p, error_cb=%p, error_cbdata=%p)\n", filename, (void *)password_cb, (void *)password_cbdata, (void *)error_cb, (void *)error_cbdata);
@ -1151,18 +1146,6 @@ pdfioFileOpen(
goto error; goto error;
} }
// Create the unique file identifier string for the object map...
curtime = pdfioFileGetCreationDate(pdf);
_pdfioCryptoSHA256Init(&ctx);
_pdfioCryptoSHA256Append(&ctx, (uint8_t *)pdf->filename, strlen(pdf->filename));
_pdfioCryptoSHA256Append(&ctx, (uint8_t *)&curtime, sizeof(curtime));
if ((id_value = pdfioArrayGetBinary(pdf->id_array, 0, &id_valuelen)) != NULL)
_pdfioCryptoSHA256Append(&ctx, id_value, id_valuelen);
if ((id_value = pdfioArrayGetBinary(pdf->id_array, 1, &id_valuelen)) != NULL)
_pdfioCryptoSHA256Append(&ctx, id_value, id_valuelen);
_pdfioCryptoSHA256Finish(&ctx, pdf->file_id);
return (pdf); return (pdf);
@ -1437,11 +1420,10 @@ static int // O - Result of comparison
compare_objmaps(_pdfio_objmap_t *a, // I - First object map compare_objmaps(_pdfio_objmap_t *a, // I - First object map
_pdfio_objmap_t *b) // I - Second object map _pdfio_objmap_t *b) // I - Second object map
{ {
int ret = memcmp(a->src_id, b->src_id, sizeof(a->src_id)); if (a->src_pdf < b->src_pdf)
// Result of comparison return (-1);
else if (a->src_pdf > b->src_pdf)
if (ret) return (1);
return (ret);
else if (a->src_number < b->src_number) else if (a->src_number < b->src_number)
return (-1); return (-1);
else if (a->src_number > b->src_number) else if (a->src_number > b->src_number)
@ -1470,8 +1452,6 @@ create_common(
pdfio_file_t *pdf; // New PDF file pdfio_file_t *pdf; // New PDF file
pdfio_dict_t *dict; // Dictionary pdfio_dict_t *dict; // Dictionary
unsigned char id_value[16]; // File ID value unsigned char id_value[16]; // File ID value
time_t curtime; // Creation date/time
_pdfio_sha256_t ctx; // Hashing context
PDFIO_DEBUG("create_common(filename=\"%s\", fd=%d, output_cb=%p, output_cbdata=%p, version=\"%s\", media_box=%p, crop_box=%p, error_cb=%p, error_cbdata=%p)\n", filename, fd, (void *)output_cb, (void *)output_cbdata, version, (void *)media_box, (void *)crop_box, (void *)error_cb, (void *)error_cbdata); PDFIO_DEBUG("create_common(filename=\"%s\", fd=%d, output_cb=%p, output_cbdata=%p, version=\"%s\", media_box=%p, crop_box=%p, error_cb=%p, error_cbdata=%p)\n", filename, fd, (void *)output_cb, (void *)output_cbdata, version, (void *)media_box, (void *)crop_box, (void *)error_cb, (void *)error_cbdata);
@ -1562,9 +1542,7 @@ create_common(
if ((dict = pdfioDictCreate(pdf)) == NULL) if ((dict = pdfioDictCreate(pdf)) == NULL)
goto error; goto error;
curtime = time(NULL); pdfioDictSetDate(dict, "CreationDate", time(NULL));
pdfioDictSetDate(dict, "CreationDate", curtime);
pdfioDictSetString(dict, "Producer", "pdfio/" PDFIO_VERSION); pdfioDictSetString(dict, "Producer", "pdfio/" PDFIO_VERSION);
if ((pdf->info_obj = pdfioFileCreateObj(pdf, dict)) == NULL) if ((pdf->info_obj = pdfioFileCreateObj(pdf, dict)) == NULL)
@ -1589,14 +1567,6 @@ create_common(
pdfioArrayAppendBinary(pdf->id_array, id_value, sizeof(id_value)); pdfioArrayAppendBinary(pdf->id_array, id_value, sizeof(id_value));
} }
// Create the unique file identifier string for the object map...
_pdfioCryptoSHA256Init(&ctx);
_pdfioCryptoSHA256Append(&ctx, (uint8_t *)pdf->filename, strlen(pdf->filename));
_pdfioCryptoSHA256Append(&ctx, (uint8_t *)&curtime, sizeof(curtime));
_pdfioCryptoSHA256Append(&ctx, id_value, sizeof(id_value));
_pdfioCryptoSHA256Append(&ctx, id_value, sizeof(id_value));
_pdfioCryptoSHA256Finish(&ctx, pdf->file_id);
return (pdf); return (pdf);
// Common error handling code... // Common error handling code...

View File

@ -79,10 +79,6 @@ pdfioObjCopy(pdfio_file_t *pdf, // I - PDF file
if (srcobj->value.type == PDFIO_VALTYPE_NONE) if (srcobj->value.type == PDFIO_VALTYPE_NONE)
_pdfioObjLoad(srcobj); _pdfioObjLoad(srcobj);
// See if we have already mapped this object...
if ((dstobj = _pdfioFileFindMappedObj(pdf, srcobj->pdf, srcobj->number)) != NULL)
return (dstobj); // Yes, return that one...
// Create the new object... // Create the new object...
if ((dstobj = _pdfioFileCreateObj(pdf, srcobj->pdf, NULL)) == NULL) if ((dstobj = _pdfioFileCreateObj(pdf, srcobj->pdf, NULL)) == NULL)
return (NULL); return (NULL);

View File

@ -221,7 +221,7 @@ struct _pdfio_dict_s // Dictionary
typedef struct _pdfio_objmap_s // PDF object map typedef struct _pdfio_objmap_s // PDF object map
{ {
pdfio_obj_t *obj; // Object for this file pdfio_obj_t *obj; // Object for this file
unsigned char src_id[32]; // Source PDF file file identifier pdfio_file_t *src_pdf; // Source PDF file
size_t src_number; // Source object number size_t src_number; // Source object number
} _pdfio_objmap_t; } _pdfio_objmap_t;
@ -236,7 +236,6 @@ typedef struct _pdfio_strbuf_s // PDF string buffer
struct _pdfio_file_s // PDF file structure struct _pdfio_file_s // PDF file structure
{ {
char *filename; // Filename char *filename; // Filename
unsigned char file_id[32]; // File identifier bytes
struct lconv *loc; // Locale data struct lconv *loc; // Locale data
char *version; // Version number char *version; // Version number
pdfio_rect_t media_box, // Default MediaBox value pdfio_rect_t media_box, // Default MediaBox value

View File

@ -270,7 +270,7 @@ _pdfioStreamCreate(
{ {
columns = 1; columns = 1;
} }
else if (columns < 0 || columns > 65536) else if (columns < 0)
{ {
_pdfioFileError(st->pdf, "Unsupported Columns value %d.", columns); _pdfioFileError(st->pdf, "Unsupported Columns value %d.", columns);
free(st); free(st);
@ -542,7 +542,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
{ {
columns = 1; columns = 1;
} }
else if (columns < 0 || columns > 65536) else if (columns < 0)
{ {
_pdfioFileError(st->pdf, "Unsupported Columns value %d.", columns); _pdfioFileError(st->pdf, "Unsupported Columns value %d.", columns);
goto error; goto error;

View File

@ -18,6 +18,15 @@ if test $# = 0; then
fi fi
for file in $(find "$@" -name \*.pdf -print); do for file in $(find "$@" -name \*.pdf -print); do
# Don't worry about test files containing MIME garbage...
(head -4 $file | grep -q Content-Type) && continue;
# Or test files containing MacBinary garbage...
(file $file | grep -q MacBinary) && continue;
# Don't worry about test files that Xpdf can't handle...
pdfinfo $file >/dev/null 2>&1 || continue;
# Run testpdfio to test loading the file... # Run testpdfio to test loading the file...
./testpdfio $file >$file.log 2>&1 ./testpdfio $file >$file.log 2>&1
if test $? = 0; then if test $? = 0; then