]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - test/ipptool.c
Save work.
[thirdparty/cups.git] / test / ipptool.c
index 39ccb286b241f94d4df0d14e703cdcd75527e49a..847dfb586e94c7374273ecfdfcfe87b1e79680a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ipptool command for CUPS.
  *
- * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 2007-2019 by Apple Inc.
  * Copyright © 1997-2007 by Easy Software Products.
  *
  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
  */
 
 #include <cups/cups-private.h>
-#include <cups/file-private.h>
 #include <regex.h>
 #include <sys/stat.h>
-#ifdef WIN32
+#ifdef _WIN32
 #  include <windows.h>
 #  ifndef R_OK
 #    define R_OK 0
@@ -24,7 +23,7 @@
 #else
 #  include <signal.h>
 #  include <termios.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 #ifndef O_BINARY
 #  define O_BINARY 0
 #endif /* !O_BINARY */
@@ -177,7 +176,7 @@ static const char *get_string(ipp_attribute_t *attr, int element, int flags, cha
 static void    init_data(_cups_testdata_t *data);
 static char    *iso_date(const ipp_uchar_t *date);
 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_attr(cups_file_t *outfile, _cups_output_t 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, ...) _CUPS_FORMAT(2, 3);
 static void    print_ippserver_attr(_cups_testdata_t *data, ipp_attribute_t *attr, int indent);
@@ -186,9 +185,9 @@ static void print_line(_cups_testdata_t *data, ipp_t *ipp, ipp_attribute_t *attr
 static void    print_xml_header(_cups_testdata_t *data);
 static void    print_xml_string(cups_file_t *outfile, const char *element, const char *s);
 static void    print_xml_trailer(_cups_testdata_t *data, int success, const char *message);
-#ifndef WIN32
+#ifndef _WIN32
 static void    sigterm_handler(int sig);
-#endif /* WIN32 */
+#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) _CUPS_NORETURN;
@@ -222,14 +221,14 @@ main(int  argc,                           /* I - Number of command-line args */
                                        /* Global data */
 
 
-#ifndef WIN32
+#ifndef _WIN32
  /*
   * Catch SIGINT and SIGTERM...
   */
 
   signal(SIGINT, sigterm_handler);
   signal(SIGTERM, sigterm_handler);
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
  /*
   * Initialize the locale and variables...
@@ -464,9 +463,9 @@ main(int  argc,                             /* I - Number of command-line args */
 
                snprintf(filename, sizeof(filename), "%s.gz", argv[i]);
                 if (access(filename, 0) && filename[0] != '/'
-#ifdef WIN32
+#ifdef _WIN32
                     && (!isalpha(filename[0] & 255) || filename[1] != ':')
-#endif /* WIN32 */
+#endif /* _WIN32 */
                     )
                {
                  snprintf(filename, sizeof(filename), "%s/ipptool/%s", cg->cups_datadir, argv[i]);
@@ -651,9 +650,9 @@ main(int  argc,                             /* I - Number of command-line args */
       }
 
       if (access(argv[i], 0) && argv[i][0] != '/'
-#ifdef WIN32
+#ifdef _WIN32
           && (!isalpha(argv[i][0] & 255) || argv[i][1] != ':')
-#endif /* WIN32 */
+#endif /* _WIN32 */
           )
       {
         snprintf(testname, sizeof(testname), "%s/ipptool/%s", cg->cups_datadir, argv[i]);
@@ -846,7 +845,7 @@ copy_hex_string(char          *buffer,      /* I - String buffer */
     if (*dataptr < 0x20 || *dataptr >= 0x7f)
       break;
 
-  if (*dataptr)
+  if (dataptr < dataend)
   {
    /*
     * Yes, encode as hex...
@@ -874,7 +873,7 @@ copy_hex_string(char          *buffer,      /* I - String buffer */
     if ((size_t)datalen > bufsize)
       datalen = (int)bufsize - 1;
 
-    memcpy(buffer, data, datalen);
+    memcpy(buffer, data, (size_t)datalen);
     buffer[datalen] = '\0';
   }
 }
@@ -1094,11 +1093,11 @@ do_test(_ipp_file_t      *f,            /* I - IPP data file */
        }
 
        if (!Cancel && status == HTTP_STATUS_ERROR && httpError(data->http) != EINVAL &&
-#ifdef WIN32
+#ifdef _WIN32
            httpError(data->http) != WSAETIMEDOUT)
 #else
            httpError(data->http) != ETIMEDOUT)
-#endif /* WIN32 */
+#endif /* _WIN32 */
        {
          if (httpReconnect2(data->http, 30000, NULL))
            data->prev_pass = 0;
@@ -1121,11 +1120,11 @@ do_test(_ipp_file_t      *f,            /* I - IPP data file */
     }
 
     if (!Cancel && status == HTTP_STATUS_ERROR && httpError(data->http) != EINVAL &&
-#ifdef WIN32
+#ifdef _WIN32
        httpError(data->http) != WSAETIMEDOUT)
 #else
        httpError(data->http) != ETIMEDOUT)
-#endif /* WIN32 */
+#endif /* _WIN32 */
     {
       if (httpReconnect2(data->http, 30000, NULL))
        data->prev_pass = 0;
@@ -1151,7 +1150,7 @@ do_test(_ipp_file_t      *f,              /* I - IPP data file */
 
     if (httpGetVersion(data->http) != HTTP_1_1)
     {
-      int version = httpGetVersion(data->http);
+      int version = (int)httpGetVersion(data->http);
 
       add_stringf(data->errors, "Bad HTTP version (%d.%d)", version / 100, version % 100);
     }
@@ -2022,9 +2021,9 @@ get_filename(const char *testfile,        /* I - Current test file */
       *dstptr = '\0';
   }
   else if (!access(src, R_OK) || *src == '/'
-#ifdef WIN32
+#ifdef _WIN32
            || (isalpha(*src & 255) && src[1] == ':')
-#endif /* WIN32 */
+#endif /* _WIN32 */
            )
   {
    /*
@@ -2183,7 +2182,7 @@ iso_date(const ipp_uchar_t *date) /* I - IPP (RFC 1903) date/time value */
 static void
 pause_message(const char *message)     /* I - Message */
 {
-#ifdef WIN32
+#ifdef _WIN32
   HANDLE       tty;                    /* Console handle */
   DWORD                mode;                   /* Console mode */
   char         key;                    /* Key press */
@@ -2231,7 +2230,7 @@ pause_message(const char *message)        /* I - Message */
     close(tty);
     return;
   }
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
  /*
   * Display the prompt...
@@ -2239,7 +2238,7 @@ pause_message(const char *message)        /* I - Message */
 
   cupsFilePrintf(cupsFileStdout(), "%s\n---- PRESS ANY KEY ----", message);
 
-#ifdef WIN32
+#ifdef _WIN32
  /*
   * Read a key...
   */
@@ -2265,7 +2264,7 @@ pause_message(const char *message)        /* I - Message */
 
   tcsetattr(tty, TCSAFLUSH, &original);
   close(tty);
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
  /*
   * Erase the "press any key" prompt...
@@ -2281,7 +2280,7 @@ pause_message(const char *message)        /* I - Message */
 
 static void
 print_attr(cups_file_t     *outfile,   /* I  - Output file */
-           int             output,     /* I  - Output format */
+           _cups_output_t  output,     /* I  - Output format */
            ipp_attribute_t *attr,      /* I  - Attribute to print */
            ipp_tag_t       *group)     /* IO - Current group */
 {
@@ -2928,7 +2927,7 @@ print_xml_trailer(
 }
 
 
-#ifndef WIN32
+#ifndef _WIN32
 /*
  * 'sigterm_handler()' - Handle SIGINT and SIGTERM.
  */
@@ -2943,7 +2942,7 @@ sigterm_handler(int sig)          /* I - Signal number (unused) */
   signal(SIGINT, SIG_DFL);
   signal(SIGTERM, SIG_DFL);
 }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 
 /*
@@ -3787,6 +3786,7 @@ token_cb(_ipp_file_t      *f,             /* I - IPP file data */
             !_cups_strcasecmp(token, "WITH-VALUE"))
     {
       off_t    lastpos;                /* Last file position */
+      int      lastline;               /* Last line number */
 
       if (data->last_expect)
       {
@@ -3816,8 +3816,9 @@ token_cb(_ipp_file_t      *f,             /* I - IPP file data */
 
       for (;;)
       {
-        lastpos = cupsFileTell(f->fp);
-        ptr     += strlen(ptr);
+        lastpos  = cupsFileTell(f->fp);
+        lastline = f->linenum;
+        ptr      += strlen(ptr);
 
        if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
          break;
@@ -3840,6 +3841,7 @@ token_cb(_ipp_file_t      *f,             /* I - IPP file data */
           */
 
           cupsFileSeek(f->fp, lastpos);
+          f->linenum = lastline;
           *ptr = '\0';
           break;
        }
@@ -4296,33 +4298,31 @@ usage(void)
 {
   _cupsLangPuts(stderr, _("Usage: ipptool [options] URI filename [ ... filenameN ]"));
   _cupsLangPuts(stderr, _("Options:"));
-  _cupsLangPuts(stderr, _("  --help                  Show help."));
-  _cupsLangPuts(stderr, _("  --ippserver filename    Produce ippserver attribute file."));
-  _cupsLangPuts(stderr, _("  --stop-after-include-error\n"
-                          "                          Stop tests after a failed INCLUDE."));
-  _cupsLangPuts(stderr, _("  --version               Show version."));
-  _cupsLangPuts(stderr, _("  -4                      Connect using IPv4."));
-  _cupsLangPuts(stderr, _("  -6                      Connect using IPv6."));
-  _cupsLangPuts(stderr, _("  -C                      Send requests using "
-                          "chunking (default)."));
-  _cupsLangPuts(stderr, _("  -E                      Test with encryption using HTTP Upgrade to TLS."));
-  _cupsLangPuts(stderr, _("  -I                      Ignore errors."));
-  _cupsLangPuts(stderr, _("  -L                      Send requests using content-length."));
-  _cupsLangPuts(stderr, _("  -P filename.plist       Produce XML plist to a file and test report to standard output."));
-  _cupsLangPuts(stderr, _("  -S                      Test with encryption using HTTPS."));
-  _cupsLangPuts(stderr, _("  -T seconds              Set the receive/send timeout in seconds."));
-  _cupsLangPuts(stderr, _("  -V version              Set default IPP version."));
-  _cupsLangPuts(stderr, _("  -X                      Produce XML plist instead of plain text."));
-  _cupsLangPuts(stderr, _("  -c                      Produce CSV output."));
-  _cupsLangPuts(stderr, _("  -d name=value           Set named variable to value."));
-  _cupsLangPuts(stderr, _("  -f filename             Set default request filename."));
-  _cupsLangPuts(stderr, _("  -h                      Validate HTTP response headers."));
-  _cupsLangPuts(stderr, _("  -i seconds              Repeat the last file with the given time interval."));
-  _cupsLangPuts(stderr, _("  -l                      Produce plain text output."));
-  _cupsLangPuts(stderr, _("  -n count                Repeat the last file the given number of times."));
-  _cupsLangPuts(stderr, _("  -q                      Run silently."));
-  _cupsLangPuts(stderr, _("  -t                      Produce a test report."));
-  _cupsLangPuts(stderr, _("  -v                      Be verbose."));
+  _cupsLangPuts(stderr, _("--ippserver filename    Produce ippserver attribute file"));
+  _cupsLangPuts(stderr, _("--stop-after-include-error\n"
+                          "                        Stop tests after a failed INCLUDE"));
+  _cupsLangPuts(stderr, _("--version               Show version"));
+  _cupsLangPuts(stderr, _("-4                      Connect using IPv4"));
+  _cupsLangPuts(stderr, _("-6                      Connect using IPv6"));
+  _cupsLangPuts(stderr, _("-C                      Send requests using chunking (default)"));
+  _cupsLangPuts(stderr, _("-E                      Test with encryption using HTTP Upgrade to TLS"));
+  _cupsLangPuts(stderr, _("-I                      Ignore errors"));
+  _cupsLangPuts(stderr, _("-L                      Send requests using content-length"));
+  _cupsLangPuts(stderr, _("-P filename.plist       Produce XML plist to a file and test report to standard output"));
+  _cupsLangPuts(stderr, _("-S                      Test with encryption using HTTPS"));
+  _cupsLangPuts(stderr, _("-T seconds              Set the receive/send timeout in seconds"));
+  _cupsLangPuts(stderr, _("-V version              Set default IPP version"));
+  _cupsLangPuts(stderr, _("-X                      Produce XML plist instead of plain text"));
+  _cupsLangPuts(stderr, _("-c                      Produce CSV output"));
+  _cupsLangPuts(stderr, _("-d name=value           Set named variable to value"));
+  _cupsLangPuts(stderr, _("-f filename             Set default request filename"));
+  _cupsLangPuts(stderr, _("-h                      Validate HTTP response headers"));
+  _cupsLangPuts(stderr, _("-i seconds              Repeat the last file with the given time interval"));
+  _cupsLangPuts(stderr, _("-l                      Produce plain text output"));
+  _cupsLangPuts(stderr, _("-n count                Repeat the last file the given number of times"));
+  _cupsLangPuts(stderr, _("-q                      Run silently"));
+  _cupsLangPuts(stderr, _("-t                      Produce a test report"));
+  _cupsLangPuts(stderr, _("-v                      Be verbose"));
 
   exit(1);
 }
@@ -4540,7 +4540,7 @@ with_value(_cups_testdata_t *data,        /* I - Test data */
     case IPP_TAG_BOOLEAN :
        for (i = 0; i < count; i ++)
        {
-          if ((!strcmp(value, "true")) == ippGetBoolean(attr, i))
+          if ((!strcmp(value, "true") || !strcmp(value, "1")) == ippGetBoolean(attr, i))
           {
             if (!matchbuf[0])
              strlcpy(matchbuf, value, matchlen);
@@ -4771,7 +4771,74 @@ with_value(_cups_testdata_t *data,       /* I - Test data */
        break;
 
     case IPP_TAG_STRING :
+        if (flags & _CUPS_WITH_REGEX)
+       {
+        /*
+         * Value is an extended, case-sensitive POSIX regular expression...
+         */
+
+         void          *adata;         /* Pointer to octetString data */
+         int           adatalen;       /* Length of octetString */
+         regex_t       re;             /* Regular expression */
+
+          if ((i = regcomp(&re, value, REG_EXTENDED | REG_NOSUB)) != 0)
+         {
+            regerror(i, &re, temp, sizeof(temp));
+
+           print_fatal_error(data, "Unable to compile WITH-VALUE regular expression \"%s\" - %s", value, temp);
+           return (0);
+         }
+
+         /*
+         * See if ALL of the values match the given regular expression.
+         */
+
+         for (i = 0; i < count; i ++)
+         {
+            if ((adata = ippGetOctetString(attr, i, &adatalen)) == NULL || adatalen >= (int)sizeof(temp))
+            {
+              match = 0;
+              break;
+            }
+            memcpy(temp, adata, (size_t)adatalen);
+            temp[adatalen] = '\0';
+
+           if (!regexec(&re, temp, 0, NULL, 0))
+           {
+             if (!matchbuf[0])
+               strlcpy(matchbuf, temp, matchlen);
+
+             if (!(flags & _CUPS_WITH_ALL))
+             {
+               match = 1;
+               break;
+             }
+           }
+           else if (flags & _CUPS_WITH_ALL)
+           {
+             match = 0;
+             break;
+           }
+         }
+
+         regfree(&re);
+
+         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);
+           }
+         }
+       }
+       else
         {
+         /*
+          * Value is a literal or hex-encoded string...
+          */
+
           unsigned char        withdata[1023], /* WITH-VALUE data */
                        *adata;         /* Pointer to octetString data */
          int           withlen,        /* Length of WITH-VALUE data */
@@ -4783,7 +4850,7 @@ with_value(_cups_testdata_t *data,        /* I - Test data */
             * Grab hex-encoded value...
             */
 
-            if ((withlen = (int)strlen(value)) & 1 || withlen > (2 * (sizeof(withdata) + 1)))
+            if ((withlen = (int)strlen(value)) & 1 || withlen > (int)(2 * (sizeof(withdata) + 1)))
             {
              print_fatal_error(data, "Bad WITH-VALUE hex value.");
               return (0);
@@ -4826,7 +4893,7 @@ with_value(_cups_testdata_t *data,        /* I - Test data */
 
             withlen = (int)strlen(value);
 
-            memcpy(withdata, value, withlen);
+            memcpy(withdata, value, (size_t)withlen);
          }
 
          for (i = 0; i < count; i ++)
@@ -4836,7 +4903,7 @@ with_value(_cups_testdata_t *data,        /* I - Test data */
            if (withlen == adatalen && !memcmp(withdata, adata, (size_t)withlen))
            {
              if (!matchbuf[0])
-               copy_hex_string(matchbuf, adata, adatalen, matchlen);
+                copy_hex_string(matchbuf, adata, adatalen, matchlen);
 
              if (!(flags & _CUPS_WITH_ALL))
              {