* Include necessary headers...
*/
-#define _IPP_PRIVATE_STRUCTURES 0 /* Disable private IPP stuff */
#include <cups/cups-private.h>
#include <cups/file-private.h>
#include <regex.h>
* Local functions...
*/
-static void add_stringf(cups_array_t *a, const char *s, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+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 void pause_message(const char *message);
static void print_attr(cups_file_t *outfile, int 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, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+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);
#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 void usage(void) __attribute__((noreturn));
-static int validate_attr(_cups_testdata_t *data, cups_array_t *errors, ipp_attribute_t *attr);
+static void usage(void) _CUPS_NORETURN;
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_from(cups_array_t *errors, ipp_attribute_t *fromattr, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
init_data(&data);
- _ippVarsInit(&vars);
+ _ippVarsInit(&vars, NULL, (_ipp_ferror_cb_t)error_cb, (_ipp_ftoken_cb_t)token_cb);
/*
* We need at least:
}
+/*
+ * 'copy_hex_string()' - Copy an octetString to a C string and encode as hex if
+ * needed.
+ */
+
+static void
+copy_hex_string(char *buffer, /* I - String buffer */
+ unsigned char *data, /* I - octetString data */
+ int datalen, /* I - octetString length */
+ size_t bufsize) /* I - Size of string buffer */
+{
+ char *bufptr, /* Pointer into string buffer */
+ *bufend = buffer + bufsize - 2;
+ /* End of string buffer */
+ unsigned char *dataptr, /* Pointer into octetString data */
+ *dataend = data + datalen;
+ /* End of octetString data */
+ static const char *hexdigits = "0123456789ABCDEF";
+ /* Hex digits */
+
+
+ /*
+ * First see if there are any non-ASCII bytes in the octetString...
+ */
+
+ for (dataptr = data; dataptr < dataend; dataptr ++)
+ if (*dataptr < 0x20 || *dataptr >= 0x7f)
+ break;
+
+ if (*dataptr)
+ {
+ /*
+ * Yes, encode as hex...
+ */
+
+ *buffer = '<';
+
+ for (bufptr = buffer + 1, dataptr = data; bufptr < bufend && dataptr < dataend; dataptr ++)
+ {
+ *bufptr++ = hexdigits[*dataptr >> 4];
+ *bufptr++ = hexdigits[*dataptr & 15];
+ }
+
+ if (bufptr < bufend)
+ *bufptr++ = '>';
+
+ *bufptr = '\0';
+ }
+ else
+ {
+ /*
+ * No, copy as a string...
+ */
+
+ if ((size_t)datalen > bufsize)
+ datalen = (int)bufsize - 1;
+
+ memcpy(buffer, data, datalen);
+ buffer[datalen] = '\0';
+ }
+}
+
+
/*
* 'do_test()' - Do a single test from the test file.
*/
group = ippGetGroupTag(attrptr);
}
- validate_attr(data, data->errors, attrptr);
+ if (!ippValidateAttribute(attrptr))
+ cupsArrayAdd(data->errors, (void *)cupsLastErrorString());
if (ippGetName(attrptr))
{
- if (cupsArrayFind(a, (void *)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));
for (i = data->num_expects, expect = data->expects; i > 0; i --, expect ++)
{
+ ipp_attribute_t *group_found; /* Found parent attribute for group tests */
+
if (expect->if_defined && !_ippVarsGet(vars, expect->if_defined))
continue;
_ippVarsGet(vars, expect->if_not_defined))
continue;
- found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
+ if ((found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL && expect->in_group && expect->in_group != ippGetGroupTag(found))
+ {
+ while ((found = ippFindNextAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL)
+ if (expect->in_group == ippGetGroupTag(found))
+ break;
+ }
do
{
+ group_found = found;
+
+ if (expect->in_group && strchr(expect->name, '/'))
+ {
+ char group_name[256],/* Parent attribute name */
+ *group_ptr; /* Pointer into parent attribute name */
+
+ strlcpy(group_name, expect->name, sizeof(group_name));
+ if ((group_ptr = strchr(group_name, '/')) != NULL)
+ *group_ptr = '\0';
+
+ group_found = ippFindAttribute(response, group_name, IPP_TAG_ZERO);
+ }
+
if ((found && expect->not_expect) ||
(!found && !(expect->not_expect || expect->optional)) ||
(found && !expect_matches(expect, ippGetValueTag(found))) ||
- (found && expect->in_group &&
- ippGetGroupTag(found) != expect->in_group))
+ (group_found && expect->in_group && ippGetGroupTag(group_found) != expect->in_group))
{
if (expect->define_no_match)
_ippVarsSet(vars, expect->define_no_match, "1");
expect->name, expect->of_type,
ippTagString(ippGetValueTag(found)));
- if (expect->in_group && ippGetGroupTag(found) != expect->in_group)
+ if (expect->in_group && ippGetGroupTag(group_found) != expect->in_group)
add_stringf(data->errors, "EXPECTED: %s IN-GROUP %s (got %s).",
expect->name, ippTagString(expect->in_group),
- ippTagString(ippGetGroupTag(found)));
+ ippTagString(ippGetGroupTag(group_found)));
}
}
* Run tests...
*/
- _ippFileParse(vars, testfile, (_ipp_ftoken_cb_t)token_cb, (_ipp_ferror_cb_t)error_cb, (void *)data);
+ _ippFileParse(vars, testfile, (void *)data);
/*
* Close connection and return...
break;
default :
- cupsFilePuts(data->outfile, " \"\"");
+ /* Out-of-band value */
break;
}
}
-/*
- * 'validate_attr()' - Determine whether an attribute is valid.
- */
-
-static int /* O - 1 if valid, 0 otherwise */
-validate_attr(_cups_testdata_t *data, /* I - Test data */
- cups_array_t *errors, /* I - Errors array */
- ipp_attribute_t *attr) /* I - Attribute to validate */
-{
- int i, /* Looping var */
- count; /* Number of values */
- char scheme[64], /* Scheme from URI */
- userpass[256], /* Username/password from URI */
- hostname[256], /* Hostname from URI */
- resource[1024]; /* Resource from URI */
- int port, /* Port number from URI */
- uri_status, /* URI separation status */
- valid = 1; /* Is the attribute valid? */
- const char *name, /* Attribute name */
- *ptr; /* Pointer into string */
- ipp_attribute_t *colattr; /* Collection attribute */
- regex_t re; /* Regular expression */
-
-
- /*
- * Skip separators.
- */
-
- if ((name = ippGetName(attr)) == NULL)
- return (1);
-
- /*
- * Validate the attribute name.
- */
-
- for (ptr = name; *ptr; ptr ++)
- if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' && *ptr != '_')
- break;
-
- if (*ptr || ptr == name)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad attribute name - invalid character "
- "(RFC 2911 section 4.1.3).", name);
- }
-
- if ((ptr - ippGetName(attr)) > 255)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad attribute name - bad length "
- "(RFC 2911 section 4.1.3).", name);
- }
-
- count = ippGetCount(attr);
-
- switch (ippGetValueTag(attr))
- {
- case IPP_TAG_INTEGER :
- break;
-
- case IPP_TAG_BOOLEAN :
- for (i = 0; i < count; i ++)
- {
- int b = ippGetBoolean(attr, i);
- /* Boolean value */
-
- if (b != 0 && b != 1)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad boolen value %d (RFC 2911 section 4.1.11).", name, b);
- }
- }
- break;
-
- case IPP_TAG_ENUM :
- for (i = 0; i < count; i ++)
- {
- if (ippGetInteger(attr, i) < 1)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad enum value %d - out of range (RFC 2911 section 4.1.4).", name, ippGetInteger(attr, i));
- }
- }
- break;
-
- case IPP_TAG_STRING :
- for (i = 0; i < count; i ++)
- {
- int datalen; /* Length of string */
-
- ippGetOctetString(attr, i, &datalen);
- if (datalen > IPP_MAX_OCTETSTRING)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad octetString value - bad length %d (RFC 2911 section 4.1.10).", name, datalen);
- }
- }
- break;
-
- case IPP_TAG_DATE :
- for (i = 0; i < count; i ++)
- {
- const ipp_uchar_t *date = ippGetDate(attr, i);
- /* Current date value */
-
- if (date[2] < 1 || date[2] > 12)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime month %u "
- "(RFC 2911 section 4.1.14).", name, date[2]);
- }
-
- if (date[3] < 1 || date[3] > 31)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime day %u "
- "(RFC 2911 section 4.1.14).", name, date[3]);
- }
-
- if (date[4] > 23)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime hours %u "
- "(RFC 2911 section 4.1.14).", name, date[4]);
- }
-
- if (date[5] > 59)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime minutes %u "
- "(RFC 2911 section 4.1.14).", name, date[5]);
- }
-
- if (date[6] > 60)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime seconds %u "
- "(RFC 2911 section 4.1.14).", name, date[6]);
- }
-
- if (date[7] > 9)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime deciseconds %u "
- "(RFC 2911 section 4.1.14).", name, date[7]);
- }
-
- if (date[8] != '-' && date[8] != '+')
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime UTC sign '%c' "
- "(RFC 2911 section 4.1.14).", name, date[8]);
- }
-
- if (date[9] > 11)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime UTC hours %u "
- "(RFC 2911 section 4.1.14).", name, date[9]);
- }
-
- if (date[10] > 59)
- {
- valid = 0;
-
- add_stringf(data->errors,
- "\"%s\": Bad dateTime UTC minutes %u "
- "(RFC 2911 section 4.1.14).", name, date[10]);
- }
- }
- break;
-
- case IPP_TAG_RESOLUTION :
- for (i = 0; i < count; i ++)
- {
- int xres, yres; /* Resolution values */
- ipp_res_t units; /* Resolution units */
-
- xres = ippGetResolution(attr, i, &yres, &units);
-
- if (xres <= 0)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad resolution value %dx%d%s - cross feed resolution must be positive (RFC 2911 section 4.1.15).", name, xres, yres, units == IPP_RES_PER_INCH ? "dpi" : units == IPP_RES_PER_CM ? "dpcm" : "unknown");
- }
-
- if (yres <= 0)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad resolution value %dx%d%s - feed resolution must be positive (RFC 2911 section 4.1.15).", name, xres, yres, units == IPP_RES_PER_INCH ? "dpi" : units == IPP_RES_PER_CM ? "dpcm" : "unknown");
- }
-
- if (units != IPP_RES_PER_INCH && units != IPP_RES_PER_CM)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad resolution value %dx%d%s - bad units value (RFC 2911 section 4.1.15).", name, xres, yres, units == IPP_RES_PER_INCH ? "dpi" : units == IPP_RES_PER_CM ? "dpcm" : "unknown");
- }
- }
- break;
-
- case IPP_TAG_RANGE :
- for (i = 0; i < count; i ++)
- {
- int lower, upper; /* Range values */
-
- lower = ippGetRange(attr, i, &upper);
-
- if (lower > upper)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad rangeOfInteger value %d-%d - lower greater than upper (RFC 2911 section 4.1.13).", name, lower, upper);
- }
- }
- break;
-
- case IPP_TAG_BEGIN_COLLECTION :
- for (i = 0; i < count; i ++)
- {
- ipp_t *col = ippGetCollection(attr, i);
- /* Collection value */
-
- for (colattr = ippFirstAttribute(col); colattr; colattr = ippNextAttribute(col))
- {
- if (!validate_attr(data, NULL, colattr))
- {
- valid = 0;
- break;
- }
- }
-
- if (colattr && errors)
- {
- add_stringf(data->errors, "\"%s\": Bad collection value.", name);
-
- while (colattr)
- {
- validate_attr(data, errors, colattr);
- colattr = ippNextAttribute(col);
- }
- }
- }
- break;
-
- case IPP_TAG_TEXT :
- case IPP_TAG_TEXTLANG :
- for (i = 0; i < count; i ++)
- {
- const char *s = ippGetString(attr, i, NULL);
- /* Text value */
-
- for (ptr = s; *ptr; ptr ++)
- {
- if ((*ptr & 0xe0) == 0xc0)
- {
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- }
- else if ((*ptr & 0xf0) == 0xe0)
- {
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- }
- else if ((*ptr & 0xf8) == 0xf0)
- {
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- }
- else if (*ptr & 0x80)
- break;
- }
-
- if (*ptr)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad text value \"%s\" - bad UTF-8 sequence (RFC 2911 section 4.1.1).", name, s);
- }
-
- if ((ptr - s) > (IPP_MAX_TEXT - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad text value \"%s\" - bad length %d (RFC 2911 section 4.1.1).", name, s, (int)strlen(s));
- }
- }
- break;
-
- case IPP_TAG_NAME :
- case IPP_TAG_NAMELANG :
- for (i = 0; i < count; i ++)
- {
- const char *s = ippGetString(attr, i, NULL);
- /* Name value */
-
- for (ptr = s; *ptr; ptr ++)
- {
- if ((*ptr & 0xe0) == 0xc0)
- {
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- }
- else if ((*ptr & 0xf0) == 0xe0)
- {
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- }
- else if ((*ptr & 0xf8) == 0xf0)
- {
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- ptr ++;
- if ((*ptr & 0xc0) != 0x80)
- break;
- }
- else if (*ptr & 0x80)
- break;
- }
-
- if (*ptr)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad name value \"%s\" - bad UTF-8 sequence (RFC 2911 section 4.1.2).", name, s);
- }
-
- if ((ptr - s) > (IPP_MAX_NAME - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad name value \"%s\" - bad length %d (RFC 2911 section 4.1.2).", name, s, (int)strlen(s));
- }
- }
- break;
-
- case IPP_TAG_KEYWORD :
- for (i = 0; i < count; i ++)
- {
- const char *keyword = ippGetString(attr, i, NULL);
- /* Keyword value */
-
- for (ptr = keyword; *ptr; ptr ++)
- if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' &&
- *ptr != '_')
- break;
-
- if (*ptr || ptr == keyword)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad keyword value \"%s\" - invalid character (RFC 2911 section 4.1.3).", name, keyword);
- }
-
- if ((ptr - keyword) > (IPP_MAX_KEYWORD - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad keyword value \"%s\" - bad length %d (RFC 2911 section 4.1.3).", name, keyword, (int)strlen(keyword));
- }
- }
- break;
-
- case IPP_TAG_URI :
- for (i = 0; i < count; i ++)
- {
- const char *uri = ippGetString(attr, i, NULL);
- /* URI value */
-
- uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource));
-
- if (uri_status < HTTP_URI_OK)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad URI value \"%s\" - %s (RFC 2911 section 4.1.5).", name, uri, httpURIStatusString(uri_status));
- }
-
- if (strlen(uri) > (IPP_MAX_URI - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad URI value \"%s\" - bad length %d (RFC 2911 section 4.1.5).", name, uri, (int)strlen(uri));
- }
- }
- break;
-
- case IPP_TAG_URISCHEME :
- for (i = 0; i < count; i ++)
- {
- const char *urischeme = ippGetString(attr, i, NULL);
- /* URI scheme value */
-
- ptr = urischeme;
- if (islower(*ptr & 255))
- {
- for (ptr ++; *ptr; ptr ++)
- if (!islower(*ptr & 255) && !isdigit(*ptr & 255) &&
- *ptr != '+' && *ptr != '-' && *ptr != '.')
- break;
- }
-
- if (*ptr || ptr == urischeme)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad uriScheme value \"%s\" - bad characters (RFC 2911 section 4.1.6).", name, urischeme);
- }
-
- if ((ptr - urischeme) > (IPP_MAX_URISCHEME - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad uriScheme value \"%s\" - bad length %d (RFC 2911 section 4.1.6).", name, urischeme, (int)strlen(urischeme));
- }
- }
- break;
-
- case IPP_TAG_CHARSET :
- for (i = 0; i < count; i ++)
- {
- const char *charset = ippGetString(attr, i, NULL);
- /* Charset value */
-
- for (ptr = charset; *ptr; ptr ++)
- if (!isprint(*ptr & 255) || isupper(*ptr & 255) ||
- isspace(*ptr & 255))
- break;
-
- if (*ptr || ptr == charset)
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad charset value \"%s\" - bad characters (RFC 2911 section 4.1.7).", name, charset);
- }
-
- if ((ptr - charset) > (IPP_MAX_CHARSET - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad charset value \"%s\" - bad length %d (RFC 2911 section 4.1.7).", name, charset, (int)strlen(charset));
- }
- }
- break;
-
- case IPP_TAG_LANGUAGE :
- /*
- * The following regular expression is derived from the ABNF for
- * language tags in RFC 4646. All I can say is that this is the
- * easiest way to check the values...
- */
-
- if ((i = regcomp(&re,
- "^("
- "(([a-z]{2,3}(-[a-z][a-z][a-z]){0,3})|[a-z]{4,8})"
- /* language */
- "(-[a-z][a-z][a-z][a-z]){0,1}" /* script */
- "(-([a-z][a-z]|[0-9][0-9][0-9])){0,1}" /* region */
- "(-([a-z]{5,8}|[0-9][0-9][0-9]))*" /* variant */
- "(-[a-wy-z](-[a-z0-9]{2,8})+)*" /* extension */
- "(-x(-[a-z0-9]{1,8})+)*" /* privateuse */
- "|"
- "x(-[a-z0-9]{1,8})+" /* privateuse */
- "|"
- "[a-z]{1,3}(-[a-z][0-9]{2,8}){1,2}" /* grandfathered */
- ")$",
- REG_NOSUB | REG_EXTENDED)) != 0)
- {
- char temp[256]; /* Temporary error string */
-
- regerror(i, &re, temp, sizeof(temp));
- print_fatal_error(data, "Unable to compile naturalLanguage regular "
- "expression: %s.", temp);
- break;
- }
-
- for (i = 0; i < count; i ++)
- {
- const char *lang = ippGetString(attr, i, NULL);
- /* Language string */
-
- if (regexec(&re, lang, 0, NULL, 0))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad naturalLanguage value \"%s\" - bad characters (RFC 2911 section 4.1.8).", name, lang);
- }
-
- if (strlen(lang) > (IPP_MAX_LANGUAGE - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad naturalLanguage value \"%s\" - bad length %d (RFC 2911 section 4.1.8).", name, lang, (int)strlen(lang));
- }
- }
-
- regfree(&re);
- break;
-
- case IPP_TAG_MIMETYPE :
- /*
- * The following regular expression is derived from the ABNF for
- * language tags in RFC 2045 and 4288. All I can say is that this is
- * the easiest way to check the values...
- */
-
- if ((i = regcomp(&re,
- "^"
- "[-a-zA-Z0-9!#$&.+^_]{1,127}" /* type-name */
- "/"
- "[-a-zA-Z0-9!#$&.+^_]{1,127}" /* subtype-name */
- "(;[-a-zA-Z0-9!#$&.+^_]{1,127}=" /* parameter= */
- "([-a-zA-Z0-9!#$&.+^_]{1,127}|\"[^\"]*\"))*"
- /* value */
- "$",
- REG_NOSUB | REG_EXTENDED)) != 0)
- {
- char temp[256]; /* Temporary error string */
-
- regerror(i, &re, temp, sizeof(temp));
- print_fatal_error(data, "Unable to compile mimeMediaType regular "
- "expression: %s.", temp);
- break;
- }
-
- for (i = 0; i < count; i ++)
- {
- const char *mimetype = ippGetString(attr, i, NULL);
- /* Mime media type string */
-
- if (regexec(&re, mimetype, 0, NULL, 0))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad mimeMediaType value \"%s\" - bad characters (RFC 2911 section 4.1.9).", name, mimetype);
- }
-
- if (strlen(mimetype) > (IPP_MAX_MIMETYPE - 1))
- {
- valid = 0;
-
- add_stringf(data->errors, "\"%s\": Bad mimeMediaType value \"%s\" - bad length %d (RFC 2911 section 4.1.9).", name, mimetype, (int)strlen(mimetype));
- }
- }
-
- regfree(&re);
- break;
-
- default :
- break;
- }
-
- return (valid);
-}
-
-
/*
* 'with_flags_string()' - Return the "WITH-xxx" predicate that corresponds to
the flags.
{
case IPP_TAG_INTEGER :
case IPP_TAG_ENUM :
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
char op, /* Comparison operator */
*nextptr; /* Next pointer */
if (!match && errors)
{
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
add_stringf(data->errors, "GOT: %s=%d", name, ippGetInteger(attr, i));
}
break;
case IPP_TAG_RANGE :
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
char op, /* Comparison operator */
*nextptr; /* Next pointer */
if (!match && errors)
{
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
int lower, upper; /* Range values */
break;
case IPP_TAG_BOOLEAN :
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
if ((!strcmp(value, "true")) == ippGetBoolean(attr, i))
{
if (!match && errors)
{
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
add_stringf(data->errors, "GOT: %s=%s", name, ippGetBoolean(attr, i) ? "true" : "false");
}
break;
case IPP_TAG_RESOLUTION :
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
int xres, yres; /* Resolution values */
ipp_res_t units; /* Resolution units */
if (!match && errors)
{
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
int xres, yres; /* Resolution values */
ipp_res_t units; /* Resolution units */
* See if ALL of the values match the given regular expression.
*/
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
if (!regexec(&re, get_string(attr, i, flags, temp, sizeof(temp)),
0, NULL, 0))
* Value is a literal URI string, see if the value(s) match...
*/
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
if (!compare_uris(value, get_string(attr, i, flags, temp, sizeof(temp))))
{
* Value is a literal string, see if the value(s) match...
*/
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
{
int result;
if (!match && errors)
{
- for (i = 0; i < ippGetCount(attr); i ++)
+ for (i = 0; i < count; i ++)
add_stringf(data->errors, "GOT: %s=\"%s\"", name, ippGetString(attr, i, NULL));
}
break;
+ case IPP_TAG_STRING :
+ {
+ unsigned char withdata[1023], /* WITH-VALUE data */
+ *adata; /* Pointer to octetString data */
+ int withlen, /* Length of WITH-VALUE data */
+ adatalen; /* Length of octetString */
+
+ if (*value == '<')
+ {
+ /*
+ * Grab hex-encoded value...
+ */
+
+ if ((withlen = (int)strlen(value)) & 1 || withlen > (int)(2 * (sizeof(withdata) + 1)))
+ {
+ print_fatal_error(data, "Bad WITH-VALUE hex value.");
+ return (0);
+ }
+
+ withlen = withlen / 2 - 1;
+
+ for (valptr = value + 1, adata = withdata; *valptr; valptr += 2)
+ {
+ int ch; /* Current character/byte */
+
+ if (isdigit(valptr[0]))
+ ch = (valptr[0] - '0') << 4;
+ else if (isalpha(valptr[0]))
+ ch = (tolower(valptr[0]) - 'a' + 10) << 4;
+ else
+ break;
+
+ if (isdigit(valptr[1]))
+ ch |= valptr[1] - '0';
+ else if (isalpha(valptr[1]))
+ ch |= tolower(valptr[1]) - 'a' + 10;
+ else
+ break;
+
+ *adata++ = (unsigned char)ch;
+ }
+
+ if (*valptr)
+ {
+ print_fatal_error(data, "Bad WITH-VALUE hex value.");
+ return (0);
+ }
+ }
+ else
+ {
+ /*
+ * Copy literal string value...
+ */
+
+ withlen = (int)strlen(value);
+
+ memcpy(withdata, value, withlen);
+ }
+
+ for (i = 0; i < count; i ++)
+ {
+ adata = ippGetOctetString(attr, i, &adatalen);
+
+ if (withlen == adatalen && !memcmp(withdata, adata, (size_t)withlen))
+ {
+ if (!matchbuf[0])
+ copy_hex_string(matchbuf, adata, adatalen, matchlen);
+
+ if (!(flags & _CUPS_WITH_ALL))
+ {
+ match = 1;
+ break;
+ }
+ }
+ else if (flags & _CUPS_WITH_ALL)
+ {
+ match = 0;
+ break;
+ }
+ }
+
+ if (!match && errors)
+ {
+ for (i = 0; i < count; i ++)
+ {
+ adata = ippGetOctetString(attr, i, &adatalen);
+ copy_hex_string(temp, adata, adatalen, sizeof(temp));
+ add_stringf(data->errors, "GOT: %s=\"%s\"", name, temp);
+ }
+ }
+ }
+ break;
+
default :
break;
}