summaryrefslogtreecommitdiff
path: root/cups
diff options
context:
space:
mode:
authorMichael R Sweet <michaelrsweet@gmail.com>2017-12-14 17:06:24 -0500
committerMichael R Sweet <michaelrsweet@gmail.com>2017-12-14 17:06:24 -0500
commit336b669e2efbaf8212f5354a21eb6bf954a3f051 (patch)
treed1c7d00f1606d5cb1f4d7829674a41ef0cbfdc8b /cups
parent841a2216d922dbb284233656c4395eb1ffa7b2f9 (diff)
downloadcups-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.c402
-rw-r--r--cups/encode.c8
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;
}
/*