diff options
author | Michael R Sweet <michaelrsweet@gmail.com> | 2017-12-14 17:06:24 -0500 |
---|---|---|
committer | Michael R Sweet <michaelrsweet@gmail.com> | 2017-12-14 17:06:24 -0500 |
commit | 336b669e2efbaf8212f5354a21eb6bf954a3f051 (patch) | |
tree | d1c7d00f1606d5cb1f4d7829674a41ef0cbfdc8b /cups | |
parent | 841a2216d922dbb284233656c4395eb1ffa7b2f9 (diff) | |
download | cups-336b669e2efbaf8212f5354a21eb6bf954a3f051.tar.gz |
The `cupsCopyDestConflicts` function now handles collection attribute
("media-col", "finishings-col", etc.) constraints (Issue #4096)
cups/dest-options.c:
- Add cups_collection_contains and cups_collection_string functions.
- Implement collection checking in cups_test_constraints.
cups/encode.c:
- Remove unused variable and assignments in cupsEncodeOptions2.
Diffstat (limited to 'cups')
-rw-r--r-- | cups/dest-options.c | 402 | ||||
-rw-r--r-- | cups/encode.c | 8 |
2 files changed, 364 insertions, 46 deletions
diff --git a/cups/dest-options.c b/cups/dest-options.c index ea1067408..2eec872cc 100644 --- a/cups/dest-options.c +++ b/cups/dest-options.c @@ -25,6 +25,8 @@ */ static void cups_add_dconstres(cups_array_t *a, ipp_t *collection); +static int cups_collection_contains(ipp_t *test, ipp_t *match); +static size_t cups_collection_string(ipp_attribute_t *attr, char *buffer, size_t bufsize); static int cups_compare_dconstres(_cups_dconstres_t *a, _cups_dconstres_t *b); static int cups_compare_media_db(_cups_media_db_t *a, @@ -1294,25 +1296,19 @@ cupsGetDestMediaDefault( * Get the default media size, if any... */ - if ((media = cupsGetOption("media", dest->num_options, - dest->options)) == NULL) + if ((media = cupsGetOption("media", dest->num_options, dest->options)) == NULL) media = "na_letter_8.5x11in"; if (cupsGetDestMediaByName(http, dest, dinfo, media, flags, size)) return (1); - if (strcmp(media, "na_letter_8.5x11in") && - cupsGetDestMediaByName(http, dest, dinfo, "iso_a4_210x297mm", flags, - size)) + if (strcmp(media, "na_letter_8.5x11in") && cupsGetDestMediaByName(http, dest, dinfo, "iso_a4_210x297mm", flags, size)) return (1); - if (strcmp(media, "iso_a4_210x297mm") && - cupsGetDestMediaByName(http, dest, dinfo, "na_letter_8.5x11in", flags, - size)) + if (strcmp(media, "iso_a4_210x297mm") && cupsGetDestMediaByName(http, dest, dinfo, "na_letter_8.5x11in", flags, size)) return (1); - if ((flags & CUPS_MEDIA_FLAGS_BORDERLESS) && - cupsGetDestMediaByName(http, dest, dinfo, "na_index_4x6in", flags, size)) + if ((flags & CUPS_MEDIA_FLAGS_BORDERLESS) && cupsGetDestMediaByName(http, dest, dinfo, "na_index_4x6in", flags, size)) return (1); /* @@ -1351,6 +1347,333 @@ cups_add_dconstres( /* + * 'cups_collection_contains()' - Check whether test collection is contained in the matching collection. + */ + +static int /* O - 1 on a match, 0 on a non-match */ +cups_collection_contains(ipp_t *test, /* I - Collection to test */ + ipp_t *match) /* I - Matching values */ +{ + int i, /* Looping var */ + count; /* Number of test values */ + ipp_attribute_t *tattr, /* Testing attribute */ + *mattr; /* Matching attribute */ + const char *tval; /* Testing string value */ + + + for (mattr = ippFirstAttribute(match); mattr; mattr = ippNextAttribute(match)) + { + if ((tattr = ippFindAttribute(test, ippGetName(mattr), IPP_TAG_ZERO)) == NULL) + return (0); + + count = ippGetCount(tattr); + + switch (ippGetValueTag(mattr)) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + if (ippGetValueTag(tattr) != ippGetValueTag(mattr)) + return (0); + + for (i = 0; i < count; i ++) + { + if (!ippContainsInteger(mattr, ippGetInteger(tattr, i))) + return (0); + } + break; + + case IPP_TAG_RANGE : + if (ippGetValueTag(tattr) != IPP_TAG_INTEGER) + return (0); + + for (i = 0; i < count; i ++) + { + if (!ippContainsInteger(mattr, ippGetInteger(tattr, i))) + return (0); + } + break; + + case IPP_TAG_BOOLEAN : + if (ippGetValueTag(tattr) != IPP_TAG_BOOLEAN || ippGetBoolean(tattr, 0) != ippGetBoolean(mattr, 0)) + return (0); + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + for (i = 0; i < count; i ++) + { + if ((tval = ippGetString(tattr, i, NULL)) == NULL || !ippContainsString(mattr, tval)) + return (0); + } + break; + + default : + return (0); + } + } + + return (1); +} + + +/* + * 'cups_collection_string()' - Convert an IPP collection to an option string. + */ + +static size_t /* O - Number of bytes needed */ +cups_collection_string( + ipp_attribute_t *attr, /* I - Collection attribute */ + char *buffer, /* I - String buffer */ + size_t bufsize) /* I - Size of buffer */ +{ + int i, j, /* Looping vars */ + count, /* Number of collection values */ + mcount; /* Number of member values */ + ipp_t *col; /* Collection */ + ipp_attribute_t *first, /* First member attribute */ + *member; /* Member attribute */ + char *bufptr, /* Pointer into buffer */ + *bufend, /* End of buffer */ + temp[100]; /* Temporary string */ + const char *mptr; /* Pointer into member value */ + int mlen; /* Length of octetString */ + + + bufptr = buffer; + bufend = buffer + bufsize - 1; + + for (i = 0, count = ippGetCount(attr); i < count; i ++) + { + col = ippGetCollection(attr, i); + + if (i) + { + if (bufptr < bufend) + *bufptr++ = ','; + else + bufptr ++; + } + + if (bufptr < bufend) + *bufptr++ = '{'; + else + bufptr ++; + + for (member = first = ippFirstAttribute(col); member; member = ippNextAttribute(col)) + { + const char *mname = ippGetName(member); + + if (member != first) + { + if (bufptr < bufend) + *bufptr++ = ' '; + else + bufptr ++; + } + + if (ippGetValueTag(member) == IPP_TAG_BOOLEAN) + { + if (!ippGetBoolean(member, 0)) + { + if (bufptr < bufend) + strlcpy(bufptr, "no", bufend - bufptr + 1); + bufptr += 2; + } + + if (bufptr < bufend) + strlcpy(bufptr, mname, bufend - bufptr + 1); + bufptr += strlen(mname); + continue; + } + + if (bufptr < bufend) + strlcpy(bufptr, mname, bufend - bufptr + 1); + bufptr += strlen(mname); + + if (bufptr < bufend) + *bufptr++ = '='; + else + bufptr ++; + + if (ippGetValueTag(member) == IPP_TAG_BEGIN_COLLECTION) + { + /* + * Convert sub-collection... + */ + + bufptr += cups_collection_string(member, bufptr, bufptr < bufend ? (size_t)(bufend - bufptr + 1) : 0); + } + else + { + /* + * Convert simple type... + */ + + for (j = 0, mcount = ippGetCount(member); j < mcount; j ++) + { + if (j) + { + if (bufptr < bufend) + *bufptr++ = ','; + else + bufptr ++; + } + + switch (ippGetValueTag(member)) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + bufptr += snprintf(bufptr, bufptr < bufend ? (bufend - bufptr + 1) : 0, "%d", ippGetInteger(member, j)); + break; + + case IPP_TAG_STRING : + if (bufptr < bufend) + *bufptr++ = '\"'; + else + bufptr ++; + + for (mptr = (const char *)ippGetOctetString(member, j, &mlen); mlen > 0; mlen --, mptr ++) + { + if (*mptr == '\"' || *mptr == '\\') + { + if (bufptr < bufend) + *bufptr++ = '\\'; + else + bufptr ++; + } + + if (bufptr < bufend) + *bufptr++ = *mptr; + else + bufptr ++; + } + + if (bufptr < bufend) + *bufptr++ = '\"'; + else + bufptr ++; + break; + + case IPP_TAG_DATE : + { + unsigned year; /* Year */ + const ipp_uchar_t *date = ippGetDate(member, j); + /* Date value */ + + year = ((unsigned)date[0] << 8) + (unsigned)date[1]; + + if (date[9] == 0 && date[10] == 0) + snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ", year, date[2], date[3], date[4], date[5], date[6]); + else + snprintf(temp, sizeof(temp), "%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]); + + if (buffer && bufptr < bufend) + strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1)); + + bufptr += strlen(temp); + } + break; + + case IPP_TAG_RESOLUTION : + { + int xres, /* Horizontal resolution */ + yres; /* Vertical resolution */ + ipp_res_t units; /* Resolution units */ + + xres = ippGetResolution(member, j, &yres, &units); + + if (xres == yres) + snprintf(temp, sizeof(temp), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); + else + snprintf(temp, sizeof(temp), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); + + if (buffer && bufptr < bufend) + strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1)); + + bufptr += strlen(temp); + } + break; + + case IPP_TAG_RANGE : + { + int lower, /* Lower bound */ + upper; /* Upper bound */ + + lower = ippGetRange(member, j, &upper); + + snprintf(temp, sizeof(temp), "%d-%d", lower, upper); + + if (buffer && bufptr < bufend) + strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1)); + + bufptr += strlen(temp); + } + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + if (bufptr < bufend) + *bufptr++ = '\"'; + else + bufptr ++; + + for (mptr = ippGetString(member, j, NULL); *mptr; mptr ++) + { + if (*mptr == '\"' || *mptr == '\\') + { + if (bufptr < bufend) + *bufptr++ = '\\'; + else + bufptr ++; + } + + if (bufptr < bufend) + *bufptr++ = *mptr; + else + bufptr ++; + } + + if (bufptr < bufend) + *bufptr++ = '\"'; + else + bufptr ++; + break; + + default : + break; + } + } + } + } + + if (bufptr < bufend) + *bufptr++ = '}'; + else + bufptr ++; + } + + *bufptr = '\0'; + return ((size_t)(bufptr - buffer + 1)); +} + + +/* * 'cups_compare_dconstres()' - Compare to resolver entries. */ @@ -1537,8 +1860,6 @@ cups_create_constraints( /* * 'cups_create_defaults()' - Create the -default option array. - * - * TODO: Need to support collection defaults... */ static void @@ -1557,32 +1878,26 @@ cups_create_defaults( * xxx=value to the defaults option array. */ - for (attr = ippFirstAttribute(dinfo->attrs); - attr; - attr = ippNextAttribute(dinfo->attrs)) + for (attr = ippFirstAttribute(dinfo->attrs); attr; attr = ippNextAttribute(dinfo->attrs)) { - if (!attr->name || attr->group_tag != IPP_TAG_PRINTER) - continue; - - if (attr->value_tag == IPP_TAG_BEGIN_COLLECTION) - continue; /* TODO: STR #4096 */ - - if ((nameptr = attr->name + strlen(attr->name) - 8) <= attr->name || - strcmp(nameptr, "-default")) + if (!ippGetName(attr) || ippGetGroupTag(attr) != IPP_TAG_PRINTER) continue; - strlcpy(name, attr->name, sizeof(name)); - if ((nameptr = name + strlen(name) - 8) <= name || - strcmp(nameptr, "-default")) + strlcpy(name, ippGetName(attr), sizeof(name)); + if ((nameptr = name + strlen(name) - 8) <= name || strcmp(nameptr, "-default")) continue; *nameptr = '\0'; - if (ippAttributeString(attr, value, sizeof(value)) >= sizeof(value)) + if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION) + { + if (cups_collection_string(attr, value, sizeof(value)) >= sizeof(value)) + continue; + } + else if (ippAttributeString(attr, value, sizeof(value)) >= sizeof(value)) continue; - dinfo->num_defaults = cupsAddOption(name, value, dinfo->num_defaults, - &dinfo->defaults); + dinfo->num_defaults = cupsAddOption(name, value, dinfo->num_defaults, &dinfo->defaults); } } @@ -2198,8 +2513,6 @@ cups_is_close_media_db( /* * 'cups_test_constraints()' - Test constraints. - * - * TODO: STR #4096 - Need to properly support media-col contraints... */ static cups_array_t * /* O - Active constraints */ @@ -2213,11 +2526,13 @@ cups_test_constraints( cups_option_t **conflicts) /* O - Conflicting options */ { int i, /* Looping var */ + count, /* Number of values */ match; /* Value matches? */ int num_matching; /* Number of matching options */ cups_option_t *matching; /* Matching options */ _cups_dconstres_t *c; /* Current constraint */ cups_array_t *active = NULL; /* Active constraints */ + ipp_t *col; /* Collection value */ ipp_attribute_t *attr; /* Current attribute */ _ipp_value_t *attrval; /* Current attribute value */ const char *value; /* Current value */ @@ -2239,17 +2554,13 @@ cups_test_constraints( attr; attr = ippNextAttribute(c->collection)) { - if (attr->value_tag == IPP_TAG_BEGIN_COLLECTION) - break; /* TODO: STR #4096 */ - /* * Get the value for the current attribute in the constraint... */ if (new_option && new_value && !strcmp(attr->name, new_option)) value = new_value; - else if ((value = cupsGetOption(attr->name, num_options, - options)) == NULL) + else if ((value = cupsGetOption(attr->name, num_options, options)) == NULL) value = cupsGetOption(attr->name, dinfo->num_defaults, dinfo->defaults); if (!value) @@ -2364,6 +2675,22 @@ cups_test_constraints( } break; + case IPP_TAG_BEGIN_COLLECTION : + col = ippNew(); + _cupsEncodeOption(col, IPP_TAG_ZERO, NULL, ippGetName(attr), value); + + for (i = 0, count = ippGetCount(attr); i < count; i ++) + { + if (cups_collection_contains(col, ippGetCollection(attr, i))) + { + match = 1; + break; + } + } + + ippDelete(col); + break; + default : break; } @@ -2386,8 +2713,7 @@ cups_test_constraints( cups_option_t *moption; /* Matching option */ for (i = num_matching, moption = matching; i > 0; i --, moption ++) - *num_conflicts = cupsAddOption(moption->name, moption->value, - *num_conflicts, conflicts); + *num_conflicts = cupsAddOption(moption->name, moption->value, *num_conflicts, conflicts); } } diff --git a/cups/encode.c b/cups/encode.c index 55152690d..d18389e65 100644 --- a/cups/encode.c +++ b/cups/encode.c @@ -668,7 +668,6 @@ cupsEncodeOptions2( { int i; /* Looping var */ char *val; /* Pointer to option value */ - ipp_tag_t value_tag; /* IPP value tag */ cups_option_t *option; /* Current option */ ipp_op_t op; /* Operation for this request */ const ipp_op_t *ops; /* List of allowed operations */ @@ -727,8 +726,6 @@ cupsEncodeOptions2( if (match->group_tag != group_tag && match->alt_group_tag != group_tag) continue; - value_tag = match->value_tag; - if (match->operations) ops = match->operations; else if (group_tag == IPP_TAG_JOB) @@ -771,11 +768,6 @@ cupsEncodeOptions2( ops = ipp_doc_creation; else ops = ipp_set_printer; - - if (!_cups_strcasecmp(option->value, "true") || !_cups_strcasecmp(option->value, "false")) - value_tag = IPP_TAG_BOOLEAN; - else - value_tag = IPP_TAG_NAME; } /* |