Skip to content

Commit 41660d6

Browse files
committed
Initial work on WITH-*-CONTENT, WITH-*-MIME-TYPES, and SAVE-*-CONTENT (Issue #22)
1 parent fa34156 commit 41660d6

2 files changed

Lines changed: 157 additions & 11 deletions

File tree

man/ipptoolfile.5

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,12 @@ Specifies that the current test should be repeated when the \fBEXPECT\fR conditi
332332
\fBSAME\-COUNT\-AS \fIattribute-name\fR
333333
Requires the \fBEXPECT\fR attribute to have the same number of values as the specified parallel attribute.
334334
.TP 5
335+
\fBSAVE\-CONTENT \fIfilespec\fR
336+
.TP 5
337+
\fBSAVE\-ALL\-CONTENT \fIfilespec\fR
338+
Saves all "http" or "https" URI values to the specified location.
339+
The filespec value is a filename or directory path and can contain the special strings "%basename%" to insert the base filename from the URI, "%ext%" to insert the extension from the URI, and "%index%" to insert the value number starting at 1.
340+
.TP 5
335341
\fBWITH\-ALL\-HOSTNAMES "\fIliteral string\fB"\fR
336342
.TP 5
337343
\fBWITH\-ALL\-HOSTNAMES "/\fIregular expression\fB/"\fR
@@ -372,6 +378,22 @@ Comparisons are case-sensitive.
372378
Requires that all value(s) of the \fBEXPECT\fR attribute matches the value(s) in the specified attribute.
373379
For example, "EXPECT-ALL media\-col\-database/media\-source WITH\-ALL\-VALUES\-FROM media\-source\-supported" requires that all the "media\-source" values are listed as a value of the "media\-source\-supported" attribute.
374380
.TP 5
381+
\fBWITH\-CONTENT available\fR
382+
.TP 5
383+
\fBWITH\-ALL\-CONTENT available\fR
384+
Requires that all URI values be accessible.
385+
A "http" or "https" URI must respond to a GET request while a "ipp" or "ipps" URI must respond to a HEAD request.
386+
.TP 5
387+
\fBWITH\-CONTENT valid\fR
388+
.TP 5
389+
\fBWITH\-ALL\-CONTENT valid\fR
390+
Requires that all "http" and "https" URI values be accessible and provide valid content.
391+
.TP 5
392+
\fBWITH\-CONTENT valid-icon\fR
393+
.TP 5
394+
\fBWITH\-ALL\-CONTENT valid-icon\fR
395+
Requires that all "http" and "https" URI values be accessible and provide valid PNG images for icons - 48x48, 128x128, or 512x512 in size with transparency.
396+
.TP 5
375397
\fBWITH\-DISTINCT\-VALUES\fR
376398
Requires that all values of the \fBEXPECT\fR attribute are unique.
377399
Comparisons are case-sensitive.

tools/ipptool.c

Lines changed: 135 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* ipptool command for CUPS.
33
*
4-
* Copyright © 2021-2022 by OpenPrinting.
4+
* Copyright © 2021-2023 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.
@@ -45,12 +45,13 @@
4545
* Types...
4646
*/
4747

48-
typedef enum ipptool_transfer_e /**** How to send request data ****/
48+
typedef enum ipptool_content_e /**** Content Validation ****/
4949
{
50-
IPPTOOL_TRANSFER_AUTO, /* Chunk for files, length for static */
51-
IPPTOOL_TRANSFER_CHUNKED, /* Chunk always */
52-
IPPTOOL_TRANSFER_LENGTH /* Length always */
53-
} ipptool_transfer_t;
50+
IPPTOOL_CONTENT_NONE, /* No content validation */
51+
IPPTOOL_CONTENT_AVAILABLE, /* Accessible resource */
52+
IPPTOOL_CONTENT_VALID, /* Valid resource */
53+
IPPTOOL_CONTENT_VALID_ICON /* Valid icon resource */
54+
} ipptool_content_t;
5455

