summaryrefslogtreecommitdiff
path: root/tools/ipptool.c
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>2021-04-05 15:57:50 -0400
committerMichael R Sweet <michael.r.sweet@gmail.com>2021-04-05 15:57:50 -0400
commit064e50fb06e83e6c1756e2a81c2fcbd4d6fca8e6 (patch)
tree45145c8db9a634af861cb1ed87a7378837e72763 /tools/ipptool.c
parent6918883fba4942931dc455b32545d6edf18dec5c (diff)
downloadcups-064e50fb06e83e6c1756e2a81c2fcbd4d6fca8e6.tar.gz
Import all of the bug fixes from the OpenPrinting CUPS repository.
Import the improvements to ippeveprinter from OpenPrinting/ippsample. Import the improvements to ippfind and ipptool from OpenPrinting/ippsample.
Diffstat (limited to 'tools/ipptool.c')
-rw-r--r--tools/ipptool.c1611
1 files changed, 1311 insertions, 300 deletions
diff --git a/tools/ipptool.c b/tools/ipptool.c
index a3a694d5f..0ebc016c0 100644
--- a/tools/ipptool.c
+++ b/tools/ipptool.c
@@ -1,7 +1,9 @@
/*
* ipptool command for CUPS.
*
- * Copyright © 2007-2019 by Apple Inc.
+ * Copyright © 2021 by OpenPrinting.
+ * Copyright © 2020 by The Printer Working Group.
+ * Copyright © 2007-2021 by Apple Inc.
* Copyright © 1997-2007 by Easy Software Products.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
@@ -33,34 +35,34 @@
* Types...
*/
-typedef enum _cups_transfer_e /**** How to send request data ****/
+typedef enum ipptool_transfer_e /**** How to send request data ****/
{
- _CUPS_TRANSFER_AUTO, /* Chunk for files, length for static */
- _CUPS_TRANSFER_CHUNKED, /* Chunk always */
- _CUPS_TRANSFER_LENGTH /* Length always */
-} _cups_transfer_t;
+ IPPTOOL_TRANSFER_AUTO, /* Chunk for files, length for static */
+ IPPTOOL_TRANSFER_CHUNKED, /* Chunk always */
+ IPPTOOL_TRANSFER_LENGTH /* Length always */
+} ipptool_transfer_t;
-typedef enum _cups_output_e /**** Output mode ****/
+typedef enum ipptool_output_e /**** Output mode ****/
{
- _CUPS_OUTPUT_QUIET, /* No output */
- _CUPS_OUTPUT_TEST, /* Traditional CUPS test output */
- _CUPS_OUTPUT_PLIST, /* XML plist test output */
- _CUPS_OUTPUT_IPPSERVER, /* ippserver attribute file output */
- _CUPS_OUTPUT_LIST, /* Tabular list output */
- _CUPS_OUTPUT_CSV /* Comma-separated values output */
-} _cups_output_t;
-
-typedef enum _cups_with_e /**** WITH flags ****/
+ IPPTOOL_OUTPUT_QUIET, /* No output */
+ IPPTOOL_OUTPUT_TEST, /* Traditional CUPS test output */
+ IPPTOOL_OUTPUT_PLIST, /* XML plist test output */
+ IPPTOOL_OUTPUT_IPPSERVER, /* ippserver attribute file output */
+ IPPTOOL_OUTPUT_LIST, /* Tabular list output */
+ IPPTOOL_OUTPUT_CSV /* Comma-separated values output */
+} ipptool_output_t;
+
+typedef enum ipptool_with_e /**** WITH flags ****/
{
- _CUPS_WITH_LITERAL = 0, /* Match string is a literal value */
- _CUPS_WITH_ALL = 1, /* Must match all values */
- _CUPS_WITH_REGEX = 2, /* Match string is a regular expression */
- _CUPS_WITH_HOSTNAME = 4, /* Match string is a URI hostname */
- _CUPS_WITH_RESOURCE = 8, /* Match string is a URI resource */
- _CUPS_WITH_SCHEME = 16 /* Match string is a URI scheme */
-} _cups_with_t;
-
-typedef struct _cups_expect_s /**** Expected attribute info ****/
+ IPPTOOL_WITH_LITERAL = 0, /* Match string is a literal value */
+ IPPTOOL_WITH_ALL = 1, /* Must match all values */
+ IPPTOOL_WITH_REGEX = 2, /* Match string is a regular expression */
+ IPPTOOL_WITH_HOSTNAME = 4, /* Match string is a URI hostname */
+ IPPTOOL_WITH_RESOURCE = 8, /* Match string is a URI resource */
+ IPPTOOL_WITH_SCHEME = 16 /* Match string is a URI scheme */
+} ipptool_with_t;
+
+typedef struct ipptool_expect_s /**** Expected attribute info ****/
{
int optional, /* Optional attribute? */
not_expect, /* Don't expect attribute? */
@@ -78,12 +80,13 @@ typedef struct _cups_expect_s /**** Expected attribute info ****/
int repeat_limit, /* Maximum number of times to repeat */
repeat_match, /* Repeat test on match */
repeat_no_match, /* Repeat test on no match */
- with_flags, /* WITH flags */
+ with_distinct, /* WITH-DISTINCT-VALUES? */
+ with_flags, /* WITH flags */
count; /* Expected count if > 0 */
ipp_tag_t in_group; /* IN-GROUP value */
-} _cups_expect_t;
+} ipptool_expect_t;
-typedef struct _cups_status_s /**** Status info ****/
+typedef struct ipptool_status_s /**** Status info ****/
{
ipp_status_t status; /* Expected status code */
char *if_defined, /* Only if variable is defined */
@@ -94,14 +97,16 @@ typedef struct _cups_status_s /**** Status info ****/
int repeat_limit, /* Maximum number of times to repeat */
repeat_match, /* Repeat the test when it does not match */
repeat_no_match; /* Repeat the test when it matches */
-} _cups_status_t;
+} ipptool_status_t;
-typedef struct _cups_testdata_s /**** Test Data ****/
+typedef struct ipptool_test_s /**** Test Data ****/
{
/* Global Options */
+ _ipp_vars_t *vars; /* Variables */
http_encryption_t encryption; /* Encryption for connection */
int family; /* Address family */
- _cups_output_t output; /* Output mode */
+ ipptool_output_t output; /* Output mode */
+ int repeat_on_busy; /* Repeat tests on server-error-busy */
int stop_after_include_error;
/* Stop after include errors? */
double timeout; /* Timeout for connection */
@@ -110,7 +115,7 @@ typedef struct _cups_testdata_s /**** Test Data ****/
/* Test Defaults */
int def_ignore_errors; /* Default IGNORE-ERRORS value */
- _cups_transfer_t def_transfer; /* Default TRANSFER value */
+ ipptool_transfer_t def_transfer; /* Default TRANSFER value */
int def_version; /* Default IPP version */
/* Global State */
@@ -133,24 +138,32 @@ typedef struct _cups_testdata_s /**** Test Data ****/
int num_displayed; /* Number of displayed attributes */
char *displayed[200]; /* Displayed attributes */
int num_expects; /* Number of expected attributes */
- _cups_expect_t expects[200], /* Expected attributes */
+ ipptool_expect_t expects[200], /* Expected attributes */
*expect, /* Current expected attribute */
*last_expect; /* Last EXPECT (for predicates) */
char file[1024], /* Data filename */
file_id[1024]; /* File identifier */
int ignore_errors; /* Ignore test failures? */
char name[1024]; /* Test name */
+ char pause[1024]; /* PAUSE value */
useconds_t repeat_interval; /* Repeat interval (delay) */
int request_id; /* Current request ID */
char resource[512]; /* Resource for request */
int skip_test, /* Skip this test? */
num_statuses; /* Number of valid status codes */
- _cups_status_t statuses[100], /* Valid status codes */
+ ipptool_status_t statuses[100], /* Valid status codes */
*last_status; /* Last STATUS (for predicates) */
char test_id[1024]; /* Test identifier */
- _cups_transfer_t transfer; /* To chunk or not to chunk */
+ ipptool_transfer_t transfer; /* To chunk or not to chunk */
int version; /* IPP version number to use */
-} _cups_testdata_t;
+ _cups_thread_t monitor_thread; /* Monitoring thread ID */
+ int monitor_done; /* Set to 1 to stop monitor thread */
+ char *monitor_uri; /* MONITOR-PRINTER-STATE URI */
+ useconds_t monitor_delay, /* MONITOR-PRINTER-STATE DELAY value, if any */
+ monitor_interval; /* MONITOR-PRINTER-STATE DELAY interval */
+ int num_monitor_expects; /* Number MONITOR-PRINTER-STATE EXPECTs */
+ ipptool_expect_t monitor_expects[10]; /* MONITOR-PRINTER-STATE EXPECTs */
+} ipptool_test_t;
/*
@@ -167,32 +180,35 @@ static int Cancel = 0; /* Cancel test? */
static void add_stringf(cups_array_t *a, const char *s, ...) _CUPS_FORMAT(2, 3);
static int compare_uris(const char *a, const char *b);
static void copy_hex_string(char *buffer, unsigned char *data, int datalen, size_t bufsize);
-static int do_test(_ipp_file_t *f, _ipp_vars_t *vars, _cups_testdata_t *data);
-static int do_tests(const char *testfile, _ipp_vars_t *vars, _cups_testdata_t *data);
-static int error_cb(_ipp_file_t *f, _cups_testdata_t *data, const char *error);
-static int expect_matches(_cups_expect_t *expect, ipp_tag_t value_tag);
+static void *do_monitor_printer_state(ipptool_test_t *data);
+static int do_test(_ipp_file_t *f, ipptool_test_t *data);
+static int do_tests(const char *testfile, ipptool_test_t *data);
+static int error_cb(_ipp_file_t *f, ipptool_test_t *data, const char *error);
+static int expect_matches(ipptool_expect_t *expect, ipp_attribute_t *attr);
static char *get_filename(const char *testfile, char *dst, const char *src, size_t dstsize);
static const char *get_string(ipp_attribute_t *attr, int element, int flags, char *buffer, size_t bufsize);
-static void init_data(_cups_testdata_t *data);
+static void init_data(ipptool_test_t *data);
static char *iso_date(const ipp_uchar_t *date);
+static int parse_monitor_printer_state(_ipp_file_t *f, ipptool_test_t *data);
static void pause_message(const char *message);
-static void print_attr(cups_file_t *outfile, _cups_output_t output, ipp_attribute_t *attr, ipp_tag_t *group);
-static void print_csv(_cups_testdata_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
-static void print_fatal_error(_cups_testdata_t *data, const char *s, ...) _CUPS_FORMAT(2, 3);
-static void print_ippserver_attr(_cups_testdata_t *data, ipp_attribute_t *attr, int indent);
-static void print_ippserver_string(_cups_testdata_t *data, const char *s, size_t len);
-static void print_line(_cups_testdata_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
-static void print_xml_header(_cups_testdata_t *data);
+static void print_attr(cups_file_t *outfile, ipptool_output_t output, ipp_attribute_t *attr, ipp_tag_t *group);
+static void print_csv(ipptool_test_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
+static void print_fatal_error(ipptool_test_t *data, const char *s, ...) _CUPS_FORMAT(2, 3);
+static void print_ippserver_attr(ipptool_test_t *data, ipp_attribute_t *attr, int indent);
+static void print_ippserver_string(ipptool_test_t *data, const char *s, size_t len);
+static void print_line(ipptool_test_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
+static void print_xml_header(ipptool_test_t *data);
static void print_xml_string(cups_file_t *outfile, const char *element, const char *s);
-static void print_xml_trailer(_cups_testdata_t *data, int success, const char *message);
+static void print_xml_trailer(ipptool_test_t *data, int success, const char *message);
#ifndef _WIN32
static void sigterm_handler(int sig);
#endif /* _WIN32 */
static int timeout_cb(http_t *http, void *user_data);
-static int token_cb(_ipp_file_t *f, _ipp_vars_t *vars, _cups_testdata_t *data, const char *token);
+static int token_cb(_ipp_file_t *f, _ipp_vars_t *vars, ipptool_test_t *data, const char *token);
static void usage(void) _CUPS_NORETURN;
+static int with_distinct_values(cups_array_t *errors, ipp_attribute_t *attr);
static const char *with_flags_string(int flags);
-static int with_value(_cups_testdata_t *data, cups_array_t *errors, char *value, int flags, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
+static int with_value(ipptool_test_t *data, cups_array_t *errors, char *value, int flags, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
static int with_value_from(cups_array_t *errors, ipp_attribute_t *fromattr, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
@@ -215,8 +231,8 @@ main(int argc, /* I - Number of command-line args */
*testfile; /* Test file to use */
int interval, /* Test interval in microseconds */
repeat; /* Repeat count */
- _cups_testdata_t data; /* Test data */
_ipp_vars_t vars; /* Variables */
+ ipptool_test_t data; /* Test data */
_cups_globals_t *cg = _cupsGlobals();
/* Global data */
@@ -239,8 +255,9 @@ main(int argc, /* I - Number of command-line args */
init_data(&data);
_ippVarsInit(&vars, NULL, (_ipp_ferror_cb_t)error_cb, (_ipp_ftoken_cb_t)token_cb);
+ data.vars = &vars;
- _ippVarsSet(&vars, "date-start", iso_date(ippTimeToDate(time(NULL))));
+ _ippVarsSet(data.vars, "date-start", iso_date(ippTimeToDate(time(NULL))));
/*
* We need at least:
@@ -278,7 +295,7 @@ main(int argc, /* I - Number of command-line args */
exit(1);
}
- data.output = _CUPS_OUTPUT_IPPSERVER;
+ data.output = IPPTOOL_OUTPUT_IPPSERVER;
}
else if (!strcmp(argv[i], "--stop-after-include-error"))
{
@@ -306,7 +323,7 @@ main(int argc, /* I - Number of command-line args */
#endif /* AF_INET6 */
case 'C' : /* Enable HTTP chunking */
- data.def_transfer = _CUPS_TRANSFER_CHUNKED;
+ data.def_transfer = IPPTOOL_TRANSFER_CHUNKED;
break;
case 'E' : /* Encrypt with TLS */
@@ -323,7 +340,7 @@ main(int argc, /* I - Number of command-line args */
break;
case 'L' : /* Disable HTTP chunking */
- data.def_transfer = _CUPS_TRANSFER_LENGTH;
+ data.def_transfer = IPPTOOL_TRANSFER_LENGTH;
break;
case 'P' : /* Output to plist file */
@@ -344,7 +361,7 @@ main(int argc, /* I - Number of command-line args */
exit(1);
}
- data.output = _CUPS_OUTPUT_PLIST;
+ data.output = IPPTOOL_OUTPUT_PLIST;
if (interval || repeat)
{
@@ -353,12 +370,15 @@ main(int argc, /* I - Number of command-line args */
}
break;
+ case 'R' : /* Repeat on server-error-busy */
+ data.repeat_on_busy = 1;
+ break;
+
case 'S' : /* Encrypt with SSL */
#ifdef HAVE_SSL
data.encryption = HTTP_ENCRYPT_ALWAYS;
#else
- _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
- argv[0]);
+ _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), "ipptool");
#endif /* HAVE_SSL */
break;
@@ -367,9 +387,7 @@ main(int argc, /* I - Number of command-line args */
if (i >= argc)
{
- _cupsLangPrintf(stderr,
- _("%s: Missing timeout for \"-T\"."),
- "ipptool");
+ _cupsLangPrintf(stderr, _("%s: Missing timeout for \"-T\"."), "ipptool");
usage();
}
@@ -381,9 +399,7 @@ main(int argc, /* I - Number of command-line args */
if (i >= argc)
{
- _cupsLangPrintf(stderr,
- _("%s: Missing version for \"-V\"."),
- "ipptool");
+ _cupsLangPrintf(stderr, _("%s: Missing version for \"-V\"."), "ipptool");
usage();
}
@@ -415,7 +431,7 @@ main(int argc, /* I - Number of command-line args */
break;
case 'X' : /* Produce XML output */
- data.output = _CUPS_OUTPUT_PLIST;
+ data.output = IPPTOOL_OUTPUT_PLIST;
if (interval || repeat)
{
@@ -425,7 +441,7 @@ main(int argc, /* I - Number of command-line args */
break;
case 'c' : /* CSV output */
- data.output = _CUPS_OUTPUT_CSV;
+ data.output = IPPTOOL_OUTPUT_CSV;
break;
case 'd' : /* Define a variable */
@@ -433,8 +449,7 @@ main(int argc, /* I - Number of command-line args */
if (i >= argc)
{
- _cupsLangPuts(stderr,
- _("ipptool: Missing name=value for \"-d\"."));
+ _cupsLangPuts(stderr, _("ipptool: Missing name=value for \"-d\"."));
usage();
}
@@ -444,7 +459,7 @@ main(int argc, /* I - Number of command-line args */
else
value = name + strlen(name);
- _ippVarsSet(&vars, name, value);
+ _ippVarsSet(data.vars, name, value);
break;
case 'f' : /* Set the default test filename */
@@ -452,8 +467,7 @@ main(int argc, /* I - Number of command-line args */
if (i >= argc)
{
- _cupsLangPuts(stderr,
- _("ipptool: Missing filename for \"-f\"."));
+ _cupsLangPuts(stderr, _("ipptool: Missing filename for \"-f\"."));
usage();
}
@@ -482,7 +496,7 @@ main(int argc, /* I - Number of command-line args */
else
strlcpy(filename, argv[i], sizeof(filename));
- _ippVarsSet(&vars, "filename", filename);
+ _ippVarsSet(data.vars, "filename", filename);
if ((ext = strrchr(filename, '.')) != NULL)
{
@@ -491,43 +505,43 @@ main(int argc, /* I - Number of command-line args */
*/
if (!_cups_strcasecmp(ext, ".gif"))
- _ippVarsSet(&vars, "filetype", "image/gif");
+ _ippVarsSet(data.vars, "filetype", "image/gif");
else if (!_cups_strcasecmp(ext, ".htm") ||
!_cups_strcasecmp(ext, ".htm.gz") ||
!_cups_strcasecmp(ext, ".html") ||
!_cups_strcasecmp(ext, ".html.gz"))
- _ippVarsSet(&vars, "filetype", "text/html");
+ _ippVarsSet(data.vars, "filetype", "text/html");
else if (!_cups_strcasecmp(ext, ".jpg") ||
!_cups_strcasecmp(ext, ".jpeg"))
- _ippVarsSet(&vars, "filetype", "image/jpeg");
+ _ippVarsSet(data.vars, "filetype", "image/jpeg");
else if (!_cups_strcasecmp(ext, ".pcl") ||
!_cups_strcasecmp(ext, ".pcl.gz"))
- _ippVarsSet(&vars, "filetype", "application/vnd.hp-PCL");
+ _ippVarsSet(data.vars, "filetype", "application/vnd.hp-PCL");
else if (!_cups_strcasecmp(ext, ".pdf"))
- _ippVarsSet(&vars, "filetype", "application/pdf");
+ _ippVarsSet(data.vars, "filetype", "application/pdf");
else if (!_cups_strcasecmp(ext, ".png"))
- _ippVarsSet(&vars, "filetype", "image/png");
+ _ippVarsSet(data.vars, "filetype", "image/png");
else if (!_cups_strcasecmp(ext, ".ps") ||
!_cups_strcasecmp(ext, ".ps.gz"))
- _ippVarsSet(&vars, "filetype", "application/postscript");
+ _ippVarsSet(data.vars, "filetype", "application/postscript");
else if (!_cups_strcasecmp(ext, ".pwg") ||
!_cups_strcasecmp(ext, ".pwg.gz") ||
!_cups_strcasecmp(ext, ".ras") ||
!_cups_strcasecmp(ext, ".ras.gz"))
- _ippVarsSet(&vars, "filetype", "image/pwg-raster");
+ _ippVarsSet(data.vars, "filetype", "image/pwg-raster");
else if (!_cups_strcasecmp(ext, ".tif") ||
!_cups_strcasecmp(ext, ".tiff"))
- _ippVarsSet(&vars, "filetype", "image/tiff");
+ _ippVarsSet(data.vars, "filetype", "image/tiff");
else if (!_cups_strcasecmp(ext, ".txt") ||
!_cups_strcasecmp(ext, ".txt.gz"))
- _ippVarsSet(&vars, "filetype", "text/plain");
+ _ippVarsSet(data.vars, "filetype", "text/plain");
else if (!_cups_strcasecmp(ext, ".urf") ||
!_cups_strcasecmp(ext, ".urf.gz"))
- _ippVarsSet(&vars, "filetype", "image/urf");
+ _ippVarsSet(data.vars, "filetype", "image/urf");
else if (!_cups_strcasecmp(ext, ".xps"))
- _ippVarsSet(&vars, "filetype", "application/openxps");
+ _ippVarsSet(data.vars, "filetype", "application/openxps");
else
- _ippVarsSet(&vars, "filetype", "application/octet-stream");
+ _ippVarsSet(data.vars, "filetype", "application/octet-stream");
}
else
{
@@ -535,7 +549,7 @@ main(int argc, /* I - Number of command-line args */
* Use the "auto-type" MIME media type...
*/
- _ippVarsSet(&vars, "filetype", "application/octet-stream");
+ _ippVarsSet(data.vars, "filetype", "application/octet-stream");
}
break;
@@ -561,7 +575,7 @@ main(int argc, /* I - Number of command-line args */
}
}
- if ((data.output == _CUPS_OUTPUT_PLIST || data.output == _CUPS_OUTPUT_IPPSERVER) && interval)
+ if ((data.output == IPPTOOL_OUTPUT_PLIST || data.output == IPPTOOL_OUTPUT_IPPSERVER) && interval)
{
_cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are incompatible with \"--ippserver\", \"-P\", and \"-X\"."));
usage();
@@ -569,7 +583,7 @@ main(int argc, /* I - Number of command-line args */
break;
case 'l' : /* List as a table */
- data.output = _CUPS_OUTPUT_LIST;
+ data.output = IPPTOOL_OUTPUT_LIST;
break;
case 'n' : /* Repeat count */
@@ -583,7 +597,7 @@ main(int argc, /* I - Number of command-line args */
else
repeat = atoi(argv[i]);
- if ((data.output == _CUPS_OUTPUT_PLIST || data.output == _CUPS_OUTPUT_IPPSERVER) && repeat)
+ if ((data.output == IPPTOOL_OUTPUT_PLIST || data.output == IPPTOOL_OUTPUT_IPPSERVER) && repeat)
{
_cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are incompatible with \"--ippserver\", \"-P\", and \"-X\"."));
usage();
@@ -591,11 +605,11 @@ main(int argc, /* I - Number of command-line args */
break;
case 'q' : /* Be quiet */
- data.output = _CUPS_OUTPUT_QUIET;
+ data.output = IPPTOOL_OUTPUT_QUIET;
break;
case 't' : /* CUPS test output */
- data.output = _CUPS_OUTPUT_TEST;
+ data.output = IPPTOOL_OUTPUT_TEST;
break;
case 'v' : /* Be verbose */
@@ -618,7 +632,7 @@ main(int argc, /* I - Number of command-line args */
* Set URI...
*/
- if (vars.uri)
+ if (data.vars->uri)
{
_cupsLangPuts(stderr, _("ipptool: May only specify a single URI."));
usage();
@@ -629,14 +643,14 @@ main(int argc, /* I - Number of command-line args */
data.encryption = HTTP_ENCRYPT_ALWAYS;
#endif /* HAVE_SSL */
- if (!_ippVarsSet(&vars, "uri", argv[i]))
+ if (!_ippVarsSet(data.vars, "uri", argv[i]))
{
_cupsLangPrintf(stderr, _("ipptool: Bad URI \"%s\"."), argv[i]);
return (1);
}
- if (vars.username[0] && vars.password)
- cupsSetPasswordCB2(_ippVarsPasswordCB, &vars);
+ if (data.vars->username[0] && data.vars->password)
+ cupsSetPasswordCB2(_ippVarsPasswordCB, data.vars);
}
else
{
@@ -644,7 +658,7 @@ main(int argc, /* I - Number of command-line args */
* Run test...
*/
- if (!vars.uri)
+ if (!data.vars->uri)
{
_cupsLangPuts(stderr, _("ipptool: URI required before test file."));
_cupsLangPuts(stderr, argv[i]);
@@ -666,26 +680,26 @@ main(int argc, /* I - Number of command-line args */
else
testfile = argv[i];
- if (!do_tests(testfile, &vars, &data))
+ if (!do_tests(testfile, &data))
status = 1;
}
}
- if (!vars.uri || !testfile)
+ if (!data.vars->uri || !testfile)
usage();
/*
* Loop if the interval is set...
*/
- if (data.output == _CUPS_OUTPUT_PLIST)
+ if (data.output == IPPTOOL_OUTPUT_PLIST)
print_xml_trailer(&data, !status, NULL);
else if (interval > 0 && repeat > 0)
{
while (repeat > 1)
{
usleep((useconds_t)interval);
- do_tests(testfile, &vars, &data);
+ do_tests(testfile, &data);
repeat --;
}
}
@@ -694,11 +708,11 @@ main(int argc, /* I - Number of command-line args */
for (;;)
{
usleep((useconds_t)interval);
- do_tests(testfile, &vars, &data);
+ do_tests(testfile, &data);
}
}
- if ((data.output == _CUPS_OUTPUT_TEST || (data.output == _CUPS_OUTPUT_PLIST && data.outfile)) && data.test_count > 1)
+ if ((data.output == IPPTOOL_OUTPUT_TEST || (data.output == IPPTOOL_OUTPUT_PLIST && data.outfile)) && data.test_count > 1)
{
/*
* Show a summary report if there were multiple tests...
@@ -709,7 +723,7 @@ main(int argc, /* I - Number of command-line args */
cupsFileClose(data.outfile);
-/*
+ /*
* Exit...
*/
@@ -882,20 +896,276 @@ copy_hex_string(char *buffer, /* I - String buffer */
/*
+ * 'do_monitor_printer_state()' - Do the MONITOR-PRINTER-STATE tests in the background.
+ */
+
+static void * // O - Thread exit status
+do_monitor_printer_state(
+ ipptool_test_t *data) // I - Test data
+{
+ int i; // Looping var
+ char scheme[32], // URI scheme
+ userpass[32], // URI username:password
+ host[256], // URI hostname/IP address
+ resource[256]; // URI resource path
+ int port; // URI port number
+ http_encryption_t encryption; // Encryption to use
+ http_t *http; // Connection to printer
+ ipp_t *request, // IPP request
+ *response = NULL; // IPP response
+ http_status_t status; // Request status
+ ipp_attribute_t *found; // Found attribute
+ ipptool_expect_t *expect; // Current EXPECT test
+ char buffer[131072]; // Copy buffer
+ static const char *pattrs[] = // List of attributes we care about
+ {
+ "marker-change-time", // "marker-xxx" are a CUPS/AirPrint extension
+ "marker-colors",
+ "marker-high-levels",
+ "marker-levels",
+ "marker-low-levels",
+ "marker-message",
+ "marker-names",
+ "marker-types",
+ "printer-alert",
+ "printer-alert-description",
+ "printer-config-change-date-time",
+ "printer-config-change-time",
+ "printer-config-changes",
+ "printer-current-time",
+ "printer-finisher",
+ "printer-finisher-description",
+ "printer-finisher-supplies",
+ "printer-finisher-supplies-description",
+ "printer-impressions-completed",
+ "printer-impressions-completed-col",
+ "printer-input-tray",
+ "printer-is-accepting-jobs",
+ "printer-media-sheets-completed",
+ "printer-media-sheets-completed-col",
+ "printer-message-date-time",
+ "printer-message-from-operator",
+ "printer-message-time",
+ "printer-output-tray",
+ "printer-pages-completed",
+ "printer-pages-completed-col",
+ "printer-state",
+ "printer-state-change-date-time",
+ "printer-state-change-time",
+ "printer-state-reasons",
+ "printer-supply",
+ "printer-supply-description",
+ "printer-up-time",
+ "queued-job-count"
+ };
+
+
+ // Connect to the printer...
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, data->monitor_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
+ {
+ print_fatal_error(data, "Bad printer URI \"%s\".", data->monitor_uri);
+ return (NULL);
+ }
+
+ if (!_cups_strcasecmp(scheme, "https") || !_cups_strcasecmp(scheme, "ipps") || port == 443)
+ encryption = HTTP_ENCRYPTION_ALWAYS;
+ else
+ encryption = data->encryption;
+
+ if ((http = httpConnect2(host, port, NULL, data->family, encryption, 1, 30000, NULL)) == NULL)
+ {
+ print_fatal_error(data, "Unable to connect to \"%s\" on port %d - %s", host, port, cupsLastErrorString());
+ return (0);
+ }
+
+#ifdef HAVE_LIBZ
+ httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING, "deflate, gzip, identity");
+#else
+ httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING, "identity");
+#endif /* HAVE_LIBZ */
+
+ if (data->timeout > 0.0)
+ httpSetTimeout(http, data->timeout, timeout_cb, NULL);
+
+ // Wait for the initial delay as needed...
+ if (data->monitor_delay)
+ usleep(data->monitor_delay);
+
+ // Create a query request that we'll reuse...
+ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+ ippSetVersion(request, data->version / 10, data->version % 10);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, data->monitor_uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
+
+ // Loop until we need to stop...
+ while (!data->monitor_done && !Cancel)
+ {
+ // Poll the printer state...
+ if ((status = cupsSendRequest(http, request, resource, ippLength(request))) != HTTP_STATUS_ERROR)
+ {
+ response = cupsGetResponse(http, resource);
+ status = httpGetStatus(http);
+ }
+
+ if (!data->monitor_done && !Cancel && status == HTTP_STATUS_ERROR && httpError(data->http) != EINVAL &&
+#ifdef _WIN32
+ httpError(data->http) != WSAETIMEDOUT)
+#else
+ httpError(data->http) != ETIMEDOUT)
+#endif // _WIN32
+ {
+ if (httpReconnect2(http, 30000, NULL))
+ break;
+ }
+ else if (status == HTTP_STATUS_ERROR || status == HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED)
+ {
+ break;
+ }
+ else if (status != HTTP_STATUS_OK)
+ {
+ httpFlush(http);
+
+ if (status == HTTP_STATUS_UNAUTHORIZED)
+ continue;
+
+ break;
+ }
+
+ for (i = data->num_monitor_expects, expect = data->monitor_expects; i > 0; i --, expect ++)
+ {
+ if (expect->if_defined && !_ippVarsGet(data->vars, expect->if_defined))
+ continue;
+
+ if (expect->if_not_defined && _ippVarsGet(data->vars, expect->if_not_defined))
+ continue;
+
+ found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
+
+ if ((found && expect->not_expect) ||
+ (!found && !(expect->not_expect || expect->optional)) ||
+ (found && !expect_matches(expect, found)) ||
+ (expect->in_group && ippGetGroupTag(found) != expect->in_group) ||
+ (expect->with_distinct && !with_distinct_values(NULL, found)))
+ {
+ if (expect->define_no_match)
+ {
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
+ data->monitor_done = 1;
+ }
+ break;
+ }
+
+ if (found)
+ ippAttributeString(found, buffer, sizeof(buffer));
+
+ if (found && !with_value(data, NULL, expect->with_value, expect->with_flags, found, buffer, sizeof(buffer)))
+ {
+ if (expect->define_no_match)
+ {
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
+ data->monitor_done = 1;
+ }
+ break;
+ }
+
+ if (found && expect->count > 0 && ippGetCount(found) != expect->count)
+ {
+ if (expect->define_no_match)
+ {
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
+ data->monitor_done = 1;
+ }
+ break;
+ }
+
+ if (found && expect->define_match)
+ {
+ _ippVarsSet(data->vars, expect->define_match, "1");
+ data->monitor_done = 1;
+ }
+
+ if (found && expect->define_value)
+ {
+ if (!expect->with_value)
+ {
+ int last = ippGetCount(found) - 1;
+ // Last element in attribute
+
+ switch (ippGetValueTag(found))
+ {
+ case IPP_TAG_ENUM :
+ case IPP_TAG_INTEGER :
+ snprintf(buffer, sizeof(buffer), "%d", ippGetInteger(found, last));
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ if (ippGetBoolean(found, last))
+ strlcpy(buffer, "true", sizeof(buffer));
+ else
+ strlcpy(buffer, "false", sizeof(buffer));
+ break;
+
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ case IPP_TAG_NAME :
+ case IPP_TAG_NAMELANG :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ strlcpy(buffer, ippGetString(found, last, NULL), sizeof(buffer));
+ break;
+
+ default :
+ ippAttributeString(found, buffer, sizeof(buffer));
+ break;
+ }
+ }
+
+ _ippVarsSet(data->vars, expect->define_value, buffer);
+ data->monitor_done = 1;
+ }
+ }
+
+ if (i == 0)
+ data->monitor_done = 1; // All tests passed
+
+ ippDelete(response);
+ response = NULL;
+
+ // Sleep between requests...
+ if (data->monitor_done || Cancel)
+ break;
+
+ usleep(data->monitor_interval);
+ }
+
+ // Close the connection to the printer and return...
+ httpClose(http);
+ ippDelete(request);
+ ippDelete(response);
+
+ return (NULL);
+}
+
+
+/*
* 'do_test()' - Do a single test from the test file.
*/
static int /* O - 1 on success, 0 on failure */
-do_test(_ipp_file_t *f, /* I - IPP data file */
- _ipp_vars_t *vars, /* I - IPP variables */
- _cups_testdata_t *data) /* I - Test data */
+do_test(_ipp_file_t *f, /* I - IPP data file */
+ ipptool_test_t *data) /* I - Test data */
{
int i, /* Looping var */
status_ok, /* Did we get a matching status? */
repeat_count = 0, /* Repeat count */
repeat_test; /* Repeat the test? */
- _cups_expect_t *expect; /* Current expected attribute */
+ ipptool_expect_t *expect; /* Current expected attribute */
ipp_t *request, /* IPP request */
*response; /* IPP response */
size_t length; /* Length of IPP request */
@@ -916,6 +1186,25 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
return (0);
/*
+ * Show any PAUSE message, as needed...
+ */
+
+ if (data->pause[0])
+ {
+ if (!data->skip_test)
+ pause_message(data->pause);
+
+ data->pause[0] = '\0';
+ }
+
+ /*
+ * Start the background thread as needed...
+ */
+
+ if (data->monitor_uri)
+ data->monitor_thread = _cupsThreadCreate((_cups_thread_func_t)do_monitor_printer_state, data);
+
+ /*
* Take over control of the attributes in the request...
*/
@@ -931,7 +1220,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
ippSetVersion(request, data->version / 10, data->version % 10);
ippSetRequestId(request, data->request_id);
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
{
cupsFilePuts(data->outfile, "<dict>\n");
cupsFilePuts(data->outfile, "<key>Name</key>\n");
@@ -964,14 +1253,14 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
cupsFilePuts(data->outfile, "</array>\n");
}
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
{
if (data->verbosity)
{
cupsFilePrintf(cupsFileStdout(), " %s:\n", ippOpString(ippGetOperation(request)));
for (attrptr = ippFirstAttribute(request); attrptr; attrptr = ippNextAttribute(request))
- print_attr(cupsFileStdout(), _CUPS_OUTPUT_TEST, attrptr, NULL);
+ print_attr(cupsFileStdout(), IPPTOOL_OUTPUT_TEST, attrptr, NULL);
}
cupsFilePrintf(cupsFileStdout(), " %-68.68s [", data->name);
@@ -985,7 +1274,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
request = NULL;
response = NULL;
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
{
cupsFilePuts(data->outfile, "<key>Successful</key>\n");
cupsFilePuts(data->outfile, "<true />\n");
@@ -997,13 +1286,13 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
cupsFilePuts(data->outfile, "<dict />\n");
}
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
cupsFilePuts(cupsFileStdout(), "SKIP]\n");
goto skip_error;
}
- vars->password_tries = 0;
+ data->vars->password_tries = 0;
do
{
@@ -1015,7 +1304,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
status = HTTP_STATUS_OK;
- if (data->transfer == _CUPS_TRANSFER_CHUNKED || (data->transfer == _CUPS_TRANSFER_AUTO && data->file[0]))
+ if (data->transfer == IPPTOOL_TRANSFER_CHUNKED || (data->transfer == IPPTOOL_TRANSFER_AUTO && data->file[0]))
{
/*
* Send request using chunking - a 0 length means "chunk".
@@ -1056,6 +1345,8 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
{
while (!response && !Cancel && data->prev_pass)
{
+ ippSetRequestId(request, ++ data->request_id);
+
status = cupsSendRequest(data->http, request, data->resource, length);
#ifdef HAVE_LIBZ
@@ -1185,16 +1476,16 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if ((attrptr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
{
snprintf(temp, sizeof(temp), "%d", ippGetInteger(attrptr, 0));
- _ippVarsSet(vars, "job-id", temp);
+ _ippVarsSet(data->vars, "job-id", temp);
}
if ((attrptr = ippFindAttribute(response, "job-uri", IPP_TAG_URI)) != NULL)
- _ippVarsSet(vars, "job-uri", ippGetString(attrptr, 0, NULL));
+ _ippVarsSet(data->vars, "job-uri", ippGetString(attrptr, 0, NULL));
if ((attrptr = ippFindAttribute(response, "notify-subscription-id", IPP_TAG_INTEGER)) != NULL)
{
snprintf(temp, sizeof(temp), "%d", ippGetInteger(attrptr, 0));
- _ippVarsSet(vars, "notify-subscription-id", temp);
+ _ippVarsSet(data->vars, "notify-subscription-id", temp);
}
/*
@@ -1212,27 +1503,27 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
major = ippGetVersion(response, &minor);
if (major != (data->version / 10) || minor != (data->version % 10))
- add_stringf(data->errors, "Bad version %d.%d in response - expected %d.%d (RFC 2911 section 3.1.8).", major, minor, data->version / 10, data->version % 10);
+ add_stringf(data->errors, "Bad version %d.%d in response - expected %d.%d (RFC 8011 section 4.1.8).", major, minor, data->version / 10, data->version % 10);
}
if (ippGetRequestId(response) != data->request_id)
- add_stringf(data->errors, "Bad request ID %d in response - expected %d (RFC 2911 section 3.1.1)", ippGetRequestId(response), data->request_id);
+ add_stringf(data->errors, "Bad request ID %d in response - expected %d (RFC 8011 section 4.1.1)", ippGetRequestId(response), data->request_id);
attrptr = ippFirstAttribute(response);
if (!attrptr)
{
- add_stringf(data->errors, "Missing first attribute \"attributes-charset (charset)\" in group operation-attributes-tag (RFC 2911 section 3.1.4).");
+ add_stringf(data->errors, "Missing first attribute \"attributes-charset (charset)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).");
}
else
{
if (!ippGetName(attrptr) || ippGetValueTag(attrptr) != IPP_TAG_CHARSET || ippGetGroupTag(attrptr) != IPP_TAG_OPERATION || ippGetCount(attrptr) != 1 ||strcmp(ippGetName(attrptr), "attributes-charset"))
- add_stringf(data->errors, "Bad first attribute \"%s (%s%s)\" in group %s, expected \"attributes-charset (charset)\" in group operation-attributes-tag (RFC 2911 section 3.1.4).", ippGetName(attrptr) ? ippGetName(attrptr) : "(null)", ippGetCount(attrptr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attrptr)), ippTagString(ippGetGroupTag(attrptr)));
+ add_stringf(data->errors, "Bad first attribute \"%s (%s%s)\" in group %s, expected \"attributes-charset (charset)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).", ippGetName(attrptr) ? ippGetName(attrptr) : "(null)", ippGetCount(attrptr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attrptr)), ippTagString(ippGetGroupTag(attrptr)));
attrptr = ippNextAttribute(response);
if (!attrptr)
- add_stringf(data->errors, "Missing second attribute \"attributes-natural-language (naturalLanguage)\" in group operation-attributes-tag (RFC 2911 section 3.1.4).");
+ add_stringf(data->errors, "Missing second attribute \"attributes-natural-language (naturalLanguage)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).");
else if (!ippGetName(attrptr) || ippGetValueTag(attrptr) != IPP_TAG_LANGUAGE || ippGetGroupTag(attrptr) != IPP_TAG_OPERATION || ippGetCount(attrptr) != 1 || strcmp(ippGetName(attrptr), "attributes-natural-language"))
- add_stringf(data->errors, "Bad first attribute \"%s (%s%s)\" in group %s, expected \"attributes-natural-language (naturalLanguage)\" in group operation-attributes-tag (RFC 2911 section 3.1.4).", ippGetName(attrptr) ? ippGetName(attrptr) : "(null)", ippGetCount(attrptr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attrptr)), ippTagString(ippGetGroupTag(attrptr)));
+ add_stringf(data->errors, "Bad first attribute \"%s (%s%s)\" in group %s, expected \"attributes-natural-language (naturalLanguage)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).", ippGetName(attrptr) ? ippGetName(attrptr) : "(null)", ippGetCount(attrptr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attrptr)), ippTagString(ippGetGroupTag(attrptr)));
}
if ((attrptr = ippFindAttribute(response, "status-message", IPP_TAG_ZERO)) != NULL)
@@ -1241,13 +1532,13 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
/* String value */
if (ippGetValueTag(attrptr) != IPP_TAG_TEXT)
- add_stringf(data->errors, "status-message (text(255)) has wrong value tag %s (RFC 2911 section 3.1.6.2).", ippTagString(ippGetValueTag(attrptr)));
+ add_stringf(data->errors, "status-message (text(255)) has wrong value tag %s (RFC 8011 section 4.1.6.2).", ippTagString(ippGetValueTag(attrptr)));
if (ippGetGroupTag(attrptr) != IPP_TAG_OPERATION)
- add_stringf(data->errors, "status-message (text(255)) has wrong group tag %s (RFC 2911 section 3.1.6.2).", ippTagString(ippGetGroupTag(attrptr)));
+ add_stringf(data->errors, "status-message (text(255)) has wrong group tag %s (RFC 8011 section 4.1.6.2).", ippTagString(ippGetGroupTag(attrptr)));
if (ippGetCount(attrptr) != 1)
- add_stringf(data->errors, "status-message (text(255)) has %d values (RFC 2911 section 3.1.6.2).", ippGetCount(attrptr));
+ add_stringf(data->errors, "status-message (text(255)) has %d values (RFC 8011 section 4.1.6.2).", ippGetCount(attrptr));
if (status_message && strlen(status_message) > 255)
- add_stringf(data->errors, "status-message (text(255)) has bad length %d (RFC 2911 section 3.1.6.2).", (int)strlen(status_message));
+ add_stringf(data->errors, "status-message (text(255)) has bad length %d (RFC 8011 section 4.1.6.2).", (int)strlen(status_message));
}
if ((attrptr = ippFindAttribute(response, "detailed-status-message",
@@ -1257,25 +1548,13 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
/* String value */
if (ippGetValueTag(attrptr) != IPP_TAG_TEXT)
- add_stringf(data->errors,
- "detailed-status-message (text(MAX)) has wrong "
- "value tag %s (RFC 2911 section 3.1.6.3).",
- ippTagString(ippGetValueTag(attrptr)));
+ add_stringf(data->errors, "detailed-status-message (text(MAX)) has wrong value tag %s (RFC 8011 section 4.1.6.3).", ippTagString(ippGetValueTag(attrptr)));
if (ippGetGroupTag(attrptr) != IPP_TAG_OPERATION)
- add_stringf(data->errors,
- "detailed-status-message (text(MAX)) has wrong "
- "group tag %s (RFC 2911 section 3.1.6.3).",
- ippTagString(ippGetGroupTag(attrptr)));
+ add_stringf(data->errors, "detailed-status-message (text(MAX)) has wrong group tag %s (RFC 8011 section 4.1.6.3).", ippTagString(ippGetGroupTag(attrptr)));
if (ippGetCount(attrptr) != 1)
- add_stringf(data->errors,
- "detailed-status-message (text(MAX)) has %d values"
- " (RFC 2911 section 3.1.6.3).",
- ippGetCount(attrptr));
+ add_stringf(data->errors, "detailed-status-message (text(MAX)) has %d values (RFC 8011 section 4.1.6.3).", ippGetCount(attrptr));
if (detailed_status_message && strlen(detailed_status_message) > 1023)
- add_stringf(data->errors,
- "detailed-status-message (text(MAX)) has bad "
- "length %d (RFC 2911 section 3.1.6.3).",
- (int)strlen(detailed_status_message));
+ add_stringf(data->errors, "detailed-status-message (text(MAX)) has bad length %d (RFC 8011 section 4.1.6.3).", (int)strlen(detailed_status_message));
}
a = cupsArrayNew((cups_array_func_t)strcmp, NULL);
@@ -1321,9 +1600,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
if (out_of_order)
- add_stringf(data->errors, "Attribute groups out of order (%s < %s)",
- ippTagString(ippGetGroupTag(attrptr)),
- ippTagString(group));
+ add_stringf(data->errors, "Attribute groups out of order (%s < %s)", ippTagString(ippGetGroupTag(attrptr)), ippTagString(group));
if (ippGetGroupTag(attrptr) != IPP_TAG_ZERO)
group = ippGetGroupTag(attrptr);
@@ -1334,9 +1611,8 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (ippGetName(attrptr))
{
- if (cupsArrayFind(a, (void *)ippGetName(attrptr)) && data->output < _CUPS_OUTPUT_LIST)
- add_stringf(data->errors, "Duplicate \"%s\" attribute in %s group",
- ippGetName(attrptr), ippTagString(group));
+ if (cupsArrayFind(a, (void *)ippGetName(attrptr)) && data->output < IPPTOOL_OUTPUT_LIST)
+ add_stringf(data->errors, "Duplicate \"%s\" attribute in %s group", ippGetName(attrptr), ippTagString(group));
cupsArrayAdd(a, (void *)ippGetName(attrptr));
}
@@ -1349,14 +1625,21 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
* values...
*/
+ if (ippGetStatusCode(response) == IPP_STATUS_ERROR_BUSY && data->repeat_on_busy)
+ {
+ // Repeat on a server-error-busy status code...
+ status_ok = 1;
+ repeat_test = 1;
+ }
+
for (i = 0, status_ok = 0; i < data->num_statuses; i ++)
{
if (data->statuses[i].if_defined &&
- !_ippVarsGet(vars, data->statuses[i].if_defined))
+ !_ippVarsGet(data->vars, data->statuses[i].if_defined))
continue;
if (data->statuses[i].if_not_defined &&
- _ippVarsGet(vars, data->statuses[i].if_not_defined))
+ _ippVarsGet(data->vars, data->statuses[i].if_not_defined))
continue;
if (ippGetStatusCode(response) == data->statuses[i].status)
@@ -1367,7 +1650,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
repeat_test = 1;
if (data->statuses[i].define_match)
- _ippVarsSet(vars, data->statuses[i].define_match, "1");
+ _ippVarsSet(data->vars, data->statuses[i].define_match, "1");
}
else
{
@@ -1376,7 +1659,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (data->statuses[i].define_no_match)
{
- _ippVarsSet(vars, data->statuses[i].define_no_match, "1");
+ _ippVarsSet(data->vars, data->statuses[i].define_no_match, "1");
status_ok = 1;
}
}
@@ -1387,21 +1670,18 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
for (i = 0; i < data->num_statuses; i ++)
{
if (data->statuses[i].if_defined &&
- !_ippVarsGet(vars, data->statuses[i].if_defined))
+ !_ippVarsGet(data->vars, data->statuses[i].if_defined))
continue;
if (data->statuses[i].if_not_defined &&
- _ippVarsGet(vars, data->statuses[i].if_not_defined))
+ _ippVarsGet(data->vars, data->statuses[i].if_not_defined))
continue;
if (!data->statuses[i].repeat_match || repeat_count >= data->statuses[i].repeat_limit)
- add_stringf(data->errors, "EXPECTED: STATUS %s (got %s)",
- ippErrorString(data->statuses[i].status),
- ippErrorString(cupsLastError()));
+ add_stringf(data->errors, "EXPECTED: STATUS %s (got %s)", ippErrorString(data->statuses[i].status), ippErrorString(cupsLastError()));
}
- if ((attrptr = ippFindAttribute(response, "status-message",
- IPP_TAG_TEXT)) != NULL)
+ if ((attrptr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT)) != NULL)
add_stringf(data->errors, "status-message=\"%s\"", ippGetString(attrptr, 0, NULL));
}
@@ -1409,11 +1689,11 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
{
ipp_attribute_t *group_found; /* Found parent attribute for group tests */
- if (expect->if_defined && !_ippVarsGet(vars, expect->if_defined))
+ if (expect->if_defined && !_ippVarsGet(data->vars, expect->if_defined))
continue;
if (expect->if_not_defined &&
- _ippVarsGet(vars, expect->if_not_defined))
+ _ippVarsGet(data->vars, expect->if_not_defined))
continue;
if ((found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL && expect->in_group && expect->in_group != ippGetGroupTag(found))
@@ -1441,11 +1721,12 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if ((found && expect->not_expect) ||
(!found && !(expect->not_expect || expect->optional)) ||
- (found && !expect_matches(expect, ippGetValueTag(found))) ||
- (group_found && expect->in_group && ippGetGroupTag(group_found) != expect->in_group))
+ (found && !expect_matches(expect, found)) ||
+ (group_found && expect->in_group && ippGetGroupTag(group_found) != expect->in_group) ||
+ (expect->with_distinct && !with_distinct_values(NULL, found)))
{
if (expect->define_no_match)
- _ippVarsSet(vars, expect->define_no_match, "1");
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
else if (!expect->define_match && !expect->define_value)
{
if (found && expect->not_expect && !expect->with_value && !expect->with_value_from)
@@ -1454,7 +1735,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
add_stringf(data->errors, "EXPECTED: %s", expect->name);
else if (found)
{
- if (!expect_matches(expect, ippGetValueTag(found)))
+ if (!expect_matches(expect, found))
add_stringf(data->errors, "EXPECTED: %s OF-TYPE %s (got %s)",
expect->name, expect->of_type,
ippTagString(ippGetValueTag(found)));
@@ -1463,6 +1744,9 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
add_stringf(data->errors, "EXPECTED: %s IN-GROUP %s (got %s).",
expect->name, ippTagString(expect->in_group),
ippTagString(ippGetGroupTag(group_found)));
+
+ if (expect->with_distinct)
+ with_distinct_values(data->errors, found);
}
}
@@ -1477,7 +1761,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (found && expect->with_value_from && !with_value_from(NULL, ippFindAttribute(response, expect->with_value_from, IPP_TAG_ZERO), found, buffer, sizeof(buffer)))
{
if (expect->define_no_match)
- _ippVarsSet(vars, expect->define_no_match, "1");
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
else if (!expect->define_match && !expect->define_value && ((!expect->repeat_match && !expect->repeat_no_match) || repeat_count >= expect->repeat_limit))
{
add_stringf(data->errors, "EXPECTED: %s WITH-VALUES-FROM %s", expect->name, expect->with_value_from);
@@ -1493,11 +1777,11 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
else if (found && !with_value(data, NULL, expect->with_value, expect->with_flags, found, buffer, sizeof(buffer)))
{
if (expect->define_no_match)
- _ippVarsSet(vars, expect->define_no_match, "1");
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
else if (!expect->define_match && !expect->define_value &&
!expect->repeat_match && (!expect->repeat_no_match || repeat_count >= expect->repeat_limit))
{
- if (expect->with_flags & _CUPS_WITH_REGEX)
+ if (expect->with_flags & IPPTOOL_WITH_REGEX)
add_stringf(data->errors, "EXPECTED: %s %s /%s/", expect->name, with_flags_string(expect->with_flags), expect->with_value);
else
add_stringf(data->errors, "EXPECTED: %s %s \"%s\"", expect->name, with_flags_string(expect->with_flags), expect->with_value);
@@ -1515,11 +1799,10 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (found && expect->count > 0 && ippGetCount(found) != expect->count)
{
if (expect->define_no_match)
- _ippVarsSet(vars, expect->define_no_match, "1");
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
else if (!expect->define_match && !expect->define_value)
{
- add_stringf(data->errors, "EXPECTED: %s COUNT %d (got %d)", expect->name,
- expect->count, ippGetCount(found));
+ add_stringf(data->errors, "EXPECTED: %s COUNT %d (got %d)", expect->name, expect->count, ippGetCount(found));
}
if (expect->repeat_no_match &&
@@ -1537,19 +1820,13 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (!attrptr || ippGetCount(attrptr) != ippGetCount(found))
{
if (expect->define_no_match)
- _ippVarsSet(vars, expect->define_no_match, "1");
+ _ippVarsSet(data->vars, expect->define_no_match, "1");
else if (!expect->define_match && !expect->define_value)
{
if (!attrptr)
- add_stringf(data->errors,
- "EXPECTED: %s (%d values) SAME-COUNT-AS %s "
- "(not returned)", expect->name,
- ippGetCount(found), expect->same_count_as);
+ add_stringf(data->errors, "EXPECTED: %s (%d values) SAME-COUNT-AS %s (not returned)", expect->name, ippGetCount(found), expect->same_count_as);
else if (ippGetCount(attrptr) != ippGetCount(found))
- add_stringf(data->errors,
- "EXPECTED: %s (%d values) SAME-COUNT-AS %s "
- "(%d values)", expect->name, ippGetCount(found),
- expect->same_count_as, ippGetCount(attrptr));
+ add_stringf(data->errors, "EXPECTED: %s (%d values) SAME-COUNT-AS %s (%d values)", expect->name, ippGetCount(found), expect->same_count_as, ippGetCount(attrptr));
}
if (expect->repeat_no_match &&
@@ -1561,7 +1838,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
if (found && expect->define_match)
- _ippVarsSet(vars, expect->define_match, "1");
+ _ippVarsSet(data->vars, expect->define_match, "1");
if (found && expect->define_value)
{
@@ -1618,7 +1895,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
}
- _ippVarsSet(vars, expect->define_value, buffer);
+ _ippVarsSet(data->vars, expect->define_value, buffer);
}
if (found && expect->repeat_match &&
@@ -1635,7 +1912,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (repeat_test)
{
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
{
cupsFilePrintf(cupsFileStdout(), "%04d]\n", repeat_count);
\
@@ -1650,7 +1927,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
{
if (!strcmp(data->displayed[i], attrname))
{
- print_attr(cupsFileStdout(), _CUPS_OUTPUT_TEST, attrptr, NULL);
+ print_attr(cupsFileStdout(), IPPTOOL_OUTPUT_TEST, attrptr, NULL);
break;
}
}
@@ -1659,7 +1936,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
}
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
{
cupsFilePrintf(cupsFileStdout(), " %-68.68s [", data->name);
}
@@ -1682,7 +1959,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
else
data->fail_count ++;
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
{
cupsFilePuts(data->outfile, "<key>Successful</key>\n");
cupsFilePuts(data->outfile, data->prev_pass ? "<true />\n" : "<false />\n");
@@ -1698,7 +1975,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
cupsFilePuts(data->outfile, "</dict>\n");
cupsFilePuts(data->outfile, "</array>\n");
}
- else if (data->output == _CUPS_OUTPUT_IPPSERVER && response)
+ else if (data->output == IPPTOOL_OUTPUT_IPPSERVER && response)
{
for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
{
@@ -1709,7 +1986,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
}
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
{
cupsFilePuts(cupsFileStdout(), data->prev_pass ? "PASS]\n" : "FAIL]\n");
@@ -1721,14 +1998,14 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (data->verbosity && response)
{
for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
- print_attr(cupsFileStdout(), _CUPS_OUTPUT_TEST, attrptr, NULL);
+ print_attr(cupsFileStdout(), IPPTOOL_OUTPUT_TEST, attrptr, NULL);
}
}
}
- else if (!data->prev_pass && data->output != _CUPS_OUTPUT_QUIET)
+ else if (!data->prev_pass && data->output != IPPTOOL_OUTPUT_QUIET)
fprintf(stderr, "%s\n", cupsLastErrorString());
- if (data->prev_pass && data->output >= _CUPS_OUTPUT_LIST && !data->verbosity && data->num_displayed > 0)
+ if (data->prev_pass && data->output >= IPPTOOL_OUTPUT_LIST && !data->verbosity && data->num_displayed > 0)
{
size_t width; /* Length of value */
@@ -1746,7 +2023,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
}
- if (data->output == _CUPS_OUTPUT_CSV)
+ if (data->output == IPPTOOL_OUTPUT_CSV)
print_csv(data, NULL, NULL, data->num_displayed, data->displayed, widths);
else
print_line(data, NULL, NULL, data->num_displayed, data->displayed, widths);
@@ -1760,7 +2037,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
if (attrptr)
{
- if (data->output == _CUPS_OUTPUT_CSV)
+ if (data->output == IPPTOOL_OUTPUT_CSV)
print_csv(data, response, attrptr, data->num_displayed, data->displayed, widths);
else
print_line(data, response, attrptr, data->num_displayed, data->displayed, widths);
@@ -1772,7 +2049,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
else if (!data->prev_pass)
{
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
{
cupsFilePuts(data->outfile, "<key>Errors</key>\n");
cupsFilePuts(data->outfile, "<array>\n");
@@ -1785,7 +2062,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
cupsFilePuts(data->outfile, "</array>\n");
}
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
{
for (error = (char *)cupsArrayFirst(data->errors);
error;
@@ -1794,7 +2071,7 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
}
}
- if (data->num_displayed > 0 && !data->verbosity && response && (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout())))
+ if (data->num_displayed > 0 && !data->verbosity && response && (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout())))
{
for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
{
@@ -1814,7 +2091,13 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
skip_error:
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->monitor_thread)
+ {
+ data->monitor_done = 1;
+ _cupsThreadWait(data->monitor_thread);
+ }
+
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
cupsFilePuts(data->outfile, "</dict>\n");
ippDelete(response);
@@ -1859,6 +2142,31 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
free(data->displayed[i]);
data->num_displayed = 0;
+ free(data->monitor_uri);
+ data->monitor_uri = NULL;
+
+ for (i = data->num_monitor_expects, expect = data->monitor_expects; i > 0; i --, expect ++)
+ {
+ free(expect->name);
+ if (expect->of_type)
+ free(expect->of_type);
+ if (expect->same_count_as)
+ free(expect->same_count_as);
+ if (expect->if_defined)
+ free(expect->if_defined);
+ if (expect->if_not_defined)
+ free(expect->if_not_defined);
+ if (expect->with_value)
+ free(expect->with_value);
+ if (expect->define_match)
+ free(expect->define_match);
+ if (expect->define_no_match)
+ free(expect->define_no_match);
+ if (expect->define_value)
+ free(expect->define_value);
+ }
+ data->num_monitor_expects = 0;
+
return (data->ignore_errors || data->prev_pass);
}
@@ -1868,9 +2176,8 @@ do_test(_ipp_file_t *f, /* I - IPP data file */
*/
static int /* O - 1 on success, 0 on failure */
-do_tests(const char *testfile, /* I - Test file to use */
- _ipp_vars_t *vars, /* I - Variables */
- _cups_testdata_t *data) /* I - Test data */
+do_tests(const char *testfile, /* I - Test file to use */
+ ipptool_test_t *data) /* I - Test data */
{
http_encryption_t encryption; /* Encryption mode */
@@ -1879,14 +2186,14 @@ do_tests(const char *testfile, /* I - Test file to use */
* Connect to the printer/server...
*/
- if (!_cups_strcasecmp(vars->scheme, "https") || !_cups_strcasecmp(vars->scheme, "ipps"))
+ if (!_cups_strcasecmp(data->vars->scheme, "https") || !_cups_strcasecmp(data->vars->scheme, "ipps") || data->vars->port == 443)
encryption = HTTP_ENCRYPTION_ALWAYS;
else
encryption = data->encryption;
- if ((data->http = httpConnect2(vars->host, vars->port, NULL, data->family, encryption, 1, 30000, NULL)) == NULL)
+ if ((data->http = httpConnect2(data->vars->host, data->vars->port, NULL, data->family, encryption, 1, 30000, NULL)) == NULL)
{
- print_fatal_error(data, "Unable to connect to \"%s\" on port %d - %s", vars->host, vars->port, cupsLastErrorString());
+ print_fatal_error(data, "Unable to connect to \"%s\" on port %d - %s", data->vars->host, data->vars->port, cupsLastErrorString());
return (0);
}
@@ -1903,7 +2210,7 @@ do_tests(const char *testfile, /* I - Test file to use */
* Run tests...
*/
- _ippFileParse(vars, testfile, (void *)data);
+ _ippFileParse(data->vars, testfile, (void *)data);
/*
* Close connection and return...
@@ -1922,7 +2229,7 @@ do_tests(const char *testfile, /* I - Test file to use */
static int /* O - 1 to continue, 0 to stop */
error_cb(_ipp_file_t *f, /* I - IPP file data */
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
const char *error) /* I - Error message */
{
(void)f;
@@ -1939,13 +2246,18 @@ error_cb(_ipp_file_t *f, /* I - IPP file data */
static int /* O - 1 if matches, 0 otherwise */
expect_matches(
- _cups_expect_t *expect, /* I - Expected attribute */
- ipp_tag_t value_tag) /* I - Value tag for attribute */
+ ipptool_expect_t *expect, /* I - Expected attribute */
+ ipp_attribute_t *attr) /* I - Attribute */
{
- int match; /* Match? */
- char *of_type, /* Type name to match */
- *next, /* Next name to match */
- sep; /* Separator character */
+ int i, /* Looping var */
+ count, /* Number of values */
+ match; /* Match? */
+ char *of_type, /* Type name to match */
+ *paren, /* Pointer to opening parenthesis */
+ *next, /* Next name to match */
+ sep; /* Separator character */
+ ipp_tag_t value_tag; /* Syntax/value tag */
+ int lower, upper; /* Lower and upper bounds for syntax */
/*
@@ -1960,6 +2272,9 @@ expect_matches(
* types separated by "," or "|"...
*/
+ value_tag = ippGetValueTag(attr);
+ count = ippGetCount(attr);
+
for (of_type = expect->of_type, match = 0; !match && *of_type; of_type = next)
{
/*
@@ -1975,19 +2290,154 @@ expect_matches(
* Support some meta-types to make it easier to write the test file.
*/
+ if ((paren = strchr(of_type, '(')) != NULL)
+ {
+ char *ptr; // Pointer into syntax string
+
+ *paren = '\0';
+
+ if (!strncmp(paren + 1, "MIN:", 4))
+ {
+ lower = INT_MIN;
+ ptr = paren + 5;
+ }
+ else if ((ptr = strchr(paren + 1, ':')) != NULL)
+ {
+ lower = atoi(paren + 1);
+ }
+ else
+ {
+ lower = 0;
+ ptr = paren + 1;
+ }
+
+ if (!strcmp(ptr, "MAX)"))
+ upper = INT_MAX;
+ else
+ upper = atoi(ptr);
+ }
+ else
+ {
+ lower = INT_MIN;
+ upper = INT_MAX;
+ }
+
if (!strcmp(of_type, "text"))
- match = value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_TEXT;
+ {
+ if (upper == INT_MAX)
+ upper = 1023;
+
+ if (value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_TEXT)
+ {
+ for (i = 0; i < count; i ++)
+ {
+ if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
+ break;
+ }
+
+ match = (i == count);
+ }
+ }
else if (!strcmp(of_type, "name"))
- match = value_tag == IPP_TAG_NAMELANG || value_tag == IPP_TAG_NAME;
+ {
+ if (upper == INT_MAX)
+ upper = 255;
+
+ if (value_tag == IPP_TAG_NAMELANG || value_tag == IPP_TAG_NAME)
+ {
+ for (i = 0; i < count; i ++)
+ {
+ if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
+ break;
+ }
+
+ match = (i == count);
+ }
+ }
else if (!strcmp(of_type, "collection"))
+ {
match = value_tag == IPP_TAG_BEGIN_COLLECTION;
- else
- match = value_tag == ippTagValue(of_type);
+ }
+ else if (value_tag == ippTagValue(of_type))
+ {
+ switch (value_tag)
+ {
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URI :
+ if (upper == INT_MAX)
+ {
+ if (value_tag == IPP_TAG_KEYWORD)
+ upper = 255;
+ else
+ upper = 1023;
+ }
+
+ for (i = 0; i < count; i ++)
+ {
+ if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
+ break;
+ }
+
+ match = (i == count);
+ break;
+
+ case IPP_TAG_STRING :
+ if (upper == INT_MAX)
+ upper = 1023;
+
+ for (i = 0; i < count; i ++)
+ {
+ int datalen; // Length of octetString value
+
+ ippGetOctetString(attr, i, &datalen);
+
+ if (datalen > upper)
+ break;
+ }
+
+ match = (i == count);
+ break;
+
+ case IPP_TAG_INTEGER :
+ for (i = 0; i < count; i ++)
+ {
+ int value = ippGetInteger(attr, i);
+ // Integer value
+
+ if (value < lower || value > upper)
+ break;
+ }
+
+ match = (i == count);
+ break;
+
+ case IPP_TAG_RANGE :
+ for (i = 0; i < count; i ++)
+ {
+ int vupper, vlower = ippGetRange(attr, i, &vupper);
+ // Range value
+
+ if (vlower < lower || vlower > upper || vupper < lower || vupper > upper)
+ break;
+ }
+
+ match = (i == count);
+ break;
+
+ default :
+ // No other constraints, so this is a match
+ match = 1;
+ break;
+ }
+ }
/*
- * Restore the separator if we have one...
+ * Restore the separators if we have them...
*/
+ if (paren)
+ *paren = '(';
+
if (sep)
*next++ = sep;
}
@@ -2047,6 +2497,21 @@ get_filename(const char *testfile, /* I - Current test file */
dstptr = dst; /* Should never happen */
strlcpy(dstptr, src, dstsize - (size_t)(dstptr - dst));
+
+#if _WIN32
+ if (_access(dst, 0))
+ {
+ /*
+ * Not available relative to the testfile, see if it can be found on the
+ * desktop...
+ */
+ const char *userprofile = getenv("USERPROFILE");
+ /* User home directory */
+
+ if (userprofile)
+ snprintf(dst, dstsize, "%s/Desktop/%s", userprofile, src);
+ }
+#endif /* _WIN32 */
}
return (dst);
@@ -2075,7 +2540,7 @@ get_string(ipp_attribute_t *attr, /* I - IPP attribute */
value = ippGetString(attr, element, NULL);
- if (flags & _CUPS_WITH_HOSTNAME)
+ if (flags & IPPTOOL_WITH_HOSTNAME)
{
if (httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme), userpass, sizeof(userpass), buffer, (int)bufsize, &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
buffer[0] = '\0';
@@ -2086,14 +2551,14 @@ get_string(ipp_attribute_t *attr, /* I - IPP attribute */
return (buffer);
}
- else if (flags & _CUPS_WITH_RESOURCE)
+ else if (flags & IPPTOOL_WITH_RESOURCE)
{
if (httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, buffer, (int)bufsize) < HTTP_URI_STATUS_OK)
buffer[0] = '\0';
return (buffer);
}
- else if (flags & _CUPS_WITH_SCHEME)
+ else if (flags & IPPTOOL_WITH_SCHEME)
{
if (httpSeparateURI(HTTP_URI_CODING_ALL, value, buffer, (int)bufsize, userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
buffer[0] = '\0';
@@ -2136,19 +2601,19 @@ get_string(ipp_attribute_t *attr, /* I - IPP attribute */
*/
static void
-init_data(_cups_testdata_t *data) /* I - Data */
+init_data(ipptool_test_t *data) /* I - Data */
{
- memset(data, 0, sizeof(_cups_testdata_t));
+ memset(data, 0, sizeof(ipptool_test_t));
- data->output = _CUPS_OUTPUT_LIST;
+ data->output = IPPTOOL_OUTPUT_LIST;
data->outfile = cupsFileStdout();
data->family = AF_UNSPEC;
- data->def_transfer = _CUPS_TRANSFER_AUTO;
+ data->def_transfer = IPPTOOL_TRANSFER_AUTO;
data->def_version = 11;
data->errors = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
data->pass = 1;
data->prev_pass = 1;
- data->request_id = (CUPS_RAND() % 1000) * 137 + 1;
+ data->request_id = (CUPS_RAND() % 1000) * 137;
data->show_header = 1;
}
@@ -2178,6 +2643,422 @@ iso_date(const ipp_uchar_t *date) /* I - IPP (RFC 1903) date/time value */
/*
+ * 'parse_monitor_printer_state()' - Parse the MONITOR-PRINTER-STATE directive.
+ *
+ * MONITOR-PRINTER-STATE [printer-uri] {
+ * DELAY nnn
+ * EXPECT attribute-name ...
+ * }
+ */
+
+static int /* O - 1 to continue, 0 to stop */
+parse_monitor_printer_state(
+ _ipp_file_t *f, /* I - IPP file data */
+ ipptool_test_t *data) /* I - Test data */
+{
+ char token[256], /* Token string */
+ name[1024], /* Name string */
+ temp[1024], /* Temporary string */
+ value[1024], /* Value string */
+ *ptr; /* Pointer into value */
+
+
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing printer URI on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (strcmp(temp, "{"))
+ {
+ // Got a printer URI so copy it...
+ data->monitor_uri = strdup(temp);
+
+ // Then see if we have an opening brace...
+ if (!_ippFileReadToken(f, temp, sizeof(temp)) || strcmp(temp, "{"))
+ {
+ print_fatal_error(data, "Missing opening brace on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else
+ {
+ // Use the default printer URI...
+ data->monitor_uri = strdup(data->vars->uri);
+ }
+
+ // Loop until we get a closing brace...
+ while (_ippFileReadToken(f, token, sizeof(token)))
+ {
+ if (_cups_strcasecmp(token, "COUNT") &&
+ _cups_strcasecmp(token, "DEFINE-MATCH") &&
+ _cups_strcasecmp(token, "DEFINE-NO-MATCH") &&
+ _cups_strcasecmp(token, "DEFINE-VALUE") &&
+ _cups_strcasecmp(token, "IF-DEFINED") &&
+ _cups_strcasecmp(token, "IF-NOT-DEFINED") &&
+ _cups_strcasecmp(token, "IN-GROUP") &&
+ _cups_strcasecmp(token, "OF-TYPE") &&
+ _cups_strcasecmp(token, "WITH-DISTINCT-VALUES") &&
+ _cups_strcasecmp(token, "WITH-VALUE"))
+ data->last_expect = NULL;
+
+ if (!strcmp(token, "}"))
+ return (1);
+ else if (!_cups_strcasecmp(token, "EXPECT"))
+ {
+ /*
+ * Expected attributes...
+ */
+
+ if (data->num_monitor_expects >= (int)(sizeof(data->monitor_expects) / sizeof(data->monitor_expects[0])))
+ {
+ print_fatal_error(data, "Too many EXPECT's on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (!_ippFileReadToken(f, name, sizeof(name)))
+ {
+ print_fatal_error(data, "Missing EXPECT name on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ data->last_expect = data->monitor_expects + data->num_monitor_expects;
+ data->num_monitor_expects ++;
+
+ memset(data->last_expect, 0, sizeof(ipptool_expect_t));
+ data->last_expect->repeat_limit = 1000;
+
+ if (name[0] == '!')
+ {
+ data->last_expect->not_expect = 1;
+ data->last_expect->name = strdup(name + 1);
+ }
+ else if (name[0] == '?')
+ {
+ data->last_expect->optional = 1;
+ data->last_expect->name = strdup(name + 1);
+ }
+ else
+ data->last_expect->name = strdup(name);
+ }
+ else if (!_cups_strcasecmp(token, "COUNT"))
+ {
+ int count; /* Count value */
+
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing COUNT number on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if ((count = atoi(temp)) <= 0)
+ {
+ print_fatal_error(data, "Bad COUNT \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->count = count;
+ }
+ else
+ {
+ print_fatal_error(data, "COUNT without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "DEFINE-MATCH"))
+ {
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing DEFINE-MATCH variable on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->define_match = strdup(temp);
+ }
+ else
+ {
+ print_fatal_error(data, "DEFINE-MATCH without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "DEFINE-NO-MATCH"))
+ {
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing DEFINE-NO-MATCH variable on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->define_no_match = strdup(temp);
+ }
+ else
+ {
+ print_fatal_error(data, "DEFINE-NO-MATCH without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "DEFINE-VALUE"))
+ {
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing DEFINE-VALUE variable on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->define_value = strdup(temp);
+ }
+ else
+ {
+ print_fatal_error(data, "DEFINE-VALUE without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "DELAY"))
+ {
+ /*
+ * Delay before operation...
+ */
+
+ double dval; /* Delay value */
+
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing DELAY value on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ _ippVarsExpand(data->vars, value, temp, sizeof(value));
+
+ if ((dval = _cupsStrScand(value, &ptr, localeconv())) < 0.0 || (*ptr && *ptr != ','))
+ {
+ print_fatal_error(data, "Bad DELAY value \"%s\" on line %d of \"%s\".", value, f->linenum, f->filename);
+ return (0);
+ }
+
+ data->monitor_delay = (useconds_t)(1000000.0 * dval);
+
+ if (*ptr == ',')
+ {
+ if ((dval = _cupsStrScand(ptr + 1, &ptr, localeconv())) <= 0.0 || *ptr)
+ {
+ print_fatal_error(data, "Bad DELAY value \"%s\" on line %d of \"%s\".", value, f->linenum, f->filename);
+ return (0);
+ }
+
+ data->monitor_interval = (useconds_t)(1000000.0 * dval);
+ }
+ else
+ data->monitor_interval = data->monitor_delay;
+ }
+ else if (!_cups_strcasecmp(token, "OF-TYPE"))
+ {
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing OF-TYPE value tag(s) on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->of_type = strdup(temp);
+ }
+ else
+ {
+ print_fatal_error(data, "OF-TYPE without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "IN-GROUP"))
+ {
+ ipp_tag_t in_group; /* IN-GROUP value */
+
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing IN-GROUP group tag on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if ((in_group = ippTagValue(temp)) == IPP_TAG_ZERO || in_group >= IPP_TAG_UNSUPPORTED_VALUE)
+ {
+ print_fatal_error(data, "Bad IN-GROUP group tag \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
+ return (0);
+ }
+ else if (data->last_expect)
+ {
+ data->last_expect->in_group = in_group;
+ }
+ else
+ {
+ print_fatal_error(data, "IN-GROUP without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "IF-DEFINED"))
+ {
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing IF-DEFINED name on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->if_defined = strdup(temp);
+ }
+ else
+ {
+ print_fatal_error(data, "IF-DEFINED without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "IF-NOT-DEFINED"))
+ {
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing IF-NOT-DEFINED name on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ if (data->last_expect)
+ {
+ data->last_expect->if_not_defined = strdup(temp);
+ }
+ else
+ {
+ print_fatal_error(data, "IF-NOT-DEFINED without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "WITH-DISTINCT-VALUES"))
+ {
+ if (data->last_expect)
+ {
+ data->last_expect->with_distinct = 1;
+ }
+ else
+ {
+ print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
+ return (0);
+ }
+ }
+ else if (!_cups_strcasecmp(token, "WITH-VALUE"))
+ {
+ off_t lastpos; /* Last file position */
+ int lastline; /* Last line number */
+
+ if (!_ippFileReadToken(f, temp, sizeof(temp)))
+ {
+ print_fatal_error(data, "Missing %s value on line %d of \"%s\".", token, f->linenum, f->filename);
+ return (0);
+ }
+
+ /*
+ * Read additional comma-delimited values - needed since legacy test files
+ * will have unquoted WITH-VALUE values with commas...
+ */
+
+ ptr = temp + strlen(temp);
+
+ for (;;)
+ {
+ lastpos = cupsFileTell(f->fp);
+ lastline = f->linenum;
+ ptr += strlen(ptr);
+
+ if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
+ break;
+
+ if (!strcmp(ptr, ","))
+ {
+ /*
+ * Append a value...
+ */
+
+ ptr += strlen(ptr);
+
+ if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
+ break;
+ }
+ else
+ {
+ /*
+ * Not another value, stop here...
+ */
+
+ cupsFileSeek(f->fp, lastpos);
+ f->linenum = lastline;
+ *ptr = '\0';
+ break;
+ }
+ }
+
+ if (data->last_expect)
+ {
+ /*
+ * Expand any variables in the value and then save it.
+ */
+
+ _ippVarsExpand(data->vars, value, temp, sizeof(value));
+
+ ptr = value + strlen(value) - 1;
+
+ if (value[0] == '/' && ptr > value && *ptr == '/')
+ {
+ /*
+ * WITH-VALUE is a POSIX extended regular expression.
+ */
+
+ data->last_expect->with_value = calloc(1, (size_t)(ptr - value));
+ data->last_expect->with_flags |= IPPTOOL_WITH_REGEX;
+
+ if (data->last_expect->with_value)
+ memcpy(data->last_expect->with_value, value + 1, (size_t)(ptr - value - 1));
+ }
+ else
+ {
+ /*
+ * WITH-VALUE is a literal value...
+ */
+
+ for (ptr = value; *ptr; ptr ++)
+ {
+ if (*ptr == '\\' && ptr[1])
+ {
+ /*
+ * Remove \ from \foo...
+ */
+
+ _cups_strcpy(ptr, ptr + 1);
+ }
+ }
+
+ data->last_expect->with_value = strdup(value);
+ data->last_expect->with_flags |= IPPTOOL_WITH_LITERAL;
+ }
+ }
+ else
+ {
+ print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
+ return (0);
+ }
+ }
+ }
+
+ print_fatal_error(data, "Missing closing brace on line %d of \"%s\".", f->linenum, f->filename);
+
+ return (0);
+}
+
+
+/*
* 'pause_message()' - Display the message and pause until the user presses a key.
*/
@@ -2282,7 +3163,7 @@ pause_message(const char *message) /* I - Message */
static void
print_attr(cups_file_t *outfile, /* I - Output file */
- _cups_output_t output, /* I - Output format */
+ ipptool_output_t output, /* I - Output format */
ipp_attribute_t *attr, /* I - Attribute to print */
ipp_tag_t *group) /* IO - Current group */
{
@@ -2291,7 +3172,7 @@ print_attr(cups_file_t *outfile, /* I - Output file */
ipp_attribute_t *colattr; /* Collection attribute */
- if (output == _CUPS_OUTPUT_PLIST)
+ if (output == IPPTOOL_OUTPUT_PLIST)
{
if (!ippGetName(attr) || (group && *group != ippGetGroupTag(attr)))
{
@@ -2417,7 +3298,7 @@ print_attr(cups_file_t *outfile, /* I - Output file */
{
char buffer[131072]; /* Value buffer */
- if (output == _CUPS_OUTPUT_TEST)
+ if (output == IPPTOOL_OUTPUT_TEST)
{
if (!ippGetName(attr))
{
@@ -2440,7 +3321,7 @@ print_attr(cups_file_t *outfile, /* I - Output file */
static void
print_csv(
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
ipp_t *ipp, /* I - Response message */
ipp_attribute_t *attr, /* I - First attribute for line */
int num_displayed, /* I - Number of attributes to display */
@@ -2530,7 +3411,7 @@ print_csv(
static void
print_fatal_error(
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
const char *s, /* I - Printf-style format string */
...) /* I - Additional arguments as needed */
{
@@ -2550,7 +3431,7 @@ print_fatal_error(
* Then output it...
*/
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
{
print_xml_header(data);
print_xml_trailer(data, 0, buffer);
@@ -2566,7 +3447,7 @@ print_fatal_error(
static void
print_ippserver_attr(
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
ipp_attribute_t *attr, /* I - Attribute to print */
int indent) /* I - Indentation level */
{
@@ -2677,7 +3558,7 @@ print_ippserver_attr(
static void
print_ippserver_string(
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
const char *s, /* I - String to print */
size_t len) /* I - Length of string */
{
@@ -2701,7 +3582,7 @@ print_ippserver_string(
static void
print_line(
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
ipp_t *ipp, /* I - Response message */
ipp_attribute_t *attr, /* I - First attribute for line */
int num_displayed, /* I - Number of attributes to display */
@@ -2787,7 +3668,7 @@ print_line(
*/
static void
-print_xml_header(_cups_testdata_t *data)/* I - Test data */
+print_xml_header(ipptool_test_t *data)/* I - Test data */
{
if (!data->xml_header)
{
@@ -2798,7 +3679,7 @@ print_xml_header(_cups_testdata_t *data)/* I - Test data */
cupsFilePuts(data->outfile, "<key>ipptoolVersion</key>\n");
cupsFilePuts(data->outfile, "<string>" CUPS_SVERSION "</string>\n");
cupsFilePuts(data->outfile, "<key>Transfer</key>\n");
- cupsFilePrintf(data->outfile, "<string>%s</string>\n", data->transfer == _CUPS_TRANSFER_AUTO ? "auto" : data->transfer == _CUPS_TRANSFER_CHUNKED ? "chunked" : "length");
+ cupsFilePrintf(data->outfile, "<string>%s</string>\n", data->transfer == IPPTOOL_TRANSFER_AUTO ? "auto" : data->transfer == IPPTOOL_TRANSFER_CHUNKED ? "chunked" : "length");
cupsFilePuts(data->outfile, "<key>Tests</key>\n");
cupsFilePuts(data->outfile, "<array>\n");
@@ -2907,7 +3788,7 @@ print_xml_string(cups_file_t *outfile, /* I - Test data */
static void
print_xml_trailer(
- _cups_testdata_t *data, /* I - Test data */
+ ipptool_test_t *data, /* I - Test data */
int success, /* I - 1 on success, 0 on failure */
const char *message) /* I - Error message or NULL */
{
@@ -2989,10 +3870,10 @@ timeout_cb(http_t *http, /* I - Connection to server */
*/
static int /* O - 1 to continue, 0 to stop */
-token_cb(_ipp_file_t *f, /* I - IPP file data */
- _ipp_vars_t *vars, /* I - IPP variables */
- _cups_testdata_t *data, /* I - Test data */
- const char *token) /* I - Current token */
+token_cb(_ipp_file_t *f, /* I - IPP file data */
+ _ipp_vars_t *vars, /* I - IPP variables */
+ ipptool_test_t *data, /* I - Test data */
+ const char *token) /* I - Current token */
{
char name[1024], /* Name string */
temp[1024], /* Temporary string */
@@ -3030,6 +3911,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") &&
_cups_strcasecmp(token, "WITH-ALL-RESOURCES") &&
_cups_strcasecmp(token, "WITH-ALL-SCHEMES") &&
+ _cups_strcasecmp(token, "WITH-DISTINCT-VALUES") &&
_cups_strcasecmp(token, "WITH-HOSTNAME") &&
_cups_strcasecmp(token, "WITH-RESOURCE") &&
_cups_strcasecmp(token, "WITH-SCHEME") &&
@@ -3048,7 +3930,17 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
if (!strcmp(token, "}"))
{
- return (do_test(f, vars, data));
+ return (do_test(f, data));
+ }
+ else if (!strcmp(token, "MONITOR-PRINTER-STATE"))
+ {
+ if (data->monitor_uri)
+ {
+ print_fatal_error(data, "Extra MONITOR-PRINTER-STATE seen on line %d of \"%s\".", f->linenum, f->filename);
+ return (0);
+ }
+
+ return (parse_monitor_printer_state(f, data));
}
else if (!strcmp(token, "COMPRESSION"))
{
@@ -3132,7 +4024,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
if (_ippFileReadToken(f, temp, sizeof(temp)))
{
- pause_message(temp);
+ strlcpy(data->pause, temp, sizeof(data->pause));
}
else
{
@@ -3151,11 +4043,11 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
{
if (isdigit(temp[0] & 255))
{
- data->request_id = atoi(temp);
+ data->request_id = atoi(temp) - 1;
}
else if (!_cups_strcasecmp(temp, "random"))
{
- data->request_id = (CUPS_RAND() % 1000) * 137 + 1;
+ data->request_id = (CUPS_RAND() % 1000) * 137;
}
else
{
@@ -3270,15 +4162,15 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
{
if (!strcmp(temp, "auto"))
{
- data->transfer = _CUPS_TRANSFER_AUTO;
+ data->transfer = IPPTOOL_TRANSFER_AUTO;
}
else if (!strcmp(temp, "chunked"))
{
- data->transfer = _CUPS_TRANSFER_CHUNKED;
+ data->transfer = IPPTOOL_TRANSFER_CHUNKED;
}
else if (!strcmp(temp, "length"))
{
- data->transfer = _CUPS_TRANSFER_LENGTH;
+ data->transfer = IPPTOOL_TRANSFER_LENGTH;
}
else
{
@@ -3509,7 +4401,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
data->last_expect = data->expects + data->num_expects;
data->num_expects ++;
- memset(data->last_expect, 0, sizeof(_cups_expect_t));
+ memset(data->last_expect, 0, sizeof(ipptool_expect_t));
data->last_expect->repeat_limit = 1000;
data->last_expect->expect_all = expect_all;
@@ -3778,6 +4670,18 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
return (0);
}
}
+ else if (!_cups_strcasecmp(token, "WITH-DISTINCT-VALUES"))
+ {
+ if (data->last_expect)
+ {
+ data->last_expect->with_distinct = 1;
+ }
+ else
+ {
+ print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
+ return (0);
+ }
+ }
else if (!_cups_strcasecmp(token, "WITH-ALL-VALUES") ||
!_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") ||
!_cups_strcasecmp(token, "WITH-ALL-RESOURCES") ||
@@ -3793,14 +4697,14 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
if (data->last_expect)
{
if (!_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") || !_cups_strcasecmp(token, "WITH-HOSTNAME"))
- data->last_expect->with_flags = _CUPS_WITH_HOSTNAME;
+ data->last_expect->with_flags = IPPTOOL_WITH_HOSTNAME;
else if (!_cups_strcasecmp(token, "WITH-ALL-RESOURCES") || !_cups_strcasecmp(token, "WITH-RESOURCE"))
- data->last_expect->with_flags = _CUPS_WITH_RESOURCE;
+ data->last_expect->with_flags = IPPTOOL_WITH_RESOURCE;
else if (!_cups_strcasecmp(token, "WITH-ALL-SCHEMES") || !_cups_strcasecmp(token, "WITH-SCHEME"))
- data->last_expect->with_flags = _CUPS_WITH_SCHEME;
+ data->last_expect->with_flags = IPPTOOL_WITH_SCHEME;
if (!_cups_strncasecmp(token, "WITH-ALL-", 9))
- data->last_expect->with_flags |= _CUPS_WITH_ALL;
+ data->last_expect->with_flags |= IPPTOOL_WITH_ALL;
}
if (!_ippFileReadToken(f, temp, sizeof(temp)))
@@ -3866,7 +4770,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
*/
data->last_expect->with_value = calloc(1, (size_t)(ptr - value));
- data->last_expect->with_flags |= _CUPS_WITH_REGEX;
+ data->last_expect->with_flags |= IPPTOOL_WITH_REGEX;
if (data->last_expect->with_value)
memcpy(data->last_expect->with_value, value + 1, (size_t)(ptr - value - 1));
@@ -3890,7 +4794,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
}
data->last_expect->with_value = strdup(value);
- data->last_expect->with_flags |= _CUPS_WITH_LITERAL;
+ data->last_expect->with_flags |= IPPTOOL_WITH_LITERAL;
}
}
else
@@ -3916,7 +4820,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
_ippVarsExpand(vars, value, temp, sizeof(value));
data->last_expect->with_value_from = strdup(value);
- data->last_expect->with_flags = _CUPS_WITH_LITERAL;
+ data->last_expect->with_flags = IPPTOOL_WITH_LITERAL;
}
else
{
@@ -3965,10 +4869,10 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
if (data->show_header)
{
- if (data->output == _CUPS_OUTPUT_PLIST)
+ if (data->output == IPPTOOL_OUTPUT_PLIST)
print_xml_header(data);
- if (data->output == _CUPS_OUTPUT_TEST || (data->output == _CUPS_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
+ if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
cupsFilePrintf(cupsFileStdout(), "\"%s\":\n", f->filename);
data->show_header = 0;
@@ -3984,8 +4888,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
if ((ptr = strrchr(data->name, '.')) != NULL)
*ptr = '\0';
data->repeat_interval = 5000000;
- data->request_id ++;
- strlcpy(data->resource, vars->resource, sizeof(data->resource));
+ strlcpy(data->resource, data->vars->resource, sizeof(data->resource));
data->skip_previous = 0;
data->skip_test = 0;
data->num_statuses = 0;
@@ -3994,6 +4897,12 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
data->transfer = data->def_transfer;
data->version = data->def_version;
+ free(data->monitor_uri);
+ data->monitor_uri = NULL;
+ data->monitor_delay = 0;
+ data->monitor_interval = 5000000;
+ data->num_monitor_expects = 0;
+
_ippVarsSet(vars, "date-current", iso_date(ippTimeToDate(time(NULL))));
f->attrs = ippNew();
@@ -4085,7 +4994,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
* Map the filename to and then run the tests...
*/
- _cups_testdata_t inc_data; /* Data for included file */
+ ipptool_test_t inc_data; /* Data for included file */
char filename[1024]; /* Mapped filename */
memcpy(&inc_data, data, sizeof(inc_data));
@@ -4094,7 +5003,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
inc_data.prev_pass = 1;
inc_data.show_header = 1;
- if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), vars, &inc_data) && data->stop_after_include_error)
+ if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), &inc_data) && data->stop_after_include_error)
{
data->pass = data->prev_pass = 0;
return (0);
@@ -4121,7 +5030,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
* Map the filename to and then run the tests...
*/
- _cups_testdata_t inc_data; /* Data for included file */
+ ipptool_test_t inc_data; /* Data for included file */
char filename[1024]; /* Mapped filename */
memcpy(&inc_data, data, sizeof(inc_data));
@@ -4130,7 +5039,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
inc_data.prev_pass = 1;
inc_data.show_header = 1;
- if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), vars, &inc_data) && data->stop_after_include_error)
+ if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), &inc_data) && data->stop_after_include_error)
{
data->pass = data->prev_pass = 0;
return (0);
@@ -4157,7 +5066,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
* Map the filename to and then run the tests...
*/
- _cups_testdata_t inc_data; /* Data for included file */
+ ipptool_test_t inc_data; /* Data for included file */
char filename[1024]; /* Mapped filename */
memcpy(&inc_data, data, sizeof(inc_data));
@@ -4166,7 +5075,7 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
inc_data.prev_pass = 1;
inc_data.show_header = 1;
- if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), vars, &inc_data) && data->stop_after_include_error)
+ if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), &inc_data) && data->stop_after_include_error)
{
data->pass = data->prev_pass = 0;
return (0);
@@ -4242,11 +5151,11 @@ token_cb(_ipp_file_t *f, /* I - IPP file data */
if (_ippFileReadToken(f, temp, sizeof(temp)))
{
if (!strcmp(temp, "auto"))
- data->def_transfer = _CUPS_TRANSFER_AUTO;
+ data->def_transfer = IPPTOOL_TRANSFER_AUTO;
else if (!strcmp(temp, "chunked"))
- data->def_transfer = _CUPS_TRANSFER_CHUNKED;
+ data->def_transfer = IPPTOOL_TRANSFER_CHUNKED;
else if (!strcmp(temp, "length"))
- data->def_transfer = _CUPS_TRANSFER_LENGTH;
+ data->def_transfer = IPPTOOL_TRANSFER_LENGTH;
else
{
print_fatal_error(data, "Bad TRANSFER value \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
@@ -4316,6 +5225,7 @@ usage(void)
_cupsLangPuts(stderr, _("-I Ignore errors"));
_cupsLangPuts(stderr, _("-L Send requests using content-length"));
_cupsLangPuts(stderr, _("-P filename.plist Produce XML plist to a file and test report to standard output"));
+ _cupsLangPuts(stderr, _("-R Repeat tests on server-error-busy"));
_cupsLangPuts(stderr, _("-S Test with encryption using HTTPS"));
_cupsLangPuts(stderr, _("-T seconds Set the receive/send timeout in seconds"));
_cupsLangPuts(stderr, _("-V version Set default IPP version"));
@@ -4336,29 +5246,130 @@ usage(void)
/*
+ * 'with_distinct_values()' - Verify that an attribute contains unique values.
+ */
+
+static int // O - 1 if distinct, 0 if duplicate
+with_distinct_values(
+ cups_array_t *errors, // I - Array of errors
+ ipp_attribute_t *attr) // I - Attribute to test
+{
+ int i, // Looping var
+ count; // Number of values
+ ipp_tag_t value_tag; // Value syntax
+ const char *value; // Current value
+ char buffer[8192]; // Temporary buffer
+ cups_array_t *values; // Array of values as strings
+
+
+ // If there is only 1 value, it must be distinct
+ if ((count = ippGetCount(attr)) == 1)
+ return (1);
+
+ // Only check integers, enums, rangeOfInteger, resolution, and nul-terminated
+ // strings...
+ switch (value_tag = ippGetValueTag(attr))
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ case IPP_TAG_RANGE :
+ case IPP_TAG_RESOLUTION :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ break;
+
+ default :
+ add_stringf(errors, "WITH-DISTINCT-VALUES %s not supported for 1setOf %s", ippGetName(attr), ippTagString(value_tag));
+ return (0);
+ }
+
+ // Collect values and determine they are all unique...
+ values = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+
+ for (i = 0; i < count; i ++)
+ {
+ switch (value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ snprintf(buffer, sizeof(buffer), "%d", ippGetInteger(attr, i));
+ value = buffer;
+ break;
+ case IPP_TAG_RANGE :
+ {
+ int upper, lower = ippGetRange(attr, i, &upper);
+ // Range values
+
+ snprintf(buffer, sizeof(buffer), "%d-%d", lower, upper);
+ value = buffer;
+ }
+ break;
+ case IPP_TAG_RESOLUTION :
+ {
+ ipp_res_t units; // Resolution units
+ int yres, xres = ippGetResolution(attr, i, &yres, &units);
+ // Resolution values
+
+ if (xres == yres)
+ snprintf(buffer, sizeof(buffer), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
+ else
+ snprintf(buffer, sizeof(buffer), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
+ value = buffer;
+ }
+ break;
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ value = ippGetString(attr, i, NULL);
+ break;
+ default : // Should never happen
+ value = "unsupported";
+ break;
+ }
+
+ if (cupsArrayFind(values, (void *)value))
+ add_stringf(errors, "DUPLICATE: %s=%s", ippGetName(attr), value);
+ else
+ cupsArrayAdd(values, (void *)value);
+ }
+
+ // Cleanup...
+ i = cupsArrayCount(values) == count;
+ cupsArrayDelete(values);
+
+ return (i);
+}
+
+
+/*
* 'with_flags_string()' - Return the "WITH-xxx" predicate that corresponds to
- the flags.
+ * the flags.
*/
static const char * /* O - WITH-xxx string */
with_flags_string(int flags) /* I - WITH flags */
{
- if (flags & _CUPS_WITH_ALL)
+ if (flags & IPPTOOL_WITH_ALL)
{
- if (flags & _CUPS_WITH_HOSTNAME)
+ if (flags & IPPTOOL_WITH_HOSTNAME)
return ("WITH-ALL-HOSTNAMES");
- else if (flags & _CUPS_WITH_RESOURCE)
+ else if (flags & IPPTOOL_WITH_RESOURCE)
return ("WITH-ALL-RESOURCES");
- else if (flags & _CUPS_WITH_SCHEME)
+ else if (flags & IPPTOOL_WITH_SCHEME)
return ("WITH-ALL-SCHEMES");
else
return ("WITH-ALL-VALUES");
}
- else if (flags & _CUPS_WITH_HOSTNAME)
+ else if (flags & IPPTOOL_WITH_HOSTNAME)
return ("WITH-HOSTNAME");
- else if (flags & _CUPS_WITH_RESOURCE)
+ else if (flags & IPPTOOL_WITH_RESOURCE)
return ("WITH-RESOURCE");
- else if (flags & _CUPS_WITH_SCHEME)
+ else if (flags & IPPTOOL_WITH_SCHEME)
return ("WITH-SCHEME");
else
return ("WITH-VALUE");
@@ -4370,7 +5381,7 @@ with_flags_string(int flags) /* I - WITH flags */
*/
static int /* O - 1 on match, 0 on non-match */
-with_value(_cups_testdata_t *data, /* I - Test data */
+with_value(ipptool_test_t *data, /* I - Test data */
cups_array_t *errors, /* I - Errors array */
char *value, /* I - Value string */
int flags, /* I - Flags for match */
@@ -4387,7 +5398,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
*matchbuf = '\0';
- match = (flags & _CUPS_WITH_ALL) ? 1 : 0;
+ match = (flags & IPPTOOL_WITH_ALL) ? 1 : 0;
/*
* NULL matches everything.
@@ -4450,7 +5461,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
}
}
- if (flags & _CUPS_WITH_ALL)
+ if (flags & IPPTOOL_WITH_ALL)
{
if (!valmatch)
{
@@ -4517,7 +5528,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
}
}
- if (flags & _CUPS_WITH_ALL)
+ if (flags & IPPTOOL_WITH_ALL)
{
if (!valmatch)
{
@@ -4552,13 +5563,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
strlcpy(matchbuf, value, matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;
@@ -4589,13 +5600,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
strlcpy(matchbuf, value, matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;
@@ -4635,7 +5646,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
case IPP_TAG_TEXTLANG :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
- if (flags & _CUPS_WITH_REGEX)
+ if (flags & IPPTOOL_WITH_REGEX)
{
/*
* Value is an extended, case-sensitive POSIX regular expression...
@@ -4663,13 +5674,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
strlcpy(matchbuf, get_string(attr, i, flags, temp, sizeof(temp)), matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;
@@ -4678,7 +5689,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
regfree(&re);
}
- else if (ippGetValueTag(attr) == IPP_TAG_URI && !(flags & (_CUPS_WITH_SCHEME | _CUPS_WITH_HOSTNAME | _CUPS_WITH_RESOURCE)))
+ else if (ippGetValueTag(attr) == IPP_TAG_URI && !(flags & (IPPTOOL_WITH_SCHEME | IPPTOOL_WITH_HOSTNAME | IPPTOOL_WITH_RESOURCE)))
{
/*
* Value is a literal URI string, see if the value(s) match...
@@ -4691,13 +5702,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
strlcpy(matchbuf, get_string(attr, i, flags, temp, sizeof(temp)), matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;
@@ -4721,7 +5732,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
* Some URI components are case-sensitive, some not...
*/
- if (flags & (_CUPS_WITH_SCHEME | _CUPS_WITH_HOSTNAME))
+ if (flags & (IPPTOOL_WITH_SCHEME | IPPTOOL_WITH_HOSTNAME))
result = _cups_strcasecmp(value, get_string(attr, i, flags, temp, sizeof(temp)));
else
result = strcmp(value, get_string(attr, i, flags, temp, sizeof(temp)));
@@ -4756,13 +5767,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
strlcpy(matchbuf, get_string(attr, i, flags, temp, sizeof(temp)), matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;
@@ -4778,7 +5789,7 @@ with_value(_cups_testdata_t *data, /* I - Test data */
break;
case IPP_TAG_STRING :
- if (flags & _CUPS_WITH_REGEX)
+ if (flags & IPPTOOL_WITH_REGEX)
{
/*
* Value is an extended, case-sensitive POSIX regular expression...
@@ -4815,13 +5826,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
strlcpy(matchbuf, temp, matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;
@@ -4912,13 +5923,13 @@ with_value(_cups_testdata_t *data, /* I - Test data */
if (!matchbuf[0])
copy_hex_string(matchbuf, adata, adatalen, matchlen);
- if (!(flags & _CUPS_WITH_ALL))
+ if (!(flags & IPPTOOL_WITH_ALL))
{
match = 1;
break;
}
}
- else if (flags & _CUPS_WITH_ALL)
+ else if (flags & IPPTOOL_WITH_ALL)
{
match = 0;
break;