11//
22// ipptool command for CUPS.
33//
4- // Copyright © 2021-2023 by OpenPrinting.
4+ // Copyright © 2021-2024 by OpenPrinting.
55// Copyright © 2020 by The Printer Working Group.
66// Copyright © 2007-2021 by Apple Inc.
77// Copyright © 1997-2007 by Easy Software Products.
2626#ifndef O_BINARY
2727# define O_BINARY 0
2828#endif // !O_BINARY
29+ #include <pdfio.h>
2930
3031
3132//
@@ -238,6 +239,7 @@ static bool parse_generate_file(ipp_file_t *f, ipptool_test_t *data);
238239static bool parse_monitor_printer_state (ipp_file_t * f , ipptool_test_t * data );
239240static const char * password_cb (const char * prompt , http_t * http , const char * method , const char * resource , void * user_data );
240241static void pause_message (const char * message );
242+ static bool pdf_error_cb (pdfio_file_t * pdf , const char * message , cups_array_t * errors );
241243static void print_attr (cups_file_t * outfile , ipptool_output_t output , ipp_attribute_t * attr , ipp_tag_t * group );
242244static ipp_attribute_t * print_csv (ipptool_test_t * data , ipp_t * ipp , ipp_attribute_t * attr , int num_displayed , char * * displayed , size_t * widths );
243245static void print_fatal_error (ipptool_test_t * data , const char * s , ...) _CUPS_FORMAT (2 , 3 );
@@ -4121,6 +4123,23 @@ pause_message(const char *message) // I - Message
41214123}
41224124
41234125
4126+ //
4127+ // 'pdf_error_cb()' - PDFio error callback.
4128+ //
4129+
4130+ static bool // O - `false` to stop loading
4131+ pdf_error_cb (pdfio_file_t * pdf , // I - PDF file
4132+ const char * message , // I - Error message
4133+ cups_array_t * errors ) // I - Array of error messages
4134+ {
4135+ (void )pdf ;
4136+
4137+ add_stringf (errors , "Unable to open PDF file: %s" , message );
4138+
4139+ return (false);
4140+ }
4141+
4142+
41244143//
41254144// 'print_attr()' - Print an attribute on the screen.
41264145//
@@ -6700,7 +6719,8 @@ with_content(
67006719 char scheme [256 ], // Scheme
67016720 userpass [256 ], // Username:password (not used)
67026721 host [256 ], // Hostname
6703- resource [256 ]; // Resource path
6722+ resource [256 ], // Resource path
6723+ * resptr ; // Pointer into resource
67046724 int port ; // Port number
67056725 http_encryption_t encryption ; // Encryption mode
67066726 http_uri_status_t uri_status ; // URI decoding status
@@ -6720,6 +6740,9 @@ with_content(
67206740 continue ;
67216741 }
67226742
6743+ if ((resptr = strchr (resource , '#' )) != NULL )
6744+ * resptr = '\0' ; // Strip HTML target ("...#target")
6745+
67236746 if (strcmp (scheme , "http" ) && strcmp (scheme , "https" ) && strcmp (scheme , "ipp" ) && strcmp (scheme , "ipps" ))
67246747 {
67256748 add_stringf (errors , "Unsupported URI scheme for '%s'." , uri );
@@ -6789,7 +6812,7 @@ with_content(
67896812
67906813 if (status != HTTP_STATUS_OK )
67916814 {
6792- add_stringf (errors , "Got unexpected status %d for HEAD request to '%s'." , (int )status , uri );
6815+ add_stringf (errors , "Got unexpected status %d for GET request to '%s'." , (int )status , uri );
67936816 ret = false;
67946817 goto get_done ;
67956818 }
@@ -6833,14 +6856,70 @@ with_content(
68336856 }
68346857 else if (!_cups_strcasecmp (content_type , "image/jpeg" ) || !_cups_strcasecmp (content_type , "image/png" ))
68356858 {
6859+ // Validate image content
68366860 if (!valid_image (filename , & width , & height , & depth ))
68376861 {
6838- add_stringf (errors , "Unable to load image '%s'." , uri );
6862+ add_stringf (errors , "Unable to open image '%s'." , uri );
68396863 ret = false;
68406864 goto get_done ;
68416865 }
68426866 }
6843- else if (!_cups_strcasecmp (content_type , "application/pdf" ) || !_cups_strcasecmp (content_type , "application/ipp" ) || !_cups_strcasecmp (content_type , "application/vnd.iccprofile" ) || !_cups_strcasecmp (content_type , "text/css" ) || !_cups_strcasecmp (content_type , "text/html" ) || !_cups_strcasecmp (content_type , "text/strings" ))
6867+ else if (!_cups_strcasecmp (content_type , "text/strings" ))
6868+ {
6869+ // Validate .strings content...
6870+ cups_lang_t * lang ; // Temporary language
6871+
6872+ if ((lang = cupsLangFind ("zz" )) == NULL )
6873+ {
6874+ add_stringf (errors , "Unable to validate '%s'." , uri );
6875+ ret = false;
6876+ goto get_done ;
6877+ }
6878+
6879+ if (!cupsLangLoadStrings (lang , filename , /*strings*/ NULL ))
6880+ {
6881+ add_stringf (errors , "Unable to open '%s': %s" , uri , cupsGetErrorString ());
6882+ ret = false;
6883+ goto get_done ;
6884+ }
6885+ }
6886+ else if (!_cups_strcasecmp (content_type , "application/pdf" ))
6887+ {
6888+ // Validate PDF content...
6889+ pdfio_file_t * pdf ; // PDF file
6890+
6891+ if ((pdf = pdfioFileOpen (filename , /*password_cb*/ NULL , /*password_data*/ NULL , (pdfio_error_cb_t )pdf_error_cb , errors )) == NULL )
6892+ {
6893+ ret = false;
6894+ goto get_done ;
6895+ }
6896+
6897+ pdfioFileClose (pdf );
6898+ }
6899+ else if (!_cups_strcasecmp (content_type , "application/ipp" ))
6900+ {
6901+ ipp_t * ipp = ippNew (); // IPP message
6902+
6903+ if ((fd = open (filename , O_RDONLY | O_BINARY )) < 0 )
6904+ {
6905+ add_stringf (errors , "Unable to open '%s': %s" , uri , strerror (errno ));
6906+ ippDelete (ipp );
6907+ ret = false;
6908+ goto get_done ;
6909+ }
6910+ else if (ippReadFile (fd , ipp ) != IPP_STATE_DATA )
6911+ {
6912+ add_stringf (errors , "Unable to read '%s': %s" , uri , cupsGetErrorString ());
6913+ ippDelete (ipp );
6914+ close (fd );
6915+ ret = false;
6916+ goto get_done ;
6917+ }
6918+
6919+ ippDelete (ipp );
6920+ close (fd );
6921+ }
6922+ else if (!_cups_strcasecmp (content_type , "application/vnd.iccprofile" ) || !_cups_strcasecmp (content_type , "text/css" ) || !_cups_strcasecmp (content_type , "text/html" ) || !_cups_strncasecmp (content_type , "text/html;" , 10 ))
68446923 {
68456924 // Just require these files to be non-empty for now, might add more checks in the future...
68466925 if (fileinfo .st_size == 0 )
@@ -6852,7 +6931,7 @@ with_content(
68526931 }
68536932 else
68546933 {
6855- add_stringf (errors , "Got unexpected Content-Type '%s' for HEAD request to '%s'." , content_type , uri );
6934+ add_stringf (errors , "Got unexpected Content-Type '%s' for GET request to '%s'." , content_type , uri );
68566935 ret = false;
68576936 goto get_done ;
68586937 }
0 commit comments