From 43239eaf8acbe3ac93e2c587312da45942dfcd1a Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Mon, 27 Sep 2021 08:37:14 -0400 Subject: [PATCH] Add placeholder password callback to support reading of encrypted PDF files in the future. --- doc/pdfio.3 | 31 +++++++++++++++++++++++-------- doc/pdfio.html | 35 ++++++++++++++++++++++++++--------- pdfio-file.c | 34 +++++++++++++++++++++++----------- pdfio.h | 4 +++- testpdfio.c | 6 +++--- 5 files changed, 78 insertions(+), 32 deletions(-) diff --git a/doc/pdfio.3 b/doc/pdfio.3 index 0c7a40c..af77926 100644 --- a/doc/pdfio.3 +++ b/doc/pdfio.3 @@ -2016,8 +2016,8 @@ CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" siz of 8.27x11in (the intersection of US Letter and ISO A4) is used. .PP The "error_cb" and "error_data" arguments specify an error handler callback -and its data pointer - if not specified the default error handler is used -that writes error messages to \fBstderr\fR. +and its data pointer - if \fBNULL\fR the default error handler is used that +writes error messages to \fBstderr\fR. .SS pdfioFileCreateArrayObj Create a new object in a PDF file containing an array. .PP @@ -2196,8 +2196,8 @@ CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" siz of 8.27x11in (the intersection of US Letter and ISO A4) is used. .PP The "error_cb" and "error_data" arguments specify an error handler callback -and its data pointer - if not specified the default error handler is used -that writes error messages to \fBstderr\fR. +and its data pointer - if \fBNULL\fR the default error handler is used that +writes error messages to \fBstderr\fR. .PP .IP 5 \fINote\fR: Files created using this API are slightly larger than those @@ -2346,16 +2346,25 @@ Open a PDF file for reading. .nf pdfio_file_t * pdfioFileOpen ( const char *filename, + pdfio_password_cb_t password_cb, + void *password_data, pdfio_error_cb_t error_cb, void *error_data ); .fi .PP This function opens an existing PDF file. The "filename" argument specifies -the name of the PDF file to create. The "error_cb" and "error_data" -arguments specify an error handler callback and its data pointer - if not -specified the default error handler is used that writes error messages to -\fBstderr\fR. +the name of the PDF file to create. +.PP +The "password_cb" and "password_data" arguments specify a password callback +and its data pointer for PDF files that use one of the standard Adobe +"security" handlers. The callback returns a password string or \fBNULL\fR to +cancel the open. If \fBNULL\fR is specified for the callback function and the +PDF file requires a password, the open will always fail. +.PP +The "error_cb" and "error_data" arguments specify an error handler callback +and its data pointer - if \fBNULL\fR the default error handler is used that +writes error messages to \fBstderr\fR. .SS pdfioFileSetAuthor Set the author for a PDF file. .PP @@ -2778,6 +2787,12 @@ Output callback for pdfioFileCreateOutput .nf typedef ssize_t(*)(void *ctx const void *data size_t datalen) pdfio_output_cb_t; .fi +.SS pdfio_password_cb_t +Password callback for pdfioFileOpen +.PP +.nf +typedef const char *(*)(void *data const char *filename) pdfio_password_cb_t; +.fi .SS pdfio_rect_t PDF rectangle .PP diff --git a/doc/pdfio.html b/doc/pdfio.html index 10d196e..84a484a 100644 --- a/doc/pdfio.html +++ b/doc/pdfio.html @@ -447,6 +447,7 @@ span.string {
  • pdfio_matrix_t[3][2]
  • pdfio_obj_t
  • pdfio_output_cb_t
  • +
  • pdfio_password_cb_t
  • pdfio_rect_t
  • pdfio_stream_t
  • pdfio_textrendering_t
  • @@ -2464,8 +2465,8 @@ CropBox for pages in the PDF file - if NULL then a default "Un of 8.27x11in (the intersection of US Letter and ISO A4) is used.

    The "error_cb" and "error_data" arguments specify an error handler callback -and its data pointer - if not specified the default error handler is used -that writes error messages to stderr.

    +and its data pointer - if NULL the default error handler is used that +writes error messages to stderr.

    pdfioFileCreateArrayObj

    Create a new object in a PDF file containing an array.

    @@ -2687,8 +2688,8 @@ CropBox for pages in the PDF file - if NULL then a default "Un of 8.27x11in (the intersection of US Letter and ISO A4) is used.

    The "error_cb" and "error_data" arguments specify an error handler callback -and its data pointer - if not specified the default error handler is used -that writes error messages to stderr.
    +and its data pointer - if NULL the default error handler is used that +writes error messages to stderr.

    Note: Files created using this API are slightly larger than those @@ -2884,11 +2885,15 @@ const char *pdfioFileGetVersion(pdfio_file_t *pdf);<

    pdfioFileOpen

    Open a PDF file for reading.

    -pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_error_cb_t error_cb, void *error_data);

    +pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_password_cb_t password_cb, void *password_data, pdfio_error_cb_t error_cb, void *error_data);

    Parameters

    + + + + @@ -2898,10 +2903,17 @@ const char *pdfioFileGetVersion(pdfio_file_t *pdf);<

    PDF file

    Discussion

    This function opens an existing PDF file. The "filename" argument specifies -the name of the PDF file to create. The "error_cb" and "error_data" -arguments specify an error handler callback and its data pointer - if not -specified the default error handler is used that writes error messages to -stderr.

    +the name of the PDF file to create.
    +
    +The "password_cb" and "password_data" arguments specify a password callback +and its data pointer for PDF files that use one of the standard Adobe +"security" handlers. The callback returns a password string or NULL to +cancel the open. If NULL is specified for the callback function and the +PDF file requires a password, the open will always fail.
    +
    +The "error_cb" and "error_data" arguments specify an error handler callback +and its data pointer - if NULL the default error handler is used that +writes error messages to stderr.

    pdfioFileSetAuthor

    Set the author for a PDF file.

    @@ -3425,6 +3437,11 @@ typedef struct _pdfio_obj_s pdfio_obj_t;

    typedef ssize_t (*pdfio_output_cb_t)(void *ctx const void *data size_t datalen);

    +

    pdfio_password_cb_t

    +

    Password callback for pdfioFileOpen

    +

    +typedef const char *(*pdfio_password_cb_t)(void *data const char *filename); +

    pdfio_rect_t

    PDF rectangle

    diff --git a/pdfio-file.c b/pdfio-file.c index 496df89..45aaf8a 100644 --- a/pdfio-file.c +++ b/pdfio-file.c @@ -177,8 +177,8 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file // of 8.27x11in (the intersection of US Letter and ISO A4) is used. // // The "error_cb" and "error_data" arguments specify an error handler callback -// and its data pointer - if not specified the default error handler is used -// that writes error messages to `stderr`. +// and its data pointer - if `NULL` the default error handler is used that +// writes error messages to `stderr`. // pdfio_file_t * // O - PDF file or `NULL` on error @@ -437,8 +437,8 @@ _pdfioFileCreateObj( // of 8.27x11in (the intersection of US Letter and ISO A4) is used. // // The "error_cb" and "error_data" arguments specify an error handler callback -// and its data pointer - if not specified the default error handler is used -// that writes error messages to `stderr`. +// and its data pointer - if `NULL` the default error handler is used that +// writes error messages to `stderr`. // // > *Note*: Files created using this API are slightly larger than those // > created using the @link pdfioFileCreate@ function since stream lengths are @@ -863,17 +863,26 @@ pdfioFileGetVersion( // 'pdfioFileOpen()' - Open a PDF file for reading. // // This function opens an existing PDF file. The "filename" argument specifies -// the name of the PDF file to create. The "error_cb" and "error_data" -// arguments specify an error handler callback and its data pointer - if not -// specified the default error handler is used that writes error messages to -// `stderr`. +// the name of the PDF file to create. +// +// The "password_cb" and "password_data" arguments specify a password callback +// and its data pointer for PDF files that use one of the standard Adobe +// "security" handlers. The callback returns a password string or `NULL` to +// cancel the open. If `NULL` is specified for the callback function and the +// PDF file requires a password, the open will always fail. +// +// The "error_cb" and "error_data" arguments specify an error handler callback +// and its data pointer - if `NULL` the default error handler is used that +// writes error messages to `stderr`. // pdfio_file_t * // O - PDF file pdfioFileOpen( - const char *filename, // I - Filename - pdfio_error_cb_t error_cb, // I - Error callback or `NULL` for default - void *error_data) // I - Error callback data, if any + const char *filename, // I - Filename + pdfio_password_cb_t password_cb, // I - Password callback or `NULL` for none + void *password_data, // I - Password callback data, if any + pdfio_error_cb_t error_cb, // I - Error callback or `NULL` for default + void *error_data) // I - Error callback data, if any { pdfio_file_t *pdf; // PDF file char line[1024], // Line from file @@ -881,6 +890,9 @@ pdfioFileOpen( off_t xref_offset; // Offset to xref table + (void)password_cb; + (void)password_data; + // Range check input... if (!filename) return (NULL); diff --git a/pdfio.h b/pdfio.h index d5de27c..4bf9082 100644 --- a/pdfio.h +++ b/pdfio.h @@ -76,6 +76,8 @@ typedef enum pdfio_filter_e // Compression/decompression filters for streams typedef struct _pdfio_obj_s pdfio_obj_t;// Numbered object in PDF file typedef ssize_t (*pdfio_output_cb_t)(void *ctx, const void *data, size_t datalen); // Output callback for pdfioFileCreateOutput +typedef const char *(*pdfio_password_cb_t)(void *data, const char *filename); + // Password callback for pdfioFileOpen typedef struct pdfio_rect_s // PDF rectangle { double x1; // Lower-left X coordinate @@ -176,7 +178,7 @@ extern const char *pdfioFileGetProducer(pdfio_file_t *pdf) _PDFIO_PUBLIC; extern const char *pdfioFileGetSubject(pdfio_file_t *pdf) _PDFIO_PUBLIC; extern const char *pdfioFileGetTitle(pdfio_file_t *pdf) _PDFIO_PUBLIC; extern const char *pdfioFileGetVersion(pdfio_file_t *pdf) _PDFIO_PUBLIC; -extern pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC; +extern pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_password_cb_t password_cb, void *password_data, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC; extern void pdfioFileSetAuthor(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC; extern void pdfioFileSetCreationDate(pdfio_file_t *pdf, time_t value) _PDFIO_PUBLIC; extern void pdfioFileSetCreator(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC; diff --git a/testpdfio.c b/testpdfio.c index 25494bf..42bbc70 100644 --- a/testpdfio.c +++ b/testpdfio.c @@ -136,7 +136,7 @@ do_test_file(const char *filename, // I - PDF filename fflush(stdout); } - if ((pdf = pdfioFileOpen(filename, (pdfio_error_cb_t)error_cb, &error)) != NULL) + if ((pdf = pdfioFileOpen(filename, /*password_cb*/NULL, /*password_data*/NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) { if (objnum) { @@ -715,7 +715,7 @@ do_unit_tests(void) // First open the test PDF file... fputs("pdfioFileOpen(\"testfiles/testpdfio.pdf\"): ", stdout); - if ((inpdf = pdfioFileOpen("testfiles/testpdfio.pdf", (pdfio_error_cb_t)error_cb, &error)) != NULL) + if ((inpdf = pdfioFileOpen("testfiles/testpdfio.pdf", /*password_cb*/NULL, /*password_data*/NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); @@ -898,7 +898,7 @@ read_unit_file(const char *filename, // I - File to read // Open the new PDF file to read it... printf("pdfioFileOpen(\"%s\", ...): ", filename); - if ((pdf = pdfioFileOpen(filename, (pdfio_error_cb_t)error_cb, &error)) != NULL) + if ((pdf = pdfioFileOpen(filename, /*password_cb*/NULL, /*password_data*/NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1);

    filename Filename
    password_cbPassword callback or NULL for none
    password_dataPassword callback data, if any
    error_cb Error callback or NULL for default
    error_data