]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add support for limits in OF-TYPE syntax strings (Issue #153)
authorMichael R Sweet <michael.r.sweet@gmail.com>
Thu, 1 Apr 2021 17:57:16 +0000 (13:57 -0400)
committerMichael R Sweet <michael.r.sweet@gmail.com>
Thu, 1 Apr 2021 17:57:16 +0000 (13:57 -0400)
doc/help/man-ipptoolfile.html
man/ipptoolfile.5
tools/ipptool.c

index 1ab401691b89cec012d28ec8f09d8055881cdceb..35ad6f873573d6533b22fa81f01e8981da987cc7 100644 (file)
@@ -233,8 +233,9 @@ The following predicates are understood following the <b>EXPECT</b> test directi
 <dd style="margin-left: 5.0em">Makes the <b>EXPECT</b> conditions apply only if the specified variable is not defined.
 <dt><b>IN-GROUP </b><i>tag</i>
 <dd style="margin-left: 5.0em">Requires the <b>EXPECT</b> attribute to be in the specified group tag.
-<dt><b>OF-TYPE </b><i>tag[|tag,...]</i>
+<dt><b>OF-TYPE </b><i>tag[(limits)|tag|...]</i>
 <dd style="margin-left: 5.0em">Requires the <b>EXPECT</b> attribute to use one of the specified value tag(s).
+Most value tags also support the specification of limits in parenthesis, for example "name(42)" would allow nameWith/WithoutLanguage strings up to 42 octets in length, "name(4:MAX)" would allow nameWith/WithoutLanguage strings between 4 and 255 octets in length, and "integer(-273:MAX)" would allow integers between -273 and 2147483647.
 <dt><b>REPEAT-LIMIT </b><i>number</i>
 <dd style="margin-left: 5.0em"><br>
 Specifies the maximum number of times to repeat if the <b>REPEAT-MATCH</b> or <b>REPEAT-NO-MATCH</b> predicate is specified. The default value is 1000.
index 76496b4838a0ca358a9c7cd84d70e9696868dcc1..000eaa5323ba1f42c93747b394e659a28403e125 100644 (file)
@@ -299,8 +299,9 @@ Makes the \fBEXPECT\fR conditions apply only if the specified variable is not de
 \fBIN\-GROUP \fItag\fR
 Requires the \fBEXPECT\fR attribute to be in the specified group tag.
 .TP 5
-\fBOF\-TYPE \fItag[|tag,...]\fR
+\fBOF\-TYPE \fItag[(limits)|tag|...]\fR
 Requires the \fBEXPECT\fR attribute to use one of the specified value tag(s).
+Most value tags also support the specification of limits in parenthesis, for example "name(42)" would allow nameWith/WithoutLanguage strings up to 42 octets in length, "name(4:MAX)" would allow nameWith/WithoutLanguage strings between 4 and 255 octets in length, and "integer(-273:MAX)" would allow integers between -273 and 2147483647.
 .TP 5
 \fBREPEAT\-LIMIT \fInumber\fR
 .br
index 6820fd460c9df616e524967ba8fd91df478cffb6..7de51e6c11899a975e45d8e98163f7b41adf9e34 100644 (file)
@@ -184,7 +184,7 @@ static void *do_monitor_printer_state(ipptool_test_t *data);
 static int     do_test(_ipp_file_t *f, ipptool_test_t *data);
 static int     do_tests(const char *testfile, ipptool_test_t *data);
 static int     error_cb(_ipp_file_t *f, ipptool_test_t *data, const char *error);
-static int      expect_matches(ipptool_expect_t *expect, ipp_tag_t value_tag);
+static int      expect_matches(ipptool_expect_t *expect, ipp_attribute_t *attr);
 static char    *get_filename(const char *testfile, char *dst, const char *src, size_t dstsize);
 static const char *get_string(ipp_attribute_t *attr, int element, int flags, char *buffer, size_t bufsize);
 static void    init_data(ipptool_test_t *data);
@@ -1044,7 +1044,7 @@ do_monitor_printer_state(
 
       if ((found && expect->not_expect) ||
          (!found && !(expect->not_expect || expect->optional)) ||
-         (found && !expect_matches(expect, ippGetValueTag(found))) ||
+         (found && !expect_matches(expect, found)) ||
          (expect->in_group && ippGetGroupTag(found) != expect->in_group) ||
          (expect->with_distinct && !with_distinct_values(NULL, found)))
       {
@@ -1737,7 +1737,7 @@ do_test(_ipp_file_t    *f,                /* I - IPP data file */
 
          if ((found && expect->not_expect) ||
              (!found && !(expect->not_expect || expect->optional)) ||
-             (found && !expect_matches(expect, ippGetValueTag(found))) ||
+             (found && !expect_matches(expect, found)) ||
              (group_found && expect->in_group && ippGetGroupTag(group_found) != expect->in_group) ||
              (expect->with_distinct && !with_distinct_values(NULL, found)))
          {
@@ -1751,7 +1751,7 @@ do_test(_ipp_file_t    *f,                /* I - IPP data file */
                add_stringf(data->errors, "EXPECTED: %s", expect->name);
              else if (found)
              {
-               if (!expect_matches(expect, ippGetValueTag(found)))
+               if (!expect_matches(expect, found))
                  add_stringf(data->errors, "EXPECTED: %s OF-TYPE %s (got %s)",
                              expect->name, expect->of_type,
                              ippTagString(ippGetValueTag(found)));
@@ -2271,12 +2271,17 @@ error_cb(_ipp_file_t      *f,           /* I - IPP file data */
 static int                             /* O - 1 if matches, 0 otherwise */
 expect_matches(
     ipptool_expect_t *expect,          /* I - Expected attribute */
-    ipp_tag_t      value_tag)          /* I - Value tag for attribute */
+    ipp_attribute_t  *attr)            /* I - Attribute */
 {
-  int  match;                          /* Match? */
-  char *of_type,                       /* Type name to match */
-       *next,                          /* Next name to match */
-       sep;                            /* Separator character */
+  int          i,                      /* Looping var */
+               count,                  /* Number of values */
+               match;                  /* Match? */
+  char         *of_type,               /* Type name to match */
+               *paren,                 /* Pointer to opening parenthesis */
+               *next,                  /* Next name to match */
+               sep;                    /* Separator character */
+  ipp_tag_t    value_tag;              /* Syntax/value tag */
+  int          lower, upper;           /* Lower and upper bounds for syntax */
 
 
  /*
@@ -2291,6 +2296,9 @@ expect_matches(
   * types separated by "," or "|"...
   */
 
+  value_tag = ippGetValueTag(attr);
+  count     = ippGetCount(attr);
+
   for (of_type = expect->of_type, match = 0; !match && *of_type; of_type = next)
   {
    /*
@@ -2306,19 +2314,154 @@ expect_matches(
     * Support some meta-types to make it easier to write the test file.
     */
 
+    if ((paren = strchr(of_type, '(')) != NULL)
+    {
+      char *ptr;                       // Pointer into syntax string
+
+      *paren = '\0';
+
+      if (!strncmp(paren + 1, "MIN:", 4))
+      {
+        lower = INT_MIN;
+        ptr   = paren + 5;
+      }
+      else if ((ptr = strchr(paren + 1, ':')) != NULL)
+      {
+        lower = atoi(paren + 1);
+      }
+      else
+      {
+        lower = 0;
+        ptr   = paren + 1;
+      }
+
+      if (!strcmp(ptr, "MAX)"))
+        upper = INT_MAX;
+      else
+        upper = atoi(ptr);
+    }
+    else
+    {
+      lower = INT_MIN;
+      upper = INT_MAX;
+    }
+
     if (!strcmp(of_type, "text"))
-      match = value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_TEXT;
+    {
+      if (upper == INT_MAX)
+        upper = 1023;
+
+      if (value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_TEXT)
+      {
+        for (i = 0; i < count; i ++)
+       {
+         if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
+           break;
+       }
+
+       match = (i == count);
+      }
+    }
     else if (!strcmp(of_type, "name"))
-      match = value_tag == IPP_TAG_NAMELANG || value_tag == IPP_TAG_NAME;
+    {
+      if (upper == INT_MAX)
+        upper = 255;
+
+      if (value_tag == IPP_TAG_NAMELANG || value_tag == IPP_TAG_NAME)
+      {
+        for (i = 0; i < count; i ++)
+       {
+         if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
+           break;
+       }
+
+       match = (i == count);
+      }
+    }
     else if (!strcmp(of_type, "collection"))
+    {
       match = value_tag == IPP_TAG_BEGIN_COLLECTION;
-    else
-      match = value_tag == ippTagValue(of_type);
+    }
+    else if (value_tag == ippTagValue(of_type))
+    {
+      switch (value_tag)
+      {
+        case IPP_TAG_KEYWORD :
+        case IPP_TAG_URI :
+            if (upper == INT_MAX)
+            {
+              if (value_tag == IPP_TAG_KEYWORD)
+               upper = 255;
+             else
+               upper = 1023;
+           }
+
+           for (i = 0; i < count; i ++)
+           {
+             if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
+               break;
+           }
+
+           match = (i == count);
+           break;
+
+        case IPP_TAG_STRING :
+            if (upper == INT_MAX)
+             upper = 1023;
+
+           for (i = 0; i < count; i ++)
+           {
+             int       datalen;        // Length of octetString value
+
+             ippGetOctetString(attr, i, &datalen);
+
+             if (datalen > upper)
+               break;
+           }
+
+           match = (i == count);
+           break;
+
+       case IPP_TAG_INTEGER :
+           for (i = 0; i < count; i ++)
+           {
+             int value = ippGetInteger(attr, i);
+                                       // Integer value
+
+             if (value < lower || value > upper)
+               break;
+           }
+
+           match = (i == count);
+           break;
+
+       case IPP_TAG_RANGE :
+           for (i = 0; i < count; i ++)
+           {
+             int vupper, vlower = ippGetRange(attr, i, &vupper);
+                                       // Range value
+
+             if (vlower < lower || vlower > upper || vupper < lower || vupper > upper)
+               break;
+           }
+
+           match = (i == count);
+           break;
+
+       default :
+           // No other constraints, so this is a match
+           match = 1;
+           break;
+      }
+    }
 
    /*
-    * Restore the separator if we have one...
+    * Restore the separators if we have them...
     */
 
+    if (paren)
+      *paren = '(';
+
     if (sep)
       *next++ = sep;
   }