5556
typedef enum ipptool_output_e /**** Output mode ****/
5657
{
@@ -63,6 +64,13 @@ typedef enum ipptool_output_e /**** Output mode ****/
6364
IPPTOOL_OUTPUT_JSON /* JSON output */
6465
} ipptool_output_t;
6566

67+
typedef enum ipptool_transfer_e /**** How to send request data ****/
68+
{
69+
IPPTOOL_TRANSFER_AUTO, /* Chunk for files, length for static */
70+
IPPTOOL_TRANSFER_CHUNKED, /* Chunk always */
71+
IPPTOOL_TRANSFER_LENGTH /* Length always */
72+
} ipptool_transfer_t;
73+
6674
typedef enum ipptool_with_e /**** WITH flags ****/
6775
{
6876
IPPTOOL_WITH_LITERAL = 0, /* Match string is a literal value */
@@ -89,6 +97,9 @@ typedef struct ipptool_expect_s /**** Expected attribute info ****/
8997
*define_no_match, /* Variable to define on no-match */
9098
*define_value, /* Variable to define with value */
9199
*display_match; /* Message to display on a match */
100+
ipptool_content_t with_content; /* WITH-*-CONTENT value */
101+
cups_array_t *with_mime_types; /* WITH-*-MIME-TYPES value(s) */
102+
char *save_filespec; /* SAVE-*-CONTENT filespec */
92103
int repeat_limit; /* Maximum number of times to repeat */
93104
bool repeat_match, /* Repeat test on match */
94105
repeat_no_match, /* Repeat test on no match */
@@ -246,6 +257,7 @@ static void sigterm_handler(int sig);
246257
static bool timeout_cb(http_t *http, void *user_data);
247258
static bool token_cb(ipp_file_t *f, ipptool_test_t *data, const char *token);
248259
static void usage(void) _CUPS_NORETURN;
260+
static bool with_content(cups_array_t *errors, ipp_attribute_t *attr, ipptool_content_t content, cups_array_t *mime_types, const char *filespec);
249261
static bool with_distinct_values(cups_array_t *errors, ipp_attribute_t *attr);
250262
static const char *with_flags_string(int flags);
251263
static bool with_value(ipptool_test_t *data, cups_array_t *errors, char *value, int flags, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
@@ -848,6 +860,8 @@ clear_data(ipptool_test_t *data) // I - Test data
848860
free(expect->define_no_match);
849861
free(expect->define_value);
850862
free(expect->display_match);
863+
cupsArrayDelete(expect->with_mime_types);
864+
free(expect->save_filespec);
851865
}
852866
data->num_expects = 0;
853867

@@ -1926,12 +1940,22 @@ do_test(ipp_file_t *f, /* I - IPP data file */
19261940

19271941
if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
19281942
repeat_test = true;
1929-
break;
1943+
1944+
continue;
19301945
}
19311946

19321947
if (found)
19331948
ippAttributeString(found, data->buffer, sizeof(data->buffer));
19341949

1950+
if (found && (expect->with_content || expect->with_mime_types || expect->save_filespec) && !with_content(exp_errors, found, expect->with_content, expect->with_mime_types, expect->save_filespec))
1951+
{
1952+
if (expect->define_no_match)
1953+
{
1954+
ippFileSetVar(data->parent, expect->define_no_match, "1");
1955+
exp_pass = true;
1956+
}
1957+
}
1958+
19351959
if (found && expect->with_value_from && !with_value_from(NULL, ippFindAttribute(response, expect->with_value_from, IPP_TAG_ZERO), found, data->buffer, sizeof(data->buffer)))
19361960
{
19371961
if (expect->define_no_match)
@@ -1949,7 +1973,7 @@ do_test(ipp_file_t *f, /* I - IPP data file */
19491973
if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
19501974
repeat_test = true;
19511975

1952-
break;
1976+
continue;
19531977
}
19541978
else if (found && !with_value(data, NULL, expect->with_value, expect->with_flags, found, data->buffer, sizeof(data->buffer)))
19551979
{
@@ -1972,7 +1996,7 @@ do_test(ipp_file_t *f, /* I - IPP data file */
19721996
if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
19731997
repeat_test = true;
19741998

1975-
break;
1999+
continue;
19762000
}
19772001
else if (expect->with_value)
19782002
{
@@ -1994,7 +2018,7 @@ do_test(ipp_file_t *f, /* I - IPP data file */
19942018
if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
19952019
repeat_test = true;
19962020

1997-
break;
2021+
continue;
19982022
}
19992023

20002024
if (found && expect->same_count_as)
@@ -2020,7 +2044,7 @@ do_test(ipp_file_t *f, /* I - IPP data file */
20202044
if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
20212045
repeat_test = true;
20222046

2023-
break;
2047+
continue;
20242048
}
20252049
}
20262050

@@ -5131,13 +5155,19 @@ token_cb(ipp_file_t *f, /* I - IPP file data */
51315155
_cups_strcasecmp(token, "REPEAT-MATCH") &&
51325156
_cups_strcasecmp(token, "REPEAT-NO-MATCH") &&
51335157
_cups_strcasecmp(token, "SAME-COUNT-AS") &&
5158+
_cups_strcasecmp(token, "SAVE-ALL-CONTENT") &&
5159+
_cups_strcasecmp(token, "SAVE-CONTENT") &&
5160+
_cups_strcasecmp(token, "WITH-ALL-CONTENT") &&
5161+
_cups_strcasecmp(token, "WITH-ALL-MIME-TYPES") &&
51345162
_cups_strcasecmp(token, "WITH-ALL-VALUES") &&
51355163
_cups_strcasecmp(token, "WITH-ALL-VALUES-FROM") &&
51365164
_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") &&
51375165
_cups_strcasecmp(token, "WITH-ALL-RESOURCES") &&
51385166
_cups_strcasecmp(token, "WITH-ALL-SCHEMES") &&
5167+
_cups_strcasecmp(token, "WITH-CONTENT") &&
51395168
_cups_strcasecmp(token, "WITH-DISTINCT-VALUES") &&
51405169
_cups_strcasecmp(token, "WITH-HOSTNAME") &&
5170+
_cups_strcasecmp(token, "WITH-MIME-TYPES") &&
51415171
_cups_strcasecmp(token, "WITH-RESOURCE") &&
51425172
_cups_strcasecmp(token, "WITH-SCHEME") &&
51435173
_cups_strcasecmp(token, "WITH-VALUE") &&
@@ -5906,6 +5936,24 @@ token_cb(ipp_file_t *f, /* I - IPP file data */
59065936
return (false);
59075937
}
59085938
}
5939+
else if (!_cups_strcasecmp(token, "SAVE-ALL-CONTENT") || !_cups_strcasecmp(token, "SAVE-CONTENT"))
5940+
{
5941+
if (!ippFileReadToken(f, temp, sizeof(temp)))
5942+
{
5943+
print_fatal_error(data, "Missing %s filespec on line %d of '%s'.", token, ippFileGetLineNumber(f), ippFileGetFilename(f));
5944+
return (false);
5945+
}
5946+
5947+
if (data->last_expect)
5948+
{
5949+
data->last_expect->save_filespec = strdup(temp);
5950+
}
5951+
else
5952+
{
5953+
print_fatal_error(data, "%s without a preceding EXPECT on line %d of '%s'.", token, ippFileGetLineNumber(f), ippFileGetFilename(f));
5954+
return (false);
5955+
}
5956+
}
59095957
else if (!_cups_strcasecmp(token, "IF-DEFINED"))
59105958
{
59115959
if (!ippFileReadToken(f, temp, sizeof(temp)))
@@ -5950,6 +5998,58 @@ token_cb(ipp_file_t *f, /* I - IPP file data */
59505998
return (false);
59515999
}
59526000
}
6001+
else if (!_cups_strcasecmp(token, "WITH-ALL-CONTENT") || !_cups_strcasecmp(token, "WITH-CONTENT"))
6002+
{
6003+
if (!ippFileReadToken(f, temp, sizeof(temp)))
6004+
{
6005+
print_fatal_error(data, "Missing %s condition on line %d of '%s'.", token, ippFileGetLineNumber(f), ippFileGetFilename(f));
6006+
return (false);
6007+
}
6008+
6009+
if (data->last_expect)
6010+
{
6011+
if (!_cups_strcasecmp(temp, "available"))
6012+
{
6013+
data->last_expect->with_content = IPPTOOL_CONTENT_AVAILABLE;
6014+
}
6015+
else if (!_cups_strcasecmp(temp, "valid"))
6016+
{
6017+
data->last_expect->with_content = IPPTOOL_CONTENT_VALID;
6018+
}
6019+
else if (!_cups_strcasecmp(temp, "valid-icon"))
6020+
{
6021+
data->last_expect->with_content = IPPTOOL_CONTENT_VALID_ICON;
6022+
}
6023+
else
6024+
{
6025+
print_fatal_error(data, "Unsupported %s %s on line %d of '%s'.", token, temp, ippFileGetLineNumber(f), ippFileGetFilename(f));
6026+
return (false);
6027+
}
6028+
}
6029+
else
6030+
{
6031+
print_fatal_error(data, "%s without a preceding EXPECT on line %d of '%s'.", token, ippFileGetLineNumber(f), ippFileGetFilename(f));
6032+
return (false);
6033+
}
6034+
}
6035+
else if (!_cups_strcasecmp(token, "WITH-ALL-MIME-TYPES") || !_cups_strcasecmp(token, "WITH-MIME-TYPES"))
6036+
{
6037+
if (!ippFileReadToken(f, temp, sizeof(temp)))
6038+
{
6039+
print_fatal_error(data, "Missing %s MIME media type(s) on line %d of '%s'.", token, ippFileGetLineNumber(f), ippFileGetFilename(f));
6040+
return (false);
6041+
}
6042+
6043+
if (data->last_expect)
6044+
{
6045+
data->last_expect->with_mime_types = cupsArrayNewStrings(temp, ',');
6046+
}
6047+
else
6048+
{
6049+
print_fatal_error(data, "%s without a preceding EXPECT on line %d of '%s'.", token, ippFileGetLineNumber(f), ippFileGetFilename(f));
6050+
return (false);
6051+
}
6052+
}
59536053
else if (!_cups_strcasecmp(token, "WITH-DISTINCT-VALUES"))
59546054
{
59556055
if (data->last_expect)
@@ -6566,6 +6666,30 @@ usage(void)
65666666
}
65676667

65686668

6669+
/*
6670+
* 'with_content()' - Verify that URIs meet content/MIME media type requirements
6671+
* and save as needed.
6672+
*/
6673+
6674+
static bool // O - `true` if valid, `false` otherwise
6675+
with_content(
6676+
cups_array_t *errors, // I - Array of errors
6677+
ipp_attribute_t *attr, // I - Attribute
6678+
ipptool_content_t content, // I - Content validation rule
6679+
cups_array_t *mime_types, // I - Comma-delimited list of MIME media types
6680+
const char *filespec) // I - Output filename specification
6681+
{
6682+
// TODO: Implement me
6683+
(void)errors;
6684+
(void)attr;
6685+
(void)content;
6686+
(void)mime_types;
6687+
(void)filespec;
6688+
6689+
return (true);
6690+
}
6691+
6692+
65696693
/*
65706694
* 'with_distinct_values()' - Verify that an attribute contains unique values.
65716695
*/

0 commit comments

Comments
 (0)