*
* ipptool command for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* which should have been included with this file. If this file is
* file is missing or damaged, see the license at "http://www.cups.org/".
*
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
* Contents:
*
* main() - Parse options and do tests.
* print_xml_string() - Print an XML string with escaping.
* print_xml_trailer() - Print the XML trailer with success/fail value.
* set_variable() - Set a variable value.
+ * sigterm_handler() - Handle SIGINT and SIGTERM.
+ * timeout_cb() - Handle HTTP timeouts.
* usage() - Show program usage.
* validate_attr() - Determine whether an attribute is valid.
* with_value() - Test a WITH-VALUE predicate.
#include <cups/cups-private.h>
#include <cups/file-private.h>
#include <regex.h>
-
+#include <sys/stat.h>
+#ifndef WIN32
+# include <signal.h>
+#endif /* WIN32 */
#ifndef O_BINARY
# define O_BINARY 0
#endif /* !O_BINARY */
*define_match, /* Variable to define on match */
*define_no_match, /* Variable to define on no-match */
*define_value; /* Variable to define with value */
- int with_regex, /* WITH-VALUE is a regular expression */
+ int repeat_match, /* Repeat test on match */
+ repeat_no_match, /* Repeat test on no match */
+ with_regex, /* WITH-VALUE is a regular expression */
count; /* Expected count if > 0 */
ipp_tag_t in_group; /* IN-GROUP value */
} _cups_expect_t;
ipp_status_t status; /* Expected status code */
char *if_defined, /* Only if variable is defined */
*if_not_defined; /* Only if variable is not defined */
+ int repeat_match, /* Repeat the test when it does not match */
+ repeat_no_match; /* Repeat the test when it matches */
} _cups_status_t;
typedef struct _cups_var_s /**** Variable ****/
typedef struct _cups_vars_s /**** Set of variables ****/
{
- const char *uri, /* URI for printer */
- *filename; /* Filename */
- char scheme[64], /* Scheme from URI */
+ char *uri, /* URI for printer */
+ *filename, /* Filename */
+ scheme[64], /* Scheme from URI */
userpass[256], /* Username/password from URI */
hostname[256], /* Hostname from URI */
resource[1024]; /* Resource path from URI */
int port; /* Port number from URI */
http_encryption_t encryption; /* Encryption for connection? */
+ double timeout; /* Timeout for connection */
+ int family; /* Address family */
cups_array_t *vars; /* Array of variables */
} _cups_vars_t;
/* How to transfer requests */
_cups_output_t Output = _CUPS_OUTPUT_LIST;
/* Output mode */
-int IgnoreErrors = 0, /* Ignore errors? */
+int Cancel = 0, /* Cancel test? */
+ IgnoreErrors = 0, /* Ignore errors? */
Verbosity = 0, /* Show all attributes? */
Version = 11, /* Default IPP version */
- XMLHeader = 0; /* 1 if header is written */
+ XMLHeader = 0, /* 1 if header is written */
+ TestCount = 0, /* Number of tests run */
+ PassCount = 0, /* Number of passing tests */
+ FailCount = 0, /* Number of failing tests */
+ SkipCount = 0; /* Number of skipped tests */
char *Password = NULL; /* Password from URI */
const char * const URIStatusStrings[] = /* URI status strings */
{
static int compare_vars(_cups_var_t *a, _cups_var_t *b);
static int do_tests(_cups_vars_t *vars, const char *testfile);
static void expand_variables(_cups_vars_t *vars, char *dst, const char *src,
- size_t dstsize)
-#ifdef __GNUC__
-__attribute((nonnull(1,2,3)))
-#endif /* __GNUC__ */
-;
+ size_t dstsize) __attribute__((nonnull(1,2,3)));
static int expect_matches(_cups_expect_t *expect, ipp_tag_t value_tag);
static ipp_t *get_collection(_cups_vars_t *vars, FILE *fp, int *linenum);
static char *get_filename(const char *testfile, char *dst, const char *src,
static char *get_variable(_cups_vars_t *vars, const char *name);
static char *iso_date(ipp_uchar_t *date);
static const char *password_cb(const char *prompt);
-static void print_attr(ipp_attribute_t *attr);
+static void print_attr(ipp_attribute_t *attr, ipp_tag_t *group);
static void print_col(ipp_t *col);
static void print_csv(ipp_attribute_t *attr, int num_displayed,
char **displayed, size_t *widths);
static void print_fatal_error(const char *s, ...)
-#ifdef __GNUC__
-__attribute__ ((__format__ (__printf__, 1, 2)))
-#endif /* __GNUC__ */
-;
+ __attribute__ ((__format__ (__printf__, 1, 2)));
static void print_line(ipp_attribute_t *attr, int num_displayed,
char **displayed, size_t *widths);
static void print_test_error(const char *s, ...)
-#ifdef __GNUC__
-__attribute__ ((__format__ (__printf__, 1, 2)))
-#endif /* __GNUC__ */
-;
+ __attribute__ ((__format__ (__printf__, 1, 2)));
static void print_xml_header(void);
static void print_xml_string(const char *element, const char *s);
static void print_xml_trailer(int success, const char *message);
static void set_variable(_cups_vars_t *vars, const char *name,
const char *value);
-static void usage(void);
+#ifndef WIN32
+static void sigterm_handler(int sig);
+#endif /* WIN32 */
+static int timeout_cb(http_t *http, void *user_data);
+static void usage(void) __attribute__((noreturn));
static int validate_attr(ipp_attribute_t *attr, int print);
static int with_value(char *value, int regex, ipp_attribute_t *attr,
- int report);
+ int report, char *matchbuf, size_t matchlen);
/*
name[1024], /* Name/value buffer */
*value, /* Pointer to value */
filename[1024], /* Real filename */
- testname[1024]; /* Real test filename */
- const char *testfile; /* Test file to use */
- int interval, /* Test interval */
+ testname[1024], /* Real test filename */
+ uri[1024]; /* Copy of printer URI */
+ const char *ext, /* Extension on filename */
+ *testfile; /* Test file to use */
+ int interval, /* Test interval in microseconds */
repeat; /* Repeat count */
_cups_vars_t vars; /* Variables */
http_uri_status_t uri_status; /* URI separation status */
/* Global data */
+#ifndef WIN32
+ /*
+ * Catch SIGINT and SIGTERM...
+ */
+
+ signal(SIGINT, sigterm_handler);
+ signal(SIGTERM, sigterm_handler);
+#endif /* !WIN32 */
/*
* Initialize the locale and variables...
_cupsSetLocale(argv);
memset(&vars, 0, sizeof(vars));
- vars.vars = cupsArrayNew((cups_array_func_t)compare_vars, NULL);
+ vars.family = AF_UNSPEC;
+ vars.vars = cupsArrayNew((cups_array_func_t)compare_vars, NULL);
/*
* We need at least:
{
switch (*opt)
{
+ case '4' : /* Connect using IPv4 only */
+ vars.family = AF_INET;
+ break;
+
+#ifdef AF_INET6
+ case '6' : /* Connect using IPv6 only */
+ vars.family = AF_INET6;
+ break;
+#endif /* AF_INET6 */
+
case 'C' : /* Enable HTTP chunking */
Transfer = _CUPS_TRANSFER_CHUNKED;
break;
#ifdef HAVE_SSL
vars.encryption = HTTP_ENCRYPT_REQUIRED;
#else
- _cupsLangPrintf(stderr,
- _("%s: Sorry, no encryption support compiled in\n"),
+ _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
argv[0]);
#endif /* HAVE_SSL */
break;
#ifdef HAVE_SSL
vars.encryption = HTTP_ENCRYPT_ALWAYS;
#else
- _cupsLangPrintf(stderr,
- _("%s: Sorry, no encryption support compiled in\n"),
+ _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
argv[0]);
#endif /* HAVE_SSL */
break;
+ case 'T' : /* Set timeout */
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPuts(stderr,
+ _("ipptool: Missing timeout for \"-T\"."));
+ usage();
+ }
+
+ vars.timeout = _cupsStrScand(argv[i], NULL, localeconv());
+ break;
+
case 'V' : /* Set IPP version */
i ++;
if (i >= argc)
{
_cupsLangPuts(stderr,
- _("ipptool: Missing version for \"-V\".\n"));
+ _("ipptool: Missing version for \"-V\"."));
usage();
}
else
{
_cupsLangPrintf(stderr,
- _("ipptool: Bad version %s for \"-V\".\n"),
+ _("ipptool: Bad version %s for \"-V\"."),
argv[i]);
usage();
}
if (interval || repeat)
{
_cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are "
- "incompatible with -X\".\n"));
+ "incompatible with -X\"."));
usage();
}
break;
if (i >= argc)
{
_cupsLangPuts(stderr,
- _("ipptool: Missing name=value for \"-d\".\n"));
+ _("ipptool: Missing name=value for \"-d\"."));
usage();
}
if (i >= argc)
{
_cupsLangPuts(stderr,
- _("ipptool: Missing filename for \"-f\".\n"));
+ _("ipptool: Missing filename for \"-f\"."));
usage();
}
- if (access(argv[i], 0) && argv[i][0] != '/')
+ if (vars.filename)
+ free(vars.filename);
+
+ if (access(argv[i], 0))
+ {
+ /*
+ * Try filename.gz...
+ */
+
+ snprintf(filename, sizeof(filename), "%s.gz", argv[i]);
+ if (access(filename, 0) && filename[0] != '/')
+ {
+ snprintf(filename, sizeof(filename), "%s/ipptool/%s",
+ cg->cups_datadir, argv[i]);
+ if (access(filename, 0))
+ {
+ snprintf(filename, sizeof(filename), "%s/ipptool/%s.gz",
+ cg->cups_datadir, argv[i]);
+ if (access(filename, 0))
+ vars.filename = strdup(argv[i]);
+ }
+ else
+ vars.filename = strdup(filename);
+ }
+ else
+ vars.filename = strdup(filename);
+ }
+ else
+ vars.filename = strdup(argv[i]);
+
+ if ((ext = strrchr(vars.filename, '.')) != NULL)
{
- snprintf(filename, sizeof(filename), "%s/ipptool/%s",
- cg->cups_datadir, argv[i]);
- if (access(argv[i], 0))
- vars.filename = argv[i];
+ /*
+ * Guess the MIME media type based on the extension...
+ */
+
+ if (!_cups_strcasecmp(ext, ".gif"))
+ set_variable(&vars, "filetype", "image/gif");
+ else if (!_cups_strcasecmp(ext, ".htm") ||
+ !_cups_strcasecmp(ext, ".htm.gz") ||
+ !_cups_strcasecmp(ext, ".html") ||
+ !_cups_strcasecmp(ext, ".html.gz"))
+ set_variable(&vars, "filetype", "text/html");
+ else if (!_cups_strcasecmp(ext, ".jpg"))
+ set_variable(&vars, "filetype", "image/jpeg");
+ else if (!_cups_strcasecmp(ext, ".pdf"))
+ set_variable(&vars, "filetype", "application/pdf");
+ else if (!_cups_strcasecmp(ext, ".png"))
+ set_variable(&vars, "filetype", "image/png");
+ else if (!_cups_strcasecmp(ext, ".ps") ||
+ !_cups_strcasecmp(ext, ".ps.gz"))
+ set_variable(&vars, "filetype", "application/postscript");
+ else if (!_cups_strcasecmp(ext, ".ras") ||
+ !_cups_strcasecmp(ext, ".ras.gz"))
+ set_variable(&vars, "filetype", "image/pwg-raster");
+ else if (!_cups_strcasecmp(ext, ".txt") ||
+ !_cups_strcasecmp(ext, ".txt.gz"))
+ set_variable(&vars, "filetype", "text/plain");
+ else if (!_cups_strcasecmp(ext, ".xps"))
+ set_variable(&vars, "filetype", "application/openxps");
else
- vars.filename = filename;
+ set_variable(&vars, "filetype", "application/octet-stream");
}
else
- vars.filename = argv[i];
+ {
+ /*
+ * Use the "auto-type" MIME media type...
+ */
+
+ set_variable(&vars, "filetype", "application/octet-stream");
+ }
break;
case 'i' : /* Test every N seconds */
if (i >= argc)
{
_cupsLangPuts(stderr,
- _("ipptool: Missing seconds for \"-i\".\n"));
+ _("ipptool: Missing seconds for \"-i\"."));
usage();
}
else
- interval = atoi(argv[i]);
+ {
+ interval = (int)(_cupsStrScand(argv[i], NULL, localeconv()) *
+ 1000000.0);
+ if (interval <= 0)
+ {
+ _cupsLangPuts(stderr,
+ _("ipptool: Invalid seconds for \"-i\"."));
+ usage();
+ }
+ }
if (Output == _CUPS_OUTPUT_PLIST && interval)
{
_cupsLangPuts(stderr, _("ipptool: \"-i\" is incompatible with "
- "\"-X\".\n"));
+ "\"-X\"."));
usage();
}
break;
if (i >= argc)
{
_cupsLangPuts(stderr,
- _("ipptool: Missing count for \"-n\".\n"));
+ _("ipptool: Missing count for \"-n\"."));
usage();
}
else
if (Output == _CUPS_OUTPUT_PLIST && repeat)
{
_cupsLangPuts(stderr, _("ipptool: \"-n\" is incompatible with "
- "\"-X\".\n"));
+ "\"-X\"."));
usage();
}
break;
break;
default :
- _cupsLangPrintf(stderr, _("ipptool: Unknown option \"-%c\".\n"),
+ _cupsLangPrintf(stderr, _("ipptool: Unknown option \"-%c\"."),
*opt);
usage();
break;
if (vars.uri)
{
- _cupsLangPuts(stderr, _("ipptool: May only specify a single URI.\n"));
+ _cupsLangPuts(stderr, _("ipptool: May only specify a single URI."));
usage();
}
if (uri_status != HTTP_URI_OK)
{
- _cupsLangPrintf(stderr, _("ipptool: Bad URI - %s.\n"),
+ _cupsLangPrintf(stderr, _("ipptool: Bad URI - %s."),
URIStatusStrings[uri_status - HTTP_URI_OVERFLOW]);
return (1);
}
cupsSetPasswordCB(password_cb);
set_variable(&vars, "uriuser", vars.userpass);
}
+
+ httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), vars.scheme, NULL,
+ vars.hostname, vars.port, vars.resource);
+ vars.uri = uri;
}
else
{
if (Output == _CUPS_OUTPUT_PLIST)
print_xml_trailer(!status, NULL);
- else if (interval && repeat > 0)
+ else if (interval > 0 && repeat > 0)
{
while (repeat > 1)
{
- sleep(interval);
+ usleep(interval);
do_tests(&vars, testfile);
repeat --;
}
}
- else if (interval)
+ else if (interval > 0)
{
for (;;)
{
- sleep(interval);
+ usleep(interval);
do_tests(&vars, testfile);
}
}
+ else if (Output == _CUPS_OUTPUT_TEST && TestCount > 1)
+ {
+ /*
+ * Show a summary report if there were multiple tests...
+ */
+
+ printf("\nSummary: %d tests, %d passed, %d failed, %d skipped\n"
+ "Score: %d%%\n", TestCount, PassCount, FailCount, SkipCount,
+ 100 * (PassCount + SkipCount) / TestCount);
+ }
/*
* Exit...
compare_vars(_cups_var_t *a, /* I - First variable */
_cups_var_t *b) /* I - Second variable */
{
- return (strcasecmp(a->name, b->name));
+ return (_cups_strcasecmp(a->name, b->name));
}
request_id, /* Current request ID */
show_header = 1, /* Show the test header? */
ignore_errors, /* Ignore test failures? */
- skip_previous = 0; /* Skip on previous test failure? */
+ skip_previous = 0, /* Skip on previous test failure? */
+ repeat_test; /* Repeat a test? */
http_t *http = NULL; /* HTTP connection to server */
FILE *fp = NULL; /* Test file */
char resource[512], /* Resource for request */
token[1024], /* Token from file */
*tokenptr, /* Pointer into token */
- temp[1024]; /* Temporary string */
- ipp_t *request = NULL; /* IPP request */
- ipp_t *response = NULL; /* IPP response */
+ temp[1024], /* Temporary string */
+ buffer[8192]; /* Copy buffer */
+ ipp_t *request = NULL, /* IPP request */
+ *response = NULL; /* IPP response */
+ size_t length; /* Length of IPP request */
+ http_status_t status; /* HTTP status */
+ cups_file_t *reqfile; /* File to send */
+ ssize_t bytes; /* Bytes read/written */
char attr[128]; /* Attribute name */
ipp_op_t op; /* Operation */
ipp_tag_t group; /* Current group */
int num_displayed = 0; /* Number of displayed attributes */
char *displayed[200]; /* Displayed attributes */
size_t widths[200]; /* Width of columns */
+ cups_array_t *a; /* Duplicate attribute array */
/*
* Connect to the server...
*/
- if ((http = httpConnectEncrypt(vars->hostname, vars->port,
- vars->encryption)) == NULL)
+ if ((http = _httpCreate(vars->hostname, vars->port, NULL, vars->encryption,
+ vars->family)) == NULL)
+ {
+ print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
+ vars->port, cupsLastErrorString());
+ pass = 0;
+ goto test_exit;
+ }
+
+ if (httpReconnect(http))
{
print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
- vars->port, strerror(errno));
+ vars->port, cupsLastErrorString());
pass = 0;
goto test_exit;
}
+ if (vars->timeout > 0.0)
+ httpSetTimeout(http, vars->timeout, timeout_cb, NULL);
+
/*
* Loop on tests...
*/
linenum = 1;
request_id = (CUPS_RAND() % 1000) * 137 + 1;
- while (get_token(fp, token, sizeof(token), &linenum) != NULL)
+ while (!Cancel && get_token(fp, token, sizeof(token), &linenum) != NULL)
{
/*
* Expect an open brace...
continue;
}
+ else if (!strcmp(token, "DEFINE-DEFAULT"))
+ {
+ /*
+ * DEFINE-DEFAULT name value
+ */
+
+ if (get_token(fp, attr, sizeof(attr), &linenum) &&
+ get_token(fp, temp, sizeof(temp), &linenum))
+ {
+ expand_variables(vars, token, temp, sizeof(token));
+ if (!get_variable(vars, attr))
+ set_variable(vars, attr, token);
+ }
+ else
+ {
+ print_fatal_error("Missing DEFINE-DEFAULT name and/or value on line "
+ "%d.", linenum);
+ pass = 0;
+ goto test_exit;
+ }
+
+ continue;
+ }
else if (!strcmp(token, "IGNORE-ERRORS"))
{
/*
*/
if (get_token(fp, temp, sizeof(temp), &linenum) &&
- (!strcasecmp(temp, "yes") || !strcasecmp(temp, "no")))
+ (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
{
- IgnoreErrors = !strcasecmp(temp, "yes");
+ IgnoreErrors = !_cups_strcasecmp(temp, "yes");
}
else
{
show_header = 1;
continue;
}
+ else if (!strcmp(token, "INCLUDE-IF-DEFINED"))
+ {
+ /*
+ * INCLUDE-IF-DEFINED name "filename"
+ * INCLUDE-IF-DEFINED name <filename>
+ */
+
+ if (get_token(fp, attr, sizeof(attr), &linenum) &&
+ get_token(fp, temp, sizeof(temp), &linenum))
+ {
+ /*
+ * Map the filename to and then run the tests...
+ */
+
+ if (get_variable(vars, attr) &&
+ !do_tests(vars, get_filename(testfile, filename, temp,
+ sizeof(filename))))
+ {
+ pass = 0;
+
+ if (!IgnoreErrors)
+ goto test_exit;
+ }
+ }
+ else
+ {
+ print_fatal_error("Missing INCLUDE-IF-DEFINED name or filename on line "
+ "%d.", linenum);
+ pass = 0;
+ goto test_exit;
+ }
+
+ show_header = 1;
+ continue;
+ }
+ else if (!strcmp(token, "INCLUDE-IF-NOT-DEFINED"))
+ {
+ /*
+ * INCLUDE-IF-NOT-DEFINED name "filename"
+ * INCLUDE-IF-NOT-DEFINED name <filename>
+ */
+
+ if (get_token(fp, attr, sizeof(attr), &linenum) &&
+ get_token(fp, temp, sizeof(temp), &linenum))
+ {
+ /*
+ * Map the filename to and then run the tests...
+ */
+
+ if (!get_variable(vars, attr) &&
+ !do_tests(vars, get_filename(testfile, filename, temp,
+ sizeof(filename))))
+ {
+ pass = 0;
+
+ if (!IgnoreErrors)
+ goto test_exit;
+ }
+ }
+ else
+ {
+ print_fatal_error("Missing INCLUDE-IF-NOT-DEFINED name or filename on "
+ "line %d.", linenum);
+ pass = 0;
+ goto test_exit;
+ }
+
+ show_header = 1;
+ continue;
+ }
else if (!strcmp(token, "SKIP-IF-DEFINED"))
{
/*
}
else
{
- print_fatal_error("Missing SKIP-IF-DEFINED value on line %d.", linenum);
+ print_fatal_error("Missing SKIP-IF-DEFINED variable on line %d.",
+ linenum);
pass = 0;
goto test_exit;
}
}
else
{
- print_fatal_error("Missing SKIP-IF-NOT-DEFINED value on line %d.",
+ print_fatal_error("Missing SKIP-IF-NOT-DEFINED variable on line %d.",
linenum);
pass = 0;
goto test_exit;
last_expect = NULL;
last_status = NULL;
filename[0] = '\0';
+ skip_previous = 0;
skip_test = 0;
version = Version;
transfer = Transfer;
while (get_token(fp, token, sizeof(token), &linenum) != NULL)
{
- if (strcasecmp(token, "COUNT") &&
- strcasecmp(token, "DEFINE-MATCH") &&
- strcasecmp(token, "DEFINE-NO-MATCH") &&
- strcasecmp(token, "DEFINE-VALUE") &&
- strcasecmp(token, "IF-DEFINED") &&
- strcasecmp(token, "IF-NOT-DEFINED") &&
- strcasecmp(token, "IN-GROUP") &&
- strcasecmp(token, "OF-TYPE") &&
- strcasecmp(token, "SAME-COUNT-AS") &&
- strcasecmp(token, "WITH-VALUE"))
+ 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, "REPEAT-MATCH") &&
+ _cups_strcasecmp(token, "REPEAT-NO-MATCH") &&
+ _cups_strcasecmp(token, "SAME-COUNT-AS") &&
+ _cups_strcasecmp(token, "WITH-VALUE"))
last_expect = NULL;
- if (strcasecmp(token, "IF-DEFINED") &&
- strcasecmp(token, "IF-NOT-DEFINED"))
+ if (_cups_strcasecmp(token, "IF-DEFINED") &&
+ _cups_strcasecmp(token, "IF-NOT-DEFINED") &&
+ _cups_strcasecmp(token, "REPEAT-MATCH") &&
+ _cups_strcasecmp(token, "REPEAT-NO-MATCH"))
last_status = NULL;
if (!strcmp(token, "}"))
if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) +
(lastcol->num_values + 1) *
- sizeof(ipp_value_t))) == NULL)
+ sizeof(_ipp_value_t))) == NULL)
{
print_fatal_error("Unable to allocate memory on line %d.", linenum);
pass = 0;
*/
if (get_token(fp, temp, sizeof(temp), &linenum) &&
- (!strcasecmp(temp, "yes") || !strcasecmp(temp, "no")))
+ (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
{
- ignore_errors = !strcasecmp(temp, "yes");
+ ignore_errors = !_cups_strcasecmp(temp, "yes");
}
else
{
continue;
}
- else if (!strcasecmp(token, "NAME"))
+ else if (!_cups_strcasecmp(token, "NAME"))
{
/*
* Name of test...
{
if (isdigit(temp[0] & 255))
request_id = atoi(temp);
- else if (!strcasecmp(temp, "random"))
+ else if (!_cups_strcasecmp(temp, "random"))
request_id = (CUPS_RAND() % 1000) * 137 + 1;
else
{
*/
if (get_token(fp, temp, sizeof(temp), &linenum) &&
- (!strcasecmp(temp, "yes") || !strcasecmp(temp, "no")))
+ (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
{
- skip_previous = !strcasecmp(temp, "yes");
+ skip_previous = !_cups_strcasecmp(temp, "yes");
}
else
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "VERSION"))
+ else if (!_cups_strcasecmp(token, "VERSION"))
{
if (get_token(fp, temp, sizeof(temp), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "RESOURCE"))
+ else if (!_cups_strcasecmp(token, "RESOURCE"))
{
/*
* Resource name...
goto test_exit;
}
}
- else if (!strcasecmp(token, "OPERATION"))
+ else if (!_cups_strcasecmp(token, "OPERATION"))
{
/*
* Operation...
goto test_exit;
}
- if ((op = ippOpValue(token)) < 0 && (op = strtol(token, NULL, 0)) == 0)
+ if ((op = ippOpValue(token)) == (ipp_op_t)-1 &&
+ (op = strtol(token, NULL, 0)) == 0)
{
print_fatal_error("Bad OPERATION code \"%s\" on line %d.", token,
linenum);
goto test_exit;
}
}
- else if (!strcasecmp(token, "GROUP"))
+ else if (!_cups_strcasecmp(token, "GROUP"))
{
/*
* Attribute group...
group = value;
}
- else if (!strcasecmp(token, "DELAY"))
+ else if (!_cups_strcasecmp(token, "DELAY"))
{
/*
* Delay before operation...
*/
- int delay;
+ double delay;
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
- if ((delay = atoi(token)) <= 0)
+ if ((delay = _cupsStrScand(token, NULL, localeconv())) <= 0.0)
{
print_fatal_error("Bad DELAY value \"%s\" on line %d.", token,
linenum);
else
{
if (Output == _CUPS_OUTPUT_TEST)
- printf(" [%d second delay]\n", delay);
+ printf(" [%g second delay]\n", delay);
- sleep(delay);
+ usleep((int)(1000000.0 * delay));
}
}
- else if (!strcasecmp(token, "ATTR"))
+ else if (!_cups_strcasecmp(token, "ATTR"))
{
/*
* Attribute...
}
expand_variables(vars, token, temp, sizeof(token));
+ attrptr = NULL;
switch (value)
{
case IPP_TAG_BOOLEAN :
- if (!strcasecmp(token, "true"))
- ippAddBoolean(request, group, attr, 1);
+ if (!_cups_strcasecmp(token, "true"))
+ attrptr = ippAddBoolean(request, group, attr, 1);
else
- ippAddBoolean(request, group, attr, atoi(token));
+ attrptr = ippAddBoolean(request, group, attr, atoi(token));
break;
case IPP_TAG_INTEGER :
case IPP_TAG_ENUM :
- ippAddInteger(request, group, value, attr, atoi(token));
+ if (!strchr(token, ','))
+ attrptr = ippAddInteger(request, group, value, attr,
+ strtol(token, &tokenptr, 0));
+ else
+ {
+ int values[100], /* Values */
+ num_values = 1; /* Number of values */
+
+ values[0] = strtol(token, &tokenptr, 10);
+ while (tokenptr && *tokenptr &&
+ num_values < (int)(sizeof(values) / sizeof(values[0])))
+ {
+ if (*tokenptr == ',')
+ tokenptr ++;
+ else if (!isdigit(*tokenptr & 255) && *tokenptr != '-')
+ break;
+
+ values[num_values] = strtol(tokenptr, &tokenptr, 0);
+ num_values ++;
+ }
+
+ attrptr = ippAddIntegers(request, group, value, attr, num_values, values);
+ }
+
+ if (!tokenptr || *tokenptr)
+ {
+ print_fatal_error("Bad %s value \"%s\" on line %d.",
+ ippTagString(value), token, linenum);
+ pass = 0;
+ goto test_exit;
+ }
break;
case IPP_TAG_RESOLUTION :
}
if (ptr <= token || xres <= 0 || yres <= 0 || !ptr ||
- (strcasecmp(ptr, "dpi") && strcasecmp(ptr, "dpc") &&
- strcasecmp(ptr, "other")))
+ (_cups_strcasecmp(ptr, "dpi") && _cups_strcasecmp(ptr, "dpc") &&
+ _cups_strcasecmp(ptr, "other")))
{
print_fatal_error("Bad resolution value \"%s\" on line %d.",
token, linenum);
goto test_exit;
}
- if (!strcasecmp(ptr, "dpi"))
- ippAddResolution(request, group, attr, IPP_RES_PER_INCH,
- xres, yres);
- else if (!strcasecmp(ptr, "dpc"))
- ippAddResolution(request, group, attr, IPP_RES_PER_CM,
- xres, yres);
+ if (!_cups_strcasecmp(ptr, "dpi"))
+ attrptr = ippAddResolution(request, group, attr, IPP_RES_PER_INCH,
+ xres, yres);
+ else if (!_cups_strcasecmp(ptr, "dpc"))
+ attrptr = ippAddResolution(request, group, attr, IPP_RES_PER_CM,
+ xres, yres);
else
- ippAddResolution(request, group, attr, (ipp_res_t)0,
- xres, yres);
+ attrptr = ippAddResolution(request, group, attr, (ipp_res_t)0,
+ xres, yres);
}
break;
goto test_exit;
}
- ippAddRanges(request, group, attr, num_vals / 2, lowers,
- uppers);
+ attrptr = ippAddRanges(request, group, attr, num_vals / 2, lowers,
+ uppers);
}
break;
if (col)
{
- lastcol = ippAddCollection(request, group, attr, col);
+ attrptr = lastcol = ippAddCollection(request, group, attr, col);
ippDelete(col);
}
else
case IPP_TAG_LANGUAGE :
case IPP_TAG_MIMETYPE :
if (!strchr(token, ','))
- ippAddString(request, group, value, attr, NULL, token);
+ attrptr = ippAddString(request, group, value, attr, NULL, token);
else
{
/*
num_values ++;
}
- ippAddStrings(request, group, value, attr, num_values,
- NULL, (const char **)values);
+ attrptr = ippAddStrings(request, group, value, attr, num_values,
+ NULL, (const char **)values);
}
break;
}
+
+ if (!attrptr)
+ {
+ print_fatal_error("Unable to add attribute on line %d: %s", linenum,
+ cupsLastErrorString());
+ pass = 0;
+ goto test_exit;
+ }
}
- else if (!strcasecmp(token, "FILE"))
+ else if (!_cups_strcasecmp(token, "FILE"))
{
/*
* File...
expand_variables(vars, token, temp, sizeof(token));
get_filename(testfile, filename, token, sizeof(filename));
}
- else if (!strcasecmp(token, "STATUS"))
+ else if (!_cups_strcasecmp(token, "STATUS"))
{
/*
* Status...
goto test_exit;
}
- if ((statuses[num_statuses].status = ippErrorValue(token)) < 0 &&
+ if ((statuses[num_statuses].status = ippErrorValue(token))
+ == (ipp_status_t)-1 &&
(statuses[num_statuses].status = strtol(token, NULL, 0)) == 0)
{
print_fatal_error("Bad STATUS code \"%s\" on line %d.", token,
last_status = statuses + num_statuses;
num_statuses ++;
- last_status->if_defined = NULL;
- last_status->if_not_defined = NULL;
+ last_status->if_defined = NULL;
+ last_status->if_not_defined = NULL;
+ last_status->repeat_match = 0;
+ last_status->repeat_no_match = 0;
}
- else if (!strcasecmp(token, "EXPECT"))
+ else if (!_cups_strcasecmp(token, "EXPECT"))
{
/*
* Expected attributes...
else
last_expect->name = strdup(token);
}
- else if (!strcasecmp(token, "COUNT"))
+ else if (!_cups_strcasecmp(token, "COUNT"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "DEFINE-MATCH"))
+ else if (!_cups_strcasecmp(token, "DEFINE-MATCH"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "DEFINE-NO-MATCH"))
+ else if (!_cups_strcasecmp(token, "DEFINE-NO-MATCH"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "DEFINE-VALUE"))
+ else if (!_cups_strcasecmp(token, "DEFINE-VALUE"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "OF-TYPE"))
+ else if (!_cups_strcasecmp(token, "OF-TYPE"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "IN-GROUP"))
+ else if (!_cups_strcasecmp(token, "IN-GROUP"))
{
ipp_tag_t in_group; /* IN-GROUP value */
goto test_exit;
}
}
- else if (!strcasecmp(token, "SAME-COUNT-AS"))
+ else if (!_cups_strcasecmp(token, "REPEAT-MATCH"))
+ {
+ if (last_status)
+ last_status->repeat_match = 1;
+ else if (last_expect)
+ last_expect->repeat_match = 1;
+ else
+ {
+ print_fatal_error("REPEAT-MATCH without a preceding EXPECT or STATUS "
+ "on line %d.", linenum);
+ pass = 0;
+ goto test_exit;
+ }
+ }
+ else if (!_cups_strcasecmp(token, "REPEAT-NO-MATCH"))
+ {
+ if (last_status)
+ last_status->repeat_no_match = 1;
+ else if (last_expect)
+ last_expect->repeat_no_match = 1;
+ else
+ {
+ print_fatal_error("REPEAT-NO-MATCH without a preceding EXPECT or "
+ "STATUS on ine %d.", linenum);
+ pass = 0;
+ goto test_exit;
+ }
+ }
+ else if (!_cups_strcasecmp(token, "SAME-COUNT-AS"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "IF-DEFINED"))
+ else if (!_cups_strcasecmp(token, "IF-DEFINED"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "IF-NOT-DEFINED"))
+ else if (!_cups_strcasecmp(token, "IF-NOT-DEFINED"))
{
if (!get_token(fp, token, sizeof(token), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "WITH-VALUE"))
+ else if (!_cups_strcasecmp(token, "WITH-VALUE"))
{
if (!get_token(fp, temp, sizeof(temp), &linenum))
{
goto test_exit;
}
}
- else if (!strcasecmp(token, "DISPLAY"))
+ else if (!_cups_strcasecmp(token, "DISPLAY"))
{
/*
* Display attributes...
* Submit the IPP request...
*/
+ TestCount ++;
+
request->request.op.version[0] = version / 10;
request->request.op.version[1] = version % 10;
request->request.op.operation_id = op;
puts("<key>Operation</key>");
print_xml_string("string", ippOpString(op));
puts("<key>RequestAttributes</key>");
- puts("<dict>");
- for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
- print_attr(attrptr);
- puts("</dict>");
+ puts("<array>");
+ if (request->attrs)
+ {
+ puts("<dict>");
+ for (attrptr = request->attrs, group = attrptr->group_tag;
+ attrptr;
+ attrptr = attrptr->next)
+ print_attr(attrptr, &group);
+ puts("</dict>");
+ }
+ puts("</array>");
}
else if (Output == _CUPS_OUTPUT_TEST)
{
if (Verbosity)
{
- printf(" %s:\n", ippOpString(op));
+ printf(" %s:\n", ippOpString(op));
- for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
- print_attr(attrptr);
+ for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
+ print_attr(attrptr, NULL);
}
- printf(" %-69.69s [", name);
+ printf(" %-68.68s [", name);
fflush(stdout);
}
if ((skip_previous && !prev_pass) || skip_test)
{
+ SkipCount ++;
+
ippDelete(request);
request = NULL;
goto skip_error;
}
- if (transfer == _CUPS_TRANSFER_CHUNKED ||
- (transfer == _CUPS_TRANSFER_AUTO && filename[0]))
+ do
{
- /*
- * Send request using chunking...
- */
+ status = HTTP_OK;
- http_status_t status = cupsSendRequest(http, request, resource, 0);
+ if (transfer == _CUPS_TRANSFER_CHUNKED ||
+ (transfer == _CUPS_TRANSFER_AUTO && filename[0]))
+ {
+ /*
+ * Send request using chunking - a 0 length means "chunk".
+ */
- if (status == HTTP_CONTINUE && filename[0])
+ length = 0;
+ }
+ else
{
- int fd; /* File to send */
- char buffer[8192]; /* Copy buffer */
- ssize_t bytes; /* Bytes read/written */
+ /*
+ * Send request using content length...
+ */
- if ((fd = open(filename, O_RDONLY | O_BINARY)) >= 0)
- {
- while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
- if ((status = cupsWriteRequestData(http, buffer,
- bytes)) != HTTP_CONTINUE)
- break;
- }
- else
+ length = ippLength(request);
+
+ if (filename[0] && (reqfile = cupsFileOpen(filename, "r")) != NULL)
{
- snprintf(buffer, sizeof(buffer), "%s: %s", filename, strerror(errno));
- _cupsSetError(IPP_INTERNAL_ERROR, buffer, 0);
+ /*
+ * Read the file to get the uncompressed file size...
+ */
+
+ while ((bytes = cupsFileRead(reqfile, buffer, sizeof(buffer))) > 0)
+ length += bytes;
- status = HTTP_ERROR;
+ cupsFileClose(reqfile);
}
}
- ippDelete(request);
+ /*
+ * Send the request...
+ */
- if (status == HTTP_CONTINUE)
- response = cupsGetResponse(http, resource);
- else
- response = NULL;
- }
- else if (filename[0])
- response = cupsDoFileRequest(http, request, resource, filename);
- else
- response = cupsDoRequest(http, request, resource);
+ response = NULL;
+ repeat_test = 0;
+ prev_pass = 1;
+
+ if (status != HTTP_ERROR)
+ {
+ while (!response && !Cancel && prev_pass)
+ {
+ status = cupsSendRequest(http, request, resource, length);
- request = NULL;
- prev_pass = 1;
+ if (!Cancel && status == HTTP_CONTINUE &&
+ request->state == IPP_DATA && filename[0])
+ {
+ if ((reqfile = cupsFileOpen(filename, "r")) != NULL)
+ {
+ while (!Cancel &&
+ (bytes = cupsFileRead(reqfile, buffer,
+ sizeof(buffer))) > 0)
+ if ((status = cupsWriteRequestData(http, buffer,
+ bytes)) != HTTP_CONTINUE)
+ break;
- if (!response)
- prev_pass = pass = 0;
- else
- {
- if (http->version != HTTP_1_1)
- prev_pass = pass = 0;
+ cupsFileClose(reqfile);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "%s: %s", filename,
+ strerror(errno));
+ _cupsSetError(IPP_INTERNAL_ERROR, buffer, 0);
- if (response->request.status.request_id != request_id)
- prev_pass = pass = 0;
+ status = HTTP_ERROR;
+ }
+ }
- if (version &&
- (response->request.status.version[0] != (version / 10) ||
- response->request.status.version[1] != (version % 10)))
- prev_pass = pass = 0;
+ /*
+ * Get the server's response...
+ */
- if ((attrptr = ippFindAttribute(response, "job-id",
- IPP_TAG_INTEGER)) != NULL)
- {
- snprintf(temp, sizeof(temp), "%d", attrptr->values[0].integer);
- set_variable(vars, "job-id", temp);
- }
+ if (!Cancel && status != HTTP_ERROR)
+ {
+ response = cupsGetResponse(http, resource);
+ status = httpGetStatus(http);
+ }
- if ((attrptr = ippFindAttribute(response, "job-uri",
- IPP_TAG_URI)) != NULL)
- set_variable(vars, "job-uri", attrptr->values[0].string.text);
+ if (!Cancel && status == HTTP_ERROR &&
+#ifdef WIN32
+ http->error != WSAETIMEDOUT)
+#else
+ http->error != ETIMEDOUT)
+#endif /* WIN32 */
+ {
+ if (httpReconnect(http))
+ prev_pass = 0;
+ }
+ else if (status == HTTP_ERROR)
+ {
+ if (!Cancel)
+ httpReconnect(http);
- if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
- IPP_TAG_INTEGER)) != NULL)
- {
- snprintf(temp, sizeof(temp), "%d", attrptr->values[0].integer);
- set_variable(vars, "notify-subscription-id", temp);
+ prev_pass = 0;
+ }
+ }
}
- attrptr = response->attrs;
- if (!attrptr || !attrptr->name ||
- attrptr->value_tag != IPP_TAG_CHARSET ||
- attrptr->group_tag != IPP_TAG_OPERATION ||
- attrptr->num_values != 1 ||
- strcmp(attrptr->name, "attributes-charset"))
- prev_pass = pass = 0;
-
- if (attrptr)
+ /*
+ * Check results of request...
+ */
+
+ if (!response)
+ prev_pass = pass = 0;
+ else
{
- attrptr = attrptr->next;
- if (!attrptr || !attrptr->name ||
- attrptr->value_tag != IPP_TAG_LANGUAGE ||
- attrptr->group_tag != IPP_TAG_OPERATION ||
- attrptr->num_values != 1 ||
- strcmp(attrptr->name, "attributes-natural-language"))
+ if (http->version != HTTP_1_1)
prev_pass = pass = 0;
- }
- if ((attrptr = ippFindAttribute(response, "status-message",
- IPP_TAG_ZERO)) != NULL &&
- (attrptr->value_tag != IPP_TAG_TEXT ||
- attrptr->group_tag != IPP_TAG_OPERATION ||
- attrptr->num_values != 1 ||
- (attrptr->value_tag == IPP_TAG_TEXT &&
- strlen(attrptr->values[0].string.text) > 255)))
- prev_pass = pass = 0;
+ if (response->state != IPP_DATA)
+ prev_pass = pass = 0;
- if ((attrptr = ippFindAttribute(response, "detailed-status-message",
- IPP_TAG_ZERO)) != NULL &&
- (attrptr->value_tag != IPP_TAG_TEXT ||
- attrptr->group_tag != IPP_TAG_OPERATION ||
- attrptr->num_values != 1 ||
- (attrptr->value_tag == IPP_TAG_TEXT &&
- strlen(attrptr->values[0].string.text) > 1023)))
- prev_pass = pass = 0;
+ if (response->request.status.request_id != request_id)
+ prev_pass = pass = 0;
- for (attrptr = response->attrs, group = attrptr->group_tag;
- attrptr;
- attrptr = attrptr->next)
- {
- if (attrptr->group_tag < group && attrptr->group_tag != IPP_TAG_ZERO)
- {
+ if (version &&
+ (response->request.status.version[0] != (version / 10) ||
+ response->request.status.version[1] != (version % 10)))
prev_pass = pass = 0;
- break;
- }
- if (!validate_attr(attrptr, 0))
+ if ((attrptr = ippFindAttribute(response, "job-id",
+ IPP_TAG_INTEGER)) != NULL)
{
- prev_pass = pass = 0;
- break;
+ snprintf(temp, sizeof(temp), "%d", attrptr->values[0].integer);
+ set_variable(vars, "job-id", temp);
}
- }
- for (i = 0; i < num_statuses; i ++)
- {
- if (statuses[i].if_defined &&
- !get_variable(vars, statuses[i].if_defined))
- continue;
+ if ((attrptr = ippFindAttribute(response, "job-uri",
+ IPP_TAG_URI)) != NULL)
+ set_variable(vars, "job-uri", attrptr->values[0].string.text);
- if (statuses[i].if_not_defined &&
- get_variable(vars, statuses[i].if_not_defined))
- continue;
+ if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ snprintf(temp, sizeof(temp), "%d", attrptr->values[0].integer);
+ set_variable(vars, "notify-subscription-id", temp);
+ }
- if (response->request.status.status_code == statuses[i].status)
- break;
- }
+ attrptr = response->attrs;
+ if (!attrptr || !attrptr->name ||
+ attrptr->value_tag != IPP_TAG_CHARSET ||
+ attrptr->group_tag != IPP_TAG_OPERATION ||
+ attrptr->num_values != 1 ||
+ strcmp(attrptr->name, "attributes-charset"))
+ prev_pass = pass = 0;
- if (i == num_statuses && num_statuses > 0)
- prev_pass = pass = 0;
- else
- {
- for (i = num_expects, expect = expects; i > 0; i --, expect ++)
- {
- if (expect->if_defined && !get_variable(vars, expect->if_defined))
- continue;
+ if (attrptr)
+ {
+ attrptr = attrptr->next;
+ if (!attrptr || !attrptr->name ||
+ attrptr->value_tag != IPP_TAG_LANGUAGE ||
+ attrptr->group_tag != IPP_TAG_OPERATION ||
+ attrptr->num_values != 1 ||
+ strcmp(attrptr->name, "attributes-natural-language"))
+ prev_pass = pass = 0;
+ }
+
+ if ((attrptr = ippFindAttribute(response, "status-message",
+ IPP_TAG_ZERO)) != NULL &&
+ (attrptr->value_tag != IPP_TAG_TEXT ||
+ attrptr->group_tag != IPP_TAG_OPERATION ||
+ attrptr->num_values != 1 ||
+ (attrptr->value_tag == IPP_TAG_TEXT &&
+ strlen(attrptr->values[0].string.text) > 255)))
+ prev_pass = pass = 0;
+
+ if ((attrptr = ippFindAttribute(response, "detailed-status-message",
+ IPP_TAG_ZERO)) != NULL &&
+ (attrptr->value_tag != IPP_TAG_TEXT ||
+ attrptr->group_tag != IPP_TAG_OPERATION ||
+ attrptr->num_values != 1 ||
+ (attrptr->value_tag == IPP_TAG_TEXT &&
+ strlen(attrptr->values[0].string.text) > 1023)))
+ prev_pass = pass = 0;
+
+ a = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
+ for (attrptr = response->attrs, group = attrptr->group_tag;
+ attrptr;
+ attrptr = attrptr->next)
+ {
+ if (attrptr->group_tag != group)
+ {
+ cupsArrayClear(a);
+
+ switch (attrptr->group_tag)
+ {
+ case IPP_TAG_ZERO :
+ break;
+
+ case IPP_TAG_OPERATION :
+ prev_pass = pass = 0;
+ break;
+
+ case IPP_TAG_UNSUPPORTED_GROUP :
+ if (group != IPP_TAG_OPERATION)
+ prev_pass = pass = 0;
+ break;
+
+ case IPP_TAG_JOB :
+ case IPP_TAG_PRINTER :
+ if (group != IPP_TAG_OPERATION &&
+ group != IPP_TAG_UNSUPPORTED_GROUP)
+ prev_pass = pass = 0;
+ break;
+
+ case IPP_TAG_SUBSCRIPTION :
+ if (group > attrptr->group_tag &&
+ group != IPP_TAG_DOCUMENT)
+ prev_pass = pass = 0;
+ break;
+
+ default :
+ if (group > attrptr->group_tag)
+ prev_pass = pass = 0;
+ break;
+ }
+
+ if (!pass)
+ break;
+
+ if (attrptr->group_tag != IPP_TAG_ZERO)
+ group = attrptr->group_tag;
+ }
+
+ if (!validate_attr(attrptr, 0))
+ {
+ prev_pass = pass = 0;
+ break;
+ }
+
+ if (attrptr->name)
+ {
+ if (cupsArrayFind(a, attrptr->name))
+ {
+ prev_pass = pass = 0;
+ break;
+ }
+
+ cupsArrayAdd(a, attrptr->name);
+ }
+ }
+
+ cupsArrayDelete(a);
+
+ for (i = 0; i < num_statuses; i ++)
+ {
+ if (statuses[i].if_defined &&
+ !get_variable(vars, statuses[i].if_defined))
+ continue;
+
+ if (statuses[i].if_not_defined &&
+ get_variable(vars, statuses[i].if_not_defined))
+ continue;
+
+ if (response->request.status.status_code == statuses[i].status)
+ {
+ if (statuses[i].repeat_match)
+ repeat_test = 1;
+
+ break;
+ }
+ else if (statuses[i].repeat_no_match)
+ repeat_test = 1;
+ }
- if (expect->if_not_defined &&
+ if (i == num_statuses && num_statuses > 0)
+ prev_pass = pass = 0;
+
+ for (i = num_expects, expect = expects; i > 0; i --, expect ++)
+ {
+ if (expect->if_defined && !get_variable(vars, expect->if_defined))
+ continue;
+
+ if (expect->if_not_defined &&
get_variable(vars, expect->if_not_defined))
- continue;
+ continue;
- found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
+ found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
- if ((found && expect->not_expect) ||
+ if ((found && expect->not_expect) ||
(!found && !(expect->not_expect || expect->optional)) ||
(found && !expect_matches(expect, found->value_tag)) ||
(found && expect->in_group &&
found->group_tag != expect->in_group))
- {
+ {
if (expect->define_no_match)
set_variable(vars, expect->define_no_match, "1");
- else if (!expect->define_match)
+ else if (!expect->define_match && !expect->define_value)
prev_pass = pass = 0;
- continue;
- }
+ if (expect->repeat_no_match)
+ repeat_test = 1;
- if (found &&
- !with_value(expect->with_value, expect->with_regex, found, 0))
- {
+ continue;
+ }
+
+ if (found)
+ ippAttributeString(found, buffer, sizeof(buffer));
+
+ if (found &&
+ !with_value(expect->with_value, expect->with_regex, found, 0,
+ buffer, sizeof(buffer)))
+ {
if (expect->define_no_match)
set_variable(vars, expect->define_no_match, "1");
- else if (!expect->define_match)
+ else if (!expect->define_match && !expect->define_value)
prev_pass = pass = 0;
- continue;
- }
+ if (expect->repeat_no_match)
+ repeat_test = 1;
- if (found && expect->count > 0 && found->num_values != expect->count)
+ continue;
+ }
+
+ if (found && expect->count > 0 &&
+ found->num_values != expect->count)
{
if (expect->define_no_match)
set_variable(vars, expect->define_no_match, "1");
- else if (!expect->define_match)
+ else if (!expect->define_match && !expect->define_value)
prev_pass = pass = 0;
- continue;
+ if (expect->repeat_no_match)
+ repeat_test = 1;
+
+ continue;
}
- if (found && expect->same_count_as)
- {
- attrptr = ippFindAttribute(response, expect->same_count_as,
- IPP_TAG_ZERO);
+ if (found && expect->same_count_as)
+ {
+ attrptr = ippFindAttribute(response, expect->same_count_as,
+ IPP_TAG_ZERO);
- if (!attrptr || attrptr->num_values != found->num_values)
- {
+ if (!attrptr || attrptr->num_values != found->num_values)
+ {
if (expect->define_no_match)
set_variable(vars, expect->define_no_match, "1");
- else if (!expect->define_match)
+ else if (!expect->define_match && !expect->define_value)
prev_pass = pass = 0;
- continue;
- }
- }
+ if (expect->repeat_no_match)
+ repeat_test = 1;
+
+ continue;
+ }
+ }
if (found && expect->define_match)
set_variable(vars, expect->define_match, "1");
if (found && expect->define_value)
- {
- _ippAttrString(found, token, sizeof(token));
- set_variable(vars, expect->define_value, token);
- }
- }
+ set_variable(vars, expect->define_value, buffer);
+
+ if (found && expect->repeat_match)
+ repeat_test = 1;
+ }
}
+
+ /*
+ * If we are going to repeat this test, sleep 1 second so we don't flood
+ * the printer with requests...
+ */
+
+ if (repeat_test)
+ sleep(1);
}
+ while (repeat_test);
+
+ ippDelete(request);
+
+ request = NULL;
+
+ if (prev_pass)
+ PassCount ++;
+ else
+ FailCount ++;
if (Output == _CUPS_OUTPUT_PLIST)
{
puts("<key>StatusCode</key>");
print_xml_string("string", ippErrorString(cupsLastError()));
puts("<key>ResponseAttributes</key>");
+ puts("<array>");
puts("<dict>");
- for (attrptr = response ? response->attrs : NULL;
+ for (attrptr = response ? response->attrs : NULL,
+ group = attrptr ? attrptr->group_tag : IPP_TAG_ZERO;
attrptr;
attrptr = attrptr->next)
- print_attr(attrptr);
+ print_attr(attrptr, &group);
puts("</dict>");
+ puts("</array>");
}
else if (Output == _CUPS_OUTPUT_TEST)
{
puts(prev_pass ? "PASS]" : "FAIL]");
- if (Verbosity && response)
+ if (!prev_pass || (Verbosity && response))
{
printf(" RECEIVED: %lu bytes in response\n",
(unsigned long)ippLength(response));
- printf(" status-code = %x (%s)\n", cupsLastError(),
- ippErrorString(cupsLastError()));
+ printf(" status-code = %s (%s)\n", ippErrorString(cupsLastError()),
+ cupsLastErrorString());
- for (attrptr = response->attrs;
- attrptr != NULL;
- attrptr = attrptr->next)
- {
- print_attr(attrptr);
+ if (response)
+ {
+ for (attrptr = response->attrs;
+ attrptr != NULL;
+ attrptr = attrptr->next)
+ print_attr(attrptr, NULL);
}
}
}
else if (!prev_pass)
fprintf(stderr, "%s\n", cupsLastErrorString());
- if (prev_pass && Output != _CUPS_OUTPUT_PLIST &&
- Output != _CUPS_OUTPUT_QUIET && !Verbosity && num_displayed > 0)
+ if (prev_pass && Output >= _CUPS_OUTPUT_LIST && !Verbosity &&
+ num_displayed > 0)
{
- if (Output >= _CUPS_OUTPUT_LIST)
+ size_t width; /* Length of value */
+
+ for (i = 0; i < num_displayed; i ++)
{
- size_t width; /* Length of value */
+ widths[i] = strlen(displayed[i]);
+ for (attrptr = ippFindAttribute(response, displayed[i], IPP_TAG_ZERO);
+ attrptr;
+ attrptr = ippFindNextAttribute(response, displayed[i],
+ IPP_TAG_ZERO))
+ {
+ width = ippAttributeString(attrptr, NULL, 0);
+ if (width > widths[i])
+ widths[i] = width;
+ }
+ }
- for (i = 0; i < num_displayed; i ++)
- {
- widths[i] = strlen(displayed[i]);
+ if (Output == _CUPS_OUTPUT_CSV)
+ print_csv(NULL, num_displayed, displayed, widths);
+ else
+ print_line(NULL, num_displayed, displayed, widths);
- for (attrptr = ippFindAttribute(response, displayed[i], IPP_TAG_ZERO);
- attrptr;
- attrptr = ippFindNextAttribute(response, displayed[i],
- IPP_TAG_ZERO))
- {
- width = _ippAttrString(attrptr, NULL, 0);
- if (width > widths[i])
- widths[i] = width;
- }
- }
+ attrptr = response->attrs;
- if (Output == _CUPS_OUTPUT_CSV)
- print_csv(NULL, num_displayed, displayed, widths);
- else
- print_line(NULL, num_displayed, displayed, widths);
+ while (attrptr)
+ {
+ while (attrptr && attrptr->group_tag <= IPP_TAG_OPERATION)
+ attrptr = attrptr->next;
- attrptr = response->attrs;
+ if (attrptr)
+ {
+ if (Output == _CUPS_OUTPUT_CSV)
+ print_csv(attrptr, num_displayed, displayed, widths);
+ else
+ print_line(attrptr, num_displayed, displayed, widths);
- while (attrptr)
- {
- while (attrptr && attrptr->group_tag <= IPP_TAG_OPERATION)
+ while (attrptr && attrptr->group_tag > IPP_TAG_OPERATION)
attrptr = attrptr->next;
-
- if (attrptr)
- {
- if (Output == _CUPS_OUTPUT_CSV)
- print_csv(attrptr, num_displayed, displayed, widths);
- else
- print_line(attrptr, num_displayed, displayed, widths);
-
- while (attrptr && attrptr->group_tag > IPP_TAG_OPERATION)
- attrptr = attrptr->next;
- }
- }
- }
- else
- {
- for (attrptr = response->attrs;
- attrptr != NULL;
- attrptr = attrptr->next)
- {
- if (attrptr->name)
- {
- for (i = 0; i < num_displayed; i ++)
- {
- if (!strcmp(displayed[i], attrptr->name))
- {
- print_attr(attrptr);
- break;
- }
- }
- }
}
}
}
cupsLastErrorString());
else
{
+ if (response->state != IPP_DATA)
+ print_test_error("Missing end-of-attributes-tag in response "
+ "(RFC 2910 section 3.5.1)");
+
if (version &&
(response->request.status.version[0] != (version / 10) ||
response->request.status.version[1] != (version % 10)))
(int)strlen(attrptr->values[0].string.text));
}
+ a = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
for (attrptr = response->attrs, group = attrptr->group_tag;
attrptr;
attrptr = attrptr->next)
{
- if (attrptr->group_tag < group && attrptr->group_tag != IPP_TAG_ZERO)
- print_test_error("Attribute groups out of order (%s < %s)",
- ippTagString(attrptr->group_tag),
- ippTagString(group));
+ if (attrptr->group_tag != group)
+ {
+ cupsArrayClear(a);
+
+ switch (attrptr->group_tag)
+ {
+ case IPP_TAG_ZERO :
+ break;
+
+ case IPP_TAG_OPERATION :
+ prev_pass = pass = 0;
+ break;
+
+ case IPP_TAG_UNSUPPORTED_GROUP :
+ if (group != IPP_TAG_OPERATION)
+ print_test_error("Attribute groups out of order (%s < %s)",
+ ippTagString(attrptr->group_tag),
+ ippTagString(group));
+ break;
+
+ case IPP_TAG_JOB :
+ case IPP_TAG_PRINTER :
+ if (group != IPP_TAG_OPERATION &&
+ group != IPP_TAG_UNSUPPORTED_GROUP)
+ print_test_error("Attribute groups out of order (%s < %s)",
+ ippTagString(attrptr->group_tag),
+ ippTagString(group));
+ break;
+
+ case IPP_TAG_SUBSCRIPTION :
+ if (group > attrptr->group_tag &&
+ group != IPP_TAG_DOCUMENT)
+ print_test_error("Attribute groups out of order (%s < %s)",
+ ippTagString(attrptr->group_tag),
+ ippTagString(group));
+ break;
+
+ default :
+ if (group > attrptr->group_tag)
+ print_test_error("Attribute groups out of order (%s < %s)",
+ ippTagString(attrptr->group_tag),
+ ippTagString(group));
+ break;
+ }
+
+ if (attrptr->group_tag != IPP_TAG_ZERO)
+ group = attrptr->group_tag;
+ }
validate_attr(attrptr, 1);
+
+ if (attrptr->name)
+ {
+ if (cupsArrayFind(a, attrptr->name))
+ print_test_error("Duplicate \"%s\" attribute in %s group",
+ attrptr->name, ippTagString(group));
+
+ cupsArrayAdd(a, attrptr->name);
+ }
}
+ cupsArrayDelete(a);
+
for (i = 0; i < num_statuses; i ++)
{
if (statuses[i].if_defined &&
if (i == num_statuses && num_statuses > 0)
{
- print_test_error("Bad status-code (%s)",
- ippErrorString(cupsLastError()));
- print_test_error("status-message=\"%s\"", cupsLastErrorString());
+ for (i = 0; i < num_statuses; i ++)
+ {
+ if (statuses[i].if_defined &&
+ !get_variable(vars, statuses[i].if_defined))
+ continue;
+
+ if (statuses[i].if_not_defined &&
+ get_variable(vars, statuses[i].if_not_defined))
+ continue;
+
+ print_test_error("EXPECTED: STATUS %s (got %s)",
+ ippErrorString(statuses[i].status),
+ ippErrorString(cupsLastError()));
+ }
+
+ if ((attrptr = ippFindAttribute(response, "status-message",
+ IPP_TAG_TEXT)) != NULL)
+ print_test_error("status-message=\"%s\"",
+ attrptr->values[0].string.text);
}
for (i = num_expects, expect = expects; i > 0; i --, expect ++)
{
- if (expect->define_match || expect->define_no_match)
+ if (expect->define_match || expect->define_no_match ||
+ expect->define_value)
continue;
if (expect->if_defined && !get_variable(vars, expect->if_defined))
expect->name, ippTagString(expect->in_group),
ippTagString(found->group_tag));
- if (!with_value(expect->with_value, expect->with_regex, found, 0))
+ if (!with_value(expect->with_value, expect->with_regex, found, 0,
+ buffer, sizeof(buffer)))
{
if (expect->with_regex)
print_test_error("EXPECTED: %s WITH-VALUE /%s/",
print_test_error("EXPECTED: %s WITH-VALUE \"%s\"",
expect->name, expect->with_value);
- with_value(expect->with_value, expect->with_regex, found, 1);
+ with_value(expect->with_value, expect->with_regex, found, 1,
+ buffer, sizeof(buffer));
}
if (expect->count > 0 && found->num_values != expect->count)
puts("</array>");
}
+ if (num_displayed > 0 && !Verbosity &&
+ (Output == _CUPS_OUTPUT_TEST || Output == _CUPS_OUTPUT_PLIST))
+ {
+ for (attrptr = response->attrs;
+ attrptr != NULL;
+ attrptr = attrptr->next)
+ {
+ if (attrptr->name)
+ {
+ for (i = 0; i < num_displayed; i ++)
+ {
+ if (!strcmp(displayed[i], attrptr->name))
+ {
+ print_attr(attrptr, NULL);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ skip_error:
+
if (Output == _CUPS_OUTPUT_PLIST)
puts("</dict>");
- skip_error:
+ fflush(stdout);
ippDelete(response);
response = NULL;
if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) +
(lastcol->num_values + 1) *
- sizeof(ipp_value_t))) == NULL)
+ sizeof(_ipp_value_t))) == NULL)
{
print_fatal_error("Unable to allocate memory on line %d.", *linenum);
goto col_error;
else
goto col_error;
}
- else if (!strcasecmp(token, "MEMBER"))
+ else if (!_cups_strcasecmp(token, "MEMBER"))
{
/*
* Attribute...
switch (value)
{
case IPP_TAG_BOOLEAN :
- if (!strcasecmp(token, "true"))
+ if (!_cups_strcasecmp(token, "true"))
ippAddBoolean(col, IPP_TAG_ZERO, attr, 1);
else
ippAddBoolean(col, IPP_TAG_ZERO, attr, atoi(token));
char units[6]; /* Units */
if (sscanf(token, "%dx%d%5s", &xres, &yres, units) != 3 ||
- (strcasecmp(units, "dpi") && strcasecmp(units, "dpc") &&
- strcasecmp(units, "other")))
+ (_cups_strcasecmp(units, "dpi") && _cups_strcasecmp(units, "dpc") &&
+ _cups_strcasecmp(units, "other")))
{
print_fatal_error("Bad resolution value \"%s\" on line %d.",
token, *linenum);
goto col_error;
}
- if (!strcasecmp(units, "dpi"))
+ if (!_cups_strcasecmp(units, "dpi"))
ippAddResolution(col, IPP_TAG_ZERO, attr, xres, yres,
IPP_RES_PER_INCH);
- else if (!strcasecmp(units, "dpc"))
+ else if (!_cups_strcasecmp(units, "dpc"))
ippAddResolution(col, IPP_TAG_ZERO, attr, xres, yres,
IPP_RES_PER_CM);
else
static char * /* O - ISO 8601 date/time string */
iso_date(ipp_uchar_t *date) /* I - IPP (RFC 1903) date/time value */
{
- unsigned year = (date[0] << 8) + date[1];
- /* Year */
+ time_t utctime; /* UTC time since 1970 */
+ struct tm *utcdate; /* UTC date/time */
static char buffer[255]; /* String buffer */
- if (date[9] == 0 && date[10] == 0)
- snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02uZ",
- year, date[2], date[3], date[4], date[5], date[6]);
- else
- snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
- year, date[2], date[3], date[4], date[5], date[6],
- date[8], date[9], date[10]);
+ utctime = ippDateToTime(date);
+ utcdate = gmtime(&utctime);
+
+ snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02dZ",
+ utcdate->tm_year + 1900, utcdate->tm_mon + 1, utcdate->tm_mday,
+ utcdate->tm_hour, utcdate->tm_min, utcdate->tm_sec);
return (buffer);
}
*/
static void
-print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
+print_attr(ipp_attribute_t *attr, /* I - Attribute to print */
+ ipp_tag_t *group) /* IO - Current group */
{
int i; /* Looping var */
ipp_attribute_t *colattr; /* Collection attribute */
if (Output == _CUPS_OUTPUT_PLIST)
{
- if (!attr->name)
+ if (!attr->name || (group && *group != attr->group_tag))
{
- printf("<key>%s</key>\n<true />\n", ippTagString(attr->group_tag));
- return;
+ puts("</dict>");
+ puts("<dict>");
+
+ if (group)
+ *group = attr->group_tag;
}
+ if (!attr->name)
+ return;
+
print_xml_string("key", attr->name);
if (attr->num_values > 1)
puts("<array>");
- }
- else if (Output == _CUPS_OUTPUT_TEST)
- {
- if (!attr->name)
- {
- puts(" -- separator --");
- return;
- }
- printf(" %s (%s%s) = ", attr->name,
- attr->num_values > 1 ? "1setOf " : "",
- ippTagString(attr->value_tag));
- }
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ printf("<integer>%d</integer>\n", attr->values[i].integer);
+ else
+ printf("%d ", attr->values[i].integer);
+ break;
- switch (attr->value_tag)
- {
- case IPP_TAG_INTEGER :
- case IPP_TAG_ENUM :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
- printf("<integer>%d</integer>\n", attr->values[i].integer);
- else
- printf("%d ", attr->values[i].integer);
- break;
+ case IPP_TAG_BOOLEAN :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ puts(attr->values[i].boolean ? "<true />" : "<false />");
+ else if (attr->values[i].boolean)
+ fputs("true ", stdout);
+ else
+ fputs("false ", stdout);
+ break;
- case IPP_TAG_BOOLEAN :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
- puts(attr->values[i].boolean ? "<true />" : "<false />");
- else if (attr->values[i].boolean)
- fputs("true ", stdout);
- else
- fputs("false ", stdout);
- break;
+ case IPP_TAG_RANGE :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ printf("<dict><key>lower</key><integer>%d</integer>"
+ "<key>upper</key><integer>%d</integer></dict>\n",
+ attr->values[i].range.lower, attr->values[i].range.upper);
+ else
+ printf("%d-%d ", attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ break;
- case IPP_TAG_RANGE :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
- printf("<dict><key>lower</key><integer>%d</integer>"
- "<key>upper</key><integer>%d</integer></dict>\n",
- attr->values[i].range.lower, attr->values[i].range.upper);
- else
- printf("%d-%d ", attr->values[i].range.lower,
- attr->values[i].range.upper);
- break;
+ case IPP_TAG_RESOLUTION :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ printf("<dict><key>xres</key><integer>%d</integer>"
+ "<key>yres</key><integer>%d</integer>"
+ "<key>units</key><string>%s</string></dict>\n",
+ attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+ "dpi" : "dpc");
+ else
+ printf("%dx%d%s ", attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+ "dpi" : "dpc");
+ break;
- case IPP_TAG_RESOLUTION :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
- printf("<dict><key>xres</key><integer>%d</integer>"
- "<key>yres</key><integer>%d</integer>"
- "<key>units</key><string>%s</string></dict>\n",
- attr->values[i].resolution.xres,
- attr->values[i].resolution.yres,
- attr->values[i].resolution.units == IPP_RES_PER_INCH ?
- "dpi" : "dpc");
- else
- printf("%dx%d%s ", attr->values[i].resolution.xres,
- attr->values[i].resolution.yres,
- attr->values[i].resolution.units == IPP_RES_PER_INCH ?
- "dpi" : "dpc");
- break;
+ case IPP_TAG_DATE :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ printf("<date>%s</date>\n", iso_date(attr->values[i].date));
+ else
+ printf("%s ", iso_date(attr->values[i].date));
+ break;
- case IPP_TAG_DATE :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
- printf("<date>%s</date>\n", iso_date(attr->values[i].date));
- else
- printf("%s ", iso_date(attr->values[i].date));
- break;
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_URI :
+ case IPP_TAG_MIMETYPE :
+ case IPP_TAG_LANGUAGE :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ print_xml_string("string", attr->values[i].string.text);
+ else
+ printf("\"%s\" ", attr->values[i].string.text);
+ break;
- case IPP_TAG_STRING :
- case IPP_TAG_TEXT :
- case IPP_TAG_NAME :
- case IPP_TAG_KEYWORD :
- case IPP_TAG_CHARSET :
- case IPP_TAG_URI :
- case IPP_TAG_MIMETYPE :
- case IPP_TAG_LANGUAGE :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
- print_xml_string("string", attr->values[i].string.text);
- else
- printf("\"%s\" ", attr->values[i].string.text);
- break;
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ for (i = 0; i < attr->num_values; i ++)
+ if (Output == _CUPS_OUTPUT_PLIST)
+ {
+ fputs("<dict><key>language</key><string>", stdout);
+ print_xml_string(NULL, attr->values[i].string.language);
+ fputs("</string><key>string</key><string>", stdout);
+ print_xml_string(NULL, attr->values[i].string.text);
+ puts("</string></dict>");
+ }
+ else
+ printf("\"%s\"[%s] ", attr->values[i].string.text,
+ attr->values[i].string.language);
+ break;
- case IPP_TAG_TEXTLANG :
- case IPP_TAG_NAMELANG :
- for (i = 0; i < attr->num_values; i ++)
- if (Output == _CUPS_OUTPUT_PLIST)
+ case IPP_TAG_BEGIN_COLLECTION :
+ for (i = 0; i < attr->num_values; i ++)
{
- fputs("<dict><key>language</key><string>", stdout);
- print_xml_string(NULL, attr->values[i].string.charset);
- fputs("</string><key>string</key><string>", stdout);
- print_xml_string(NULL, attr->values[i].string.text);
- puts("</string></dict>");
+ if (Output == _CUPS_OUTPUT_PLIST)
+ {
+ puts("<dict>");
+ for (colattr = attr->values[i].collection->attrs;
+ colattr;
+ colattr = colattr->next)
+ print_attr(colattr, NULL);
+ puts("</dict>");
+ }
+ else
+ {
+ if (i)
+ putchar(' ');
+
+ print_col(attr->values[i].collection);
+ }
}
- else
- printf("\"%s\",%s ", attr->values[i].string.text,
- attr->values[i].string.charset);
- break;
+ break;
- case IPP_TAG_BEGIN_COLLECTION :
- for (i = 0; i < attr->num_values; i ++)
- {
+ default :
if (Output == _CUPS_OUTPUT_PLIST)
- {
- puts("<dict>");
- for (colattr = attr->values[i].collection->attrs;
- colattr;
- colattr = colattr->next)
- print_attr(colattr);
- puts("</dict>");
- }
+ printf("<string><<%s>></string>\n",
+ ippTagString(attr->value_tag));
else
- {
- if (i)
- putchar(' ');
-
- print_col(attr->values[i].collection);
- }
- }
- break;
-
- default :
- if (Output == _CUPS_OUTPUT_PLIST)
- printf("<string><<%s>></string>\n",
- ippTagString(attr->value_tag));
- else
- fputs(ippTagString(attr->value_tag), stdout);
- break;
- }
+ fputs(ippTagString(attr->value_tag), stdout);
+ break;
+ }
- if (Output == _CUPS_OUTPUT_PLIST)
- {
if (attr->num_values > 1)
puts("</array>");
}
else
- putchar('\n');
+ {
+ char buffer[8192]; /* Value buffer */
+
+ if (Output == _CUPS_OUTPUT_TEST)
+ {
+ if (!attr->name)
+ {
+ puts(" -- separator --");
+ return;
+ }
+
+ printf(" %s (%s%s) = ", attr->name,
+ attr->num_values > 1 ? "1setOf " : "",
+ ippTagString(attr->value_tag));
+ }
+
+ ippAttributeString(attr, buffer, sizeof(buffer));
+ puts(buffer);
+ }
}
case IPP_TAG_TEXTLANG :
case IPP_TAG_NAMELANG :
for (i = 0; i < attr->num_values; i ++)
- printf("\"%s\",%s ", attr->values[i].string.text,
- attr->values[i].string.charset);
+ printf("\"%s\"[%s] ", attr->values[i].string.text,
+ attr->values[i].string.language);
break;
case IPP_TAG_BEGIN_COLLECTION :
break;
else if (!strcmp(current->name, displayed[i]))
{
- _ippAttrString(current, buffer, maxlength);
+ ippAttributeString(current, buffer, maxlength);
break;
}
}
print_xml_trailer(0, buffer);
}
else
- _cupsLangPrintf(stderr, "ipptool: %s\n", buffer);
+ _cupsLangPrintf(stderr, "ipptool: %s", buffer);
}
break;
else if (!strcmp(current->name, displayed[i]))
{
- _ippAttrString(current, buffer, maxlength);
+ ippAttributeString(current, buffer, maxlength);
break;
}
}
fputs("<", stdout);
else if (*s == '>')
fputs(">", stdout);
+ else if ((*s & 0xe0) == 0xc0)
+ {
+ /*
+ * Validate UTF-8 two-byte sequence...
+ */
+
+ if ((s[1] & 0xc0) != 0x80)
+ {
+ putchar('?');
+ s ++;
+ }
+ else
+ {
+ putchar(*s++);
+ putchar(*s);
+ }
+ }
+ else if ((*s & 0xf0) == 0xe0)
+ {
+ /*
+ * Validate UTF-8 three-byte sequence...
+ */
+
+ if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80)
+ {
+ putchar('?');
+ s += 2;
+ }
+ else
+ {
+ putchar(*s++);
+ putchar(*s++);
+ putchar(*s);
+ }
+ }
+ else if ((*s & 0xf8) == 0xf0)
+ {
+ /*
+ * Validate UTF-8 four-byte sequence...
+ */
+
+ if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
+ (s[3] & 0xc0) != 0x80)
+ {
+ putchar('?');
+ s += 3;
+ }
+ else
+ {
+ putchar(*s++);
+ putchar(*s++);
+ putchar(*s++);
+ putchar(*s);
+ }
+ }
+ else if ((*s & 0x80) || (*s < ' ' && !isspace(*s & 255)))
+ {
+ /*
+ * Invalid control character...
+ */
+
+ putchar('?');
+ }
else
putchar(*s);
*var; /* New variable */
+ if (!_cups_strcasecmp(name, "filename"))
+ {
+ if (vars->filename)
+ free(vars->filename);
+
+ vars->filename = strdup(value);
+ return;
+ }
+
key.name = (char *)name;
if ((var = cupsArrayFind(vars->vars, &key)) != NULL)
{
}
+#ifndef WIN32
+/*
+ * 'sigterm_handler()' - Handle SIGINT and SIGTERM.
+ */
+
+static void
+sigterm_handler(int sig) /* I - Signal number (unused) */
+{
+ (void)sig;
+
+ Cancel = 1;
+
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+}
+#endif /* !WIN32 */
+
+
+/*
+ * 'timeout_cb()' - Handle HTTP timeouts.
+ */
+
+static int /* O - 1 to continue, 0 to cancel */
+timeout_cb(http_t *http, /* I - Connection to server (unused) */
+ void *user_data) /* I - User data (unused) */
+{
+ (void)http;
+ (void)user_data;
+
+ /* Always cancel on timeout */
+ return (0);
+}
+
+
/*
* 'usage()' - Show program usage.
*/
static void
usage(void)
{
- _cupsLangPuts(stderr,
- _("Usage: ipptool [options] URI filename [ ... "
- "filenameN ]\n"
- "\n"
- "Options:\n"
- "\n"
- "-C Send requests using chunking (default)\n"
- "-E Test with TLS encryption.\n"
- "-I Ignore errors\n"
- "-L Send requests using content-length\n"
- "-S Test with SSL encryption.\n"
- "-V version Set default IPP version.\n"
- "-X Produce XML plist instead of plain text.\n"
- "-d name=value Define variable.\n"
- "-f filename Set default request filename.\n"
- "-i seconds Repeat the last file with the given time "
- "interval.\n"
- "-n count Repeat the last file the given number of "
- "times.\n"
- "-q Be quiet - no output except errors.\n"
- "-t Produce a test report.\n"
- "-v Show all attributes sent and received.\n"));
+ _cupsLangPuts(stderr, _("Usage: ipptool [options] URI filename [ ... "
+ "filenameN ]"));
+ _cupsLangPuts(stderr, _("Options:"));
+ _cupsLangPuts(stderr, _(" -4 Connect using IPv4."));
+ _cupsLangPuts(stderr, _(" -6 Connect using IPv6."));
+ _cupsLangPuts(stderr, _(" -C Send requests using "
+ "chunking (default)."));
+ _cupsLangPuts(stderr, _(" -E Test with TLS "
+ "encryption."));
+ _cupsLangPuts(stderr, _(" -I Ignore errors."));
+ _cupsLangPuts(stderr, _(" -L Send requests using "
+ "content-length."));
+ _cupsLangPuts(stderr, _(" -S Test with SSL "
+ "encryption."));
+ _cupsLangPuts(stderr, _(" -T Set the receive/send "
+ "timeout in seconds."));
+ _cupsLangPuts(stderr, _(" -V version Set default IPP "
+ "version."));
+ _cupsLangPuts(stderr, _(" -X Produce XML plist instead "
+ "of plain text."));
+ _cupsLangPuts(stderr, _(" -d name=value Set named variable to "
+ "value."));
+ _cupsLangPuts(stderr, _(" -f filename Set default request "
+ "filename."));
+ _cupsLangPuts(stderr, _(" -i seconds Repeat the last file with "
+ "the given time interval."));
+ _cupsLangPuts(stderr, _(" -n count Repeat the last file the "
+ "given number of times."));
+ _cupsLangPuts(stderr, _(" -q Be quiet - no output "
+ "except errors."));
+ _cupsLangPuts(stderr, _(" -t Produce a test report."));
+ _cupsLangPuts(stderr, _(" -v Show all attributes sent "
+ "and received."));
exit(1);
}
with_value(char *value, /* I - Value string */
int regex, /* I - Value is a regular expression */
ipp_attribute_t *attr, /* I - Attribute to compare */
- int report) /* I - 1 = report failures */
+ int report, /* I - 1 = report failures */
+ char *matchbuf, /* I - Buffer to hold matching value */
+ size_t matchlen) /* I - Length of match buffer */
{
int i; /* Looping var */
char *valptr; /* Pointer into value */
+ *matchbuf = '\0';
+
/*
* NULL matches everything.
*/
valptr = value;
- if (!strncmp(valptr, "no-value,", 9))
- valptr += 9;
while (isspace(*valptr & 255) || isdigit(*valptr & 255) ||
*valptr == '-' || *valptr == ',' || *valptr == '<' ||
{
case '=' :
if (attr->values[i].integer == intvalue)
+ {
+ snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
return (1);
+ }
break;
case '<' :
if (attr->values[i].integer < intvalue)
+ {
+ snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
return (1);
+ }
break;
case '>' :
if (attr->values[i].integer > intvalue)
+ {
+ snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
return (1);
+ }
break;
}
}
}
break;
+ case IPP_TAG_RANGE :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ char op, /* Comparison operator */
+ *nextptr; /* Next pointer */
+ int intvalue; /* Integer value */
+
+
+ valptr = value;
+
+ while (isspace(*valptr & 255) || isdigit(*valptr & 255) ||
+ *valptr == '-' || *valptr == ',' || *valptr == '<' ||
+ *valptr == '=' || *valptr == '>')
+ {
+ op = '=';
+ while (*valptr && !isdigit(*valptr & 255) && *valptr != '-')
+ {
+ if (*valptr == '<' || *valptr == '>' || *valptr == '=')
+ op = *valptr;
+ valptr ++;
+ }
+
+ if (!*valptr)
+ break;
+
+ intvalue = strtol(valptr, &nextptr, 0);
+ if (nextptr == valptr)
+ break;
+ valptr = nextptr;
+
+ switch (op)
+ {
+ case '=' :
+ if (attr->values[i].range.lower == intvalue ||
+ attr->values[i].range.upper == intvalue)
+ {
+ snprintf(matchbuf, matchlen, "%d-%d",
+ attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ return (1);
+ }
+ break;
+ case '<' :
+ if (attr->values[i].range.upper < intvalue)
+ {
+ snprintf(matchbuf, matchlen, "%d-%d",
+ attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ return (1);
+ }
+ break;
+ case '>' :
+ if (attr->values[i].range.upper > intvalue)
+ {
+ snprintf(matchbuf, matchlen, "%d-%d",
+ attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ return (1);
+ }
+ break;
+ }
+ }
+ }
+
+ if (report)
+ {
+ for (i = 0; i < attr->num_values; i ++)
+ print_test_error("GOT: %s=%d-%d", attr->name,
+ attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ }
+ break;
+
case IPP_TAG_BOOLEAN :
for (i = 0; i < attr->num_values; i ++)
{
if (!strcmp(value, "true") == attr->values[i].boolean)
+ {
+ strlcpy(matchbuf, value, matchlen);
return (1);
+ }
}
if (report)
break;
case IPP_TAG_NOVALUE :
- return (!strcmp(value, "no-value") || !strncmp(value, "no-value,", 9));
+ case IPP_TAG_UNKNOWN :
+ return (1);
case IPP_TAG_CHARSET :
case IPP_TAG_KEYWORD :
regfree(&re);
+ if (i == attr->num_values)
+ strlcpy(matchbuf, attr->values[0].string.text, matchlen);
+
return (i == attr->num_values);
}
else
for (i = 0; i < attr->num_values; i ++)
{
if (!strcmp(value, attr->values[i].string.text))
+ {
+ strlcpy(matchbuf, attr->values[i].string.text, matchlen);
return (1);
+ }
}
if (report)