]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
The `cupsCopyDestConflicts` function now handles collection attribute
authorMichael R Sweet <michaelrsweet@gmail.com>
Thu, 14 Dec 2017 22:06:24 +0000 (17:06 -0500)
committerMichael R Sweet <michaelrsweet@gmail.com>
Thu, 14 Dec 2017 22:06:24 +0000 (17:06 -0500)
("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.

CHANGES.md
cups/dest-options.c
cups/encode.c

index 6f3657e3b28779f0cd67b16491dd0aeb3a4ffd74..411340972d4500ca7ea4d63feb632054e805ffd8 100644 (file)
@@ -7,6 +7,8 @@ Changes in CUPS v2.3b1
 
 - CUPS is now provided under the Apache License, Version 2.0.
 - Documentation updates (Issue #4580, Issue #5177, Issue #5192)
+- The `cupsCopyDestConflicts` function now handles collection attribute
+  ("media-col", "finishings-col", etc.) constraints (Issue #4096)
 - The `lpoptions` command incorrectly saved default options (Issue #4717)
 - The `lpstat` command now reports when new jobs are being held (Issue #4761)
 - The `ippfind` command now supports finding printers whose name starts with an
index ea1067408fca8da3e42dc681e0d5a91a747a7f34..2eec872ccfbea850d6fdfe7cfb4b9277b51fe73d 100644 (file)
@@ -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);
 
  /*
@@ -1350,6 +1346,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);
       }
     }
 
index 55152690d438a228dacc44478766fde4995f7c9f..d18389e650fc6dbdf7e3dfac730698476025ad32 100644 (file)
@@ -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;
     }
 
    /*