Skip to content

Commit 9362942

Browse files
committed
Enhance WITH-[ALL-]CONTENT support to validate IPP, PDF, and .strings files (Issue #87)
Strip HTML target ("...#target") from URIs when doing validation. Update man pages. Add resource validation test file.
1 parent 15e3e29 commit 9362942

8 files changed

Lines changed: 145 additions & 16 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ libcups v3.0rc1 (TBD)
2121
- Updated the various tool man pages, usage output, and examples.
2222
- Updated `ippCreateRequestedArray` for the Get-Documents and
2323
Get-Output-Device-Attributes operations.
24+
- Updated `ipptool` to validate IPP, PDF, and .strings files using the
25+
"WITH-[ALL-]CONTENT" predicate (Issue #87)
2426
- Now use installed PDFio library, if available.
2527
- Now use NotoSansMono font for `ipptransform` text conversions.
2628
- Brought back IPP/2.x and related conformance test files (Issue #85)

examples/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ TESTFILES = \
8585
rfc3995-3996.test \
8686
rfc3998.test \
8787
set-attrs-hold.test \
88-
validate-job.test
88+
validate-job.test \
89+
validate-resources.test
8990

9091

9192
#

examples/validate-resources.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Validate printer resources
2+
{
3+
NAME "Validate Printer Resources"
4+
OPERATION Get-Printer-Attributes
5+
GROUP operation-attributes-tag
6+
ATTR charset attributes-charset utf-8
7+
ATTR language attributes-natural-language en
8+
ATTR uri printer-uri $uri
9+
ATTR name requesting-user-name $user
10+
11+
STATUS successful-ok
12+
13+
EXPECT ?printer-charge-info-uri OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1 WITH-CONTENT valid
14+
15+
EXPECT printer-icc-profiles OF-TYPE collection IN-GROUP printer-attributes-tag DEFINE-MATCH PRINTER_HAS_ICC_PROFILES
16+
EXPECT printer-icc-profiles/profile-uri OF-TYPE uri COUNT 1 WITH-CONTENT valid IF-DEFINED PRINTER_HAS_ICC_PROFILES
17+
18+
EXPECT ?printer-icons OF-TYPE uri IN-GROUP printer-attributes-tag WITH-ALL-CONTENT valid-icon
19+
20+
EXPECT ?printer-more-info OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1 WITH-CONTENT valid
21+
22+
EXPECT ?printer-more-info-manufacturer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1 WITH-CONTENT valid
23+
24+
EXPECT ?printer-privacy-policy-uri OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1 WITH-CONTENT valid
25+
26+
EXPECT ?printer-static-resource-directory-uri OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1 WITH-CONTENT valid
27+
28+
EXPECT ?printer-strings-uri OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1 WITH-CONTENT valid
29+
}

man/ipptool.1

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
.\"
22
.\" ipptool man page.
33
.\"
4-
.\" Copyright © 2021-2023 by OpenPrinting.
4+
.\" Copyright © 2021-2024 by OpenPrinting.
55
.\" Copyright © 2010-2019 by Apple Inc.
66
.\"
77
.\" Licensed under Apache License v2.0. See the file "LICENSE" for more
88
.\" information.
99
.\"
10-
.TH ipptool 1 "CUPS" "2023-11-22" "OpenPrinting"
10+
.TH ipptool 1 "CUPS" "2024-09-12" "OpenPrinting"
1111
.SH NAME
1212
ipptool \- perform internet printing protocol requests
1313
.SH SYNOPSIS
@@ -227,6 +227,8 @@ The following standard test files are available:
227227
identify\-printer\-display.test - Identify a printer via the display
228228
ipp\-1.1.test - Run IPP/1.1 conformance tests
229229
ipp\-2.0.test - Run IPP/2.0 conformance tests
230+
ipp\-2.1.test - Run IPP/2.1 conformance tests
231+
ipp\-2.2.test - Run IPP/2.2 conformance tests
230232
print\-job.test - Print a file
231233
print\-job\-and\-wait.test - Print a file and wait for completion
232234
print\-job\-deflate.test - Print a file with deflate compression
@@ -239,8 +241,21 @@ The following standard test files are available:
239241
print\-job\-password.test - Print a file with a password/PIN
240242
print\-job\-raster.test - Print a generated raster file
241243
print\-uri.test - Print a URI/URL
244+
pwg5100.1.test - Test PWG 5100.1 (Finishings) conformance
245+
pwg5100.2.test - Test PWG 5100.2 (output-bin) conformance
246+
pwg5100.3.test - Test PWG 5100.3 (Production) conformance
247+
pwg5100.5.test - Test PWG 5100.5 (Document Object) conformance
248+
pwg5100.6.test - Test PWG 5100.6 (Page Overrides) conformance
249+
pwg5100.7.test - Test PWG 5100.7 (Job Extensions) conformance
250+
pwg5100.8.test - Test PWG 5100.8 (-actuals) conformance
251+
pwg5100.9.test - Test PWG 5100.9 (Alerts) conformance
252+
pwg5100.11.test - Test PWG 5100.11 (Enterprise) conformance
253+
rfc3380.test - Test RFC 3380 (Job and Printer Set) conformance
254+
rfc3995-3996.test - Test RFC 3995/3996 (Notifications) conformance
255+
rfc3998.test - Test RFC 3998 (Admin) conformance
242256
set\-attrs\-hold.test - Test setting job-hold-until to hold a job
243257
validate\-job.test - Validate a job ticket
258+
validate\-resources.test - Validate printer resource files and web pages
244259
.fi
245260
.PP
246261
The following standard document files are available:
@@ -287,4 +302,4 @@ IANA IPP Registry (https://www.iana.org/assignments/ipp\-registrations),
287302
PWG Internet Printing Protocol Workgroup (https://www.pwg.org/ipp),
288303
RFC 8011 (https://datatracker.ietf.org/doc/html/rfc8011)
289304
.SH COPYRIGHT
290-
Copyright \[co] 2021-2023 by OpenPrinting.
305+
Copyright \[co] 2021-2024 by OpenPrinting.

man/ipptoolfile.5

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
.\"
22
.\" ipptoolfile man page.
33
.\"
4-
.\" Copyright © 2021-2023 by OpenPrinting.
4+
.\" Copyright © 2021-2024 by OpenPrinting.
55
.\" Copyright © 2010-2021 by Apple Inc.
66
.\"
77
.\" Licensed under Apache License v2.0. See the file "LICENSE" for more
88
.\" information.
99
.\"
10-
.TH ipptoolfile 5 "CUPS" "2023-11-17" "OpenPrinting"
10+
.TH ipptoolfile 5 "CUPS" "2024-09-12" "OpenPrinting"
1111
.SH NAME
1212
ipptoolfile \- ipptool file format
1313
.SH DESCRIPTION
@@ -352,6 +352,9 @@ A "http" or "https" URI must respond to a GET request while a "ipp" or "ipps" UR
352352
.TP 5
353353
\fBWITH\-CONTENT valid\fR
354354
Requires that all "http" and "https" URI values be accessible and provide valid content.
355+
Currently
356+
.B ipptool
357+
is able to validate CSS, HTML, ICC, IPP, JPEG, PDF, PNG, and Apple .strings files.
355358
.TP 5
356359
\fBWITH\-ALL\-CONTENT valid-icon\fR
357360
.TP 5
@@ -886,4 +889,4 @@ PWG 5101.1-2023: PWG Media Standardized Names v2.1 (https://ftp.pwg.org/pub/pwg/
886889
.PP
887890
RFC 8011 (https://datatracker.ietf.org/doc/html/rfc8011)
888891
.SH COPYRIGHT
889-
Copyright \[co] 2021-2023 by OpenPrinting.
892+
Copyright \[co] 2021-2024 by OpenPrinting.

tools/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ ippfind-static: ippfind.o ../cups/$(LIBCUPS_STATIC)
172172

173173
ipptool: ipptool.o ../cups/$(LIBCUPS) ipptool-static
174174
echo Linking $@...
175-
$(CC) $(LDFLAGS) $(OPTIM) -o $@ ipptool.o $(LINKCUPS) $(LIBS)
175+
$(CC) $(LDFLAGS) $(OPTIM) -o $@ ipptool.o $(LINKCUPS) $(XFORMLIBS) $(LIBS)
176176
$(CODE_SIGN) $(CSFLAGS) $@
177177

178178

@@ -182,7 +182,7 @@ ipptool: ipptool.o ../cups/$(LIBCUPS) ipptool-static
182182

183183
ipptool-static: ipptool.o ../cups/$(LIBCUPS_STATIC)
184184
echo Linking $@...
185-
$(CC) $(LDFLAGS) $(OPTIM) -o $@ ipptool.o ../cups/$(LIBCUPS_STATIC) $(LIBS)
185+
$(CC) $(LDFLAGS) $(OPTIM) -o $@ ipptool.o ../cups/$(LIBCUPS_STATIC) $(XFORMLIBS) $(LIBS)
186186
$(CODE_SIGN) $(CSFLAGS) $@
187187

188188

tools/ipptool.c

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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.
@@ -26,6 +26,7 @@
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);
238239
static bool parse_monitor_printer_state(ipp_file_t *f, ipptool_test_t *data);
239240
static const char *password_cb(const char *prompt, http_t *http, const char *method, const char *resource, void *user_data);
240241
static void pause_message(const char *message);
242+
static bool pdf_error_cb(pdfio_file_t *pdf, const char *message, cups_array_t *errors);
241243
static void print_attr(cups_file_t *outfile, ipptool_output_t output, ipp_attribute_t *attr, ipp_tag_t *group);
242244
static ipp_attribute_t *print_csv(ipptool_test_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
243245
static 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

Comments
 (0)