]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.6svn-r10024.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 28 Sep 2011 22:40:47 +0000 (22:40 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 28 Sep 2011 22:40:47 +0000 (22:40 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3438 a1ca3aef-8c08-0410-bb20-df032aa958be

16 files changed:
CHANGES-IPPTOOL.txt [new file with mode: 0644]
IPPTOOL.txt
backend/dnssd.c
cups/http-support.c
cups/http.c
cups/ipp-support.c
cups/request.c
man/ipptoolfile.man
test/Dependencies
test/Makefile
test/ipp-1.1.test
test/ipp-2.1.test
test/ipp-2.2.test
test/ipptool.c
test/xmltotest.c [new file with mode: 0644]
tools/makeipptoolpkg

diff --git a/CHANGES-IPPTOOL.txt b/CHANGES-IPPTOOL.txt
new file mode 100644 (file)
index 0000000..e107c3c
--- /dev/null
@@ -0,0 +1,53 @@
+CHANGES-IPPTOOL.txt - 2011-09-28
+--------------------------------
+
+This file provides a list of changes to the ipptool binary distribution posted
+on cups.org.
+
+
+2011-09-28
+
+       - Test output now includes a summary and overall score at the end.
+       - The MATCH-VALUE predicate now correctly deals with a failed EXPECT
+         condition.
+       - The IPP/1.1 test suite now looks for legacy media names and uses them
+         if the corresponding PWG standard names are not present.
+       - The IPP/1.1 test suite now tests the Print-Job+Release-Job when the
+         printer supports the job-hold-until attribute, Hold-Job operation, and
+         Release-Job operation.
+
+
+2011-09-21
+
+       - Fixes for HTTP chunking, timeout, and encryption issues reported by
+         various users.
+       - Greatly improved IPP tests with added IPP/2.2 tests.
+       - New test documents - 1-page and 4-page mixed A4/Letter PDF/PS and a
+         couple JPEGs.
+       - New REPEAT directives to programmatically repeat tests as needed.
+
+
+2011-08-16
+
+       - The Windows version no longer requires Visual Studio to be installed.
+       - The Windows version now supports SSL.
+       - Added "ipps" URI support.
+       - Added a new "-T" option.
+       - Added support for fractional seconds for the -i option and DELAY
+         directive.
+       - Added support for authentication.
+       - Added DEFINE-MATCH, DEFINE-NO-MATCH, DEFINE-VALUE, IF-NOT-DEFINED,
+         IGNORE-ERRORS, SKIP-IF-DEFINED, SKIP-IF-NOT-DEFINED,
+         SKIP-PREVIOUS-ERROR directives.
+       - WITH-VALUE now supports variable expansion.
+       - Updated the IPP/1.1 conformance test to skip the "my-jobs different
+         user" test if the printer URI contains a username.
+       - Updated the IPP conformance tests to validate media, media-default,
+         and media-supported values.
+       - No longer error out if a Printer returns a different version number in
+         the response when the request contains the version 0.0.
+
+
+2010-10-16
+
+       - Initial release of standalone binary.
index 5e84ebf01446f1b00a39ed0e2df6d050d8413e24..b0c671c2b57b4acc801868eb5df23e847234a834 100644 (file)
@@ -1,6 +1,8 @@
-IPPTOOL.txt - 2011-09-14
+IPPTOOL.txt - 2011-09-28
 ------------------------
 
+See the file CHANGES-IPPTOOL.txt for a list of changes to this software.
+
 
 INTRODUCTION
 
@@ -50,10 +52,10 @@ CONFORMANCE TESTS
     IPP/2.2.  For a given printer URI, the following commands perform tests at
     each level:
 
-        ipptool -tf filename [options] printer-uri ipp-1.1.test
-        ipptool -tf filename [options] -V 2.0 printer-uri ipp-2.0.test
-        ipptool -tf filename [options] -V 2.1 printer-uri ipp-2.1.test
-        ipptool -tf filename [options] -V 2.2 printer-uri ipp-2.2.test
+        ipptool -tf filename [options] -I printer-uri ipp-1.1.test
+        ipptool -tf filename [options] -I -V 2.0 printer-uri ipp-2.0.test
+        ipptool -tf filename [options] -I -V 2.1 printer-uri ipp-2.1.test
+        ipptool -tf filename [options] -I -V 2.2 printer-uri ipp-2.2.test
 
     The filename must use a format supported by the printer; ipptool will guess
     the MIME media type using the extension, otherwise application/octet stream
@@ -73,13 +75,17 @@ CONFORMANCE TESTS
     Print-by-reference (URL) printing can be tested by defining the document-uri
     variable to a URL, for example:
 
-        ipptool -tf filename -d document-uri=your-url printer-uri ipp-1.1.test
+        ipptool -tf filename -d document-uri=url -I printer-uri ipp-1.1.test
 
     The standard test files are available on cups.org under the "test"
     directory, for example:
 
        http://www.cups.org/test/document-a4.pdf
 
+    The "document" test files contain 4 pages each.  Doing the IPP conformance
+    tests will will produce up to 90 pages on various media, depending on the
+    printer.
+
 
 READING THE DOCUMENTATION
 
@@ -97,6 +103,34 @@ GETTING SUPPORT AND OTHER RESOURCES
     See the CUPS web site at "http://www.cups.org/" for other resources.
 
 
+REPORTING BUGS
+
+    If you believe you have discovered a bug in ipptool, please fill out the
+    bug form at:
+
+       http://www.cups.org/str.php
+
+    Be sure to identify the version of CUPS and ipptool (if you downloaded the
+    standalone version) you are using, the printer (if any) and firmware
+    version, and include any files that apply.
+
+    If you downloaded the standalone version of ipptool, please also re-run the
+    test with debug logging enabled.  Run the following commands on Windows to
+    enable debug logging:
+
+       set CUPS_DEBUG_LOG=ipptool.log
+       set CUPS_DEBUG_LEVEL=6
+
+    For Linux and Mac OS X use:
+
+       CUPS_DEBUG_LOG=ipptool.log; export CUPS_DEBUG_LOG
+       CUPS_DEBUG_LEVEL=6; export CUPS_DEBUG_LEVEL
+
+    Then when you run the ipptool command a new "ipptool.log" file will be
+    created with detailed information - attach this file to the bug you file
+    as well.
+
+
 LEGAL STUFF
 
     CUPS is Copyright 2007-2011 by Apple Inc.  CUPS and the CUPS logo are
@@ -104,8 +138,6 @@ LEGAL STUFF
 
     The MD5 Digest code is Copyright 1999 Aladdin Enterprises.
 
-    This software is based in part on the work of the Independent JPEG Group.
-
     CUPS is provided under the terms of version 2 of the GNU General Public
     License and GNU Library General Public License. This program is distributed
     in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
index e8de61c254c9a288566ee466268fbb77d2557438..fd86e08148e4ccab28e8497e84161ed1b2c88b63 100644 (file)
@@ -774,7 +774,7 @@ query_callback(
 
         datalen = *data++;
 
-        if (!datalen || (data + datalen) >= dataend)
+        if (!datalen || (data + datalen) > dataend)
          break;
 
         datanext = data + datalen;
index 7c30f4d9f061b4b4a83ebd1688a6ef5dbcfe5323..0d1f2b211f58def1688333c3688bcc3b5e8ac36c 100644 (file)
@@ -1823,17 +1823,36 @@ http_resolve_cb(
 
   if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "rp",
                                     &valueLen)) != NULL)
+  {
+    if (((char *)value)[0] == '/')
+    {
+     /*
+      * "rp" value (incorrectly) has a leading slash already...
+      */
+
+      memcpy(rp, value, valueLen);
+      rp[valueLen] = '\0';
+    }
+    else
+    {
+     /*
+      * Convert to resource by concatenating with a leading "/"...
+      */
+
+      rp[0] = '/';
+      memcpy(rp + 1, value, valueLen);
+      rp[valueLen + 1] = '\0';
+    }
+  }
+  else
   {
    /*
-    * Convert to resource by concatenating with a leading "/"...
+    * Default "rp" value is blank, mapping to a path of "/"...
     */
 
     rp[0] = '/';
-    memcpy(rp + 1, value, valueLen);
-    rp[valueLen + 1] = '\0';
+    rp[1] = '\0';
   }
-  else
-    rp[0] = '\0';
 
  /*
   * Lookup the FQDN if needed...
index d5dfd71e095dda31611407f565ca47edab0bc7d6..33307db463d7f878e0821f4a41e966c9bf81fb31 100644 (file)
@@ -3768,6 +3768,7 @@ http_set_credentials(http_t *http)        /* I - Connection to server */
   return (error);
 }
 #  endif /* HAVE_CDSASSL && HAVE_SECCERTIFICATECOPYDATA */
+#endif /* HAVE_SSL */
 
 
 /*
@@ -3816,6 +3817,7 @@ http_set_wait(http_t *http)               /* I - Connection to server */
 }
 
 
+#ifdef HAVE_SSL
 /*
  * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
  */
@@ -4263,10 +4265,8 @@ http_setup_ssl(http_t *http)             /* I - Connection to server */
 
   return (0);
 }
-#endif /* HAVE_SSL */
 
 
-#ifdef HAVE_SSL
 /*
  * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
  */
index cbf144dbb7a45c87880256741a21dd028805880b..a6c23f555667eb6c4225d960c89006ea428213cd 100644 (file)
@@ -371,6 +371,16 @@ _ippAttrString(ipp_attribute_t *attr,      /* I - Attribute */
             bufptr += strlen(ptr);
             break;
           }
+          else if (!strcmp(attr->name, "operations-supported"))
+          {
+            ptr = ippOpString(val->integer);
+
+            if (buffer && bufptr < bufend)
+              strlcpy(bufptr, ptr, bufend - bufptr + 1);
+
+            bufptr += strlen(ptr);
+            break;
+          }
 
       case IPP_TAG_INTEGER :
           if (buffer && bufptr < bufend)
@@ -621,7 +631,7 @@ ippOpString(ipp_op_t op)            /* I - Operation ID */
   * No, build an "unknown-xxxx" operation string...
   */
 
-  sprintf(cg->ipp_unknown, "unknown-%04x", op);
+  sprintf(cg->ipp_unknown, "0x%04x", op);
 
   return (cg->ipp_unknown);
 }
@@ -639,6 +649,9 @@ ippOpValue(const char *name)                /* I - Textual name */
   int          i;
 
 
+  if (!strncmp(name, "0x", 2))
+    return ((ipp_op_t)strtol(name + 2, NULL, 16));
+
   for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++)
     if (!_cups_strcasecmp(name, ipp_std_ops[i]))
       return ((ipp_op_t)i);
index 1f87e77f650c23753dcc6c8928715198a2ed3ea2..9d004c39b31ff5e8b48de3161929e6e0142b57b0 100644 (file)
@@ -476,6 +476,8 @@ cupsGetResponse(http_t     *http,   /* I - Connection to server or @code CUPS_HTTP
                   attr ? attr->values[0].string.text :
                      ippErrorString(response->request.status.status_code), 0);
   }
+  else if (status == HTTP_ERROR)
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(http->error), 0);
   else if (status != HTTP_OK)
     _cupsSetHTTPError(status);
 
index 6f659891060219d325853a756736980500c2cd1a..c379c0477b38d5880969d2ab6c676fa94cff8522 100644 (file)
@@ -11,7 +11,7 @@
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH ipptoolfile 5 "CUPS" "13 September 2011" "Apple Inc."
+.TH ipptoolfile 5 "CUPS" "28 September 2011" "Apple Inc."
 .SH NAME
 ipptoolfile \- ipptool file format
 
@@ -251,7 +251,7 @@ effect of this predicate is that this EXPECT will never fail a test.
 .TP 5
 DEFINE-VALUE variable-name
 Defines the variable to the value of the attribute when the EXPECT condition
-matches.
+matches. A side-effect of this predicate is that this EXPECT will never fail a test.
 .TP 5
 IF-DEFINED variable-name
 Makes the EXPECT conditions apply only if the specified variable is defined.
index 32891447ef8e69813a38b27ad2e29ef057831161..63cc5bd70361721678d090acf725dd9ed04556f0 100644 (file)
@@ -18,3 +18,5 @@ ipptool.o: ../cups/http-private.h ../cups/http.h ../cups/md5-private.h
 ipptool.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/language-private.h
 ipptool.o: ../cups/transcode.h ../cups/thread-private.h
 ipptool.o: ../cups/file-private.h ../cups/cups-private.h
+xmltotest.o: ../cups/cups.h ../cups/file.h ../cups/versioning.h ../cups/ipp.h
+xmltotest.o: ../cups/http.h ../cups/array.h ../cups/language.h
index d4073abc1087109ca9ab37fdd642709ffaf8fb84..f66b5dc659730fde165b2e1e2bb89486d59ee0b4 100644 (file)
@@ -44,7 +44,8 @@ TESTFILES     =       \
                        testfile.txt
 OBJS           =       \
                        ippserver.o \
-                       ipptool.o
+                       ipptool.o \
+                       xmltotest.o
 TARGETS                =       \
                        ippserver \
                        ipptool \
@@ -180,6 +181,17 @@ ipptool-static:    ipptool.o ../cups/$(LIBCUPSSTATIC)
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
+#
+# xmltotest
+#
+
+xmltotest: xmltotest.o ../cups/$(LIBUPSSTATIC)
+       echo Linking $@...
+       $(CC) $(LDFLAGS) -o $@ xmltotest.o  ../cups/$(LIBCUPSSTATIC) \
+               $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) \
+               -lmxml
+
+
 #
 # Dependencies...
 #
index 5b56771812397b1189f98aa12a1f32d0950d2dfa..12d6ea674ace1aeddd2f188773d9ac7bb256e492 100644 (file)
@@ -203,6 +203,22 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 
        STATUS successful-ok
 
+       # Display some useful information to identify the test
+       DISPLAY printer-name
+       DISPLAY printer-make-and-model
+       DISPLAY color-supported
+       DISPLAY pages-per-minute
+       DISPLAY pages-per-minute-color
+       DISPLAY document-format-supported
+       DISPLAY finishings-supported
+       DISPLAY job-sheets-supported
+       DISPLAY media-supported
+       DISPLAY number-up-supported
+       DISPLAY operations-supported
+       DISPLAY print-quality-supported
+       DISPLAY reference-uri-schemes-supported
+       DISPLAY sizes-supported
+
        # Job template attributes
        EXPECT ?copies-default OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
        EXPECT ?copies-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag
@@ -238,9 +254,9 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        EXPECT document-format-supported WITH-VALUE "application/postscript" DEFINE-MATCH OPTIONAL_POSTSCRIPT
        EXPECT document-format-supported WITH-VALUE "image/jpeg" DEFINE-MATCH OPTIONAL_JPEG
        EXPECT job-sheets-supported WITH-VALUE "standard" DEFINE-MATCH OPTIONAL_STANDARD_SHEET
-       EXPECT media-supported WITH-VALUE "iso_a4_210x297mm" DEFINE-MATCH OPTIONAL_A4_MEDIA
-       EXPECT media-supported WITH-VALUE "na_letter_8.5x11in" DEFINE-MATCH OPTIONAL_LETTER_MEDIA
-       EXPECT media-supported WITH-VALUE "na_index-4x6_4x6in" DEFINE-MATCH OPTIONAL_4X6_MEDIA
+       EXPECT media-supported WITH-VALUE "/^(a4|iso-a4|iso_a4_210x297mm)$$/" DEFINE-VALUE OPTIONAL_A4_MEDIA
+       EXPECT media-supported WITH-VALUE "/^(letter|na-letter|na_letter_8.5x11in)$$/" DEFINE-VALUE OPTIONAL_LETTER_MEDIA
+       EXPECT media-supported WITH-VALUE "/^(index-4x6|na_index-4x6_4x6in)$$/" DEFINE-VALUE OPTIONAL_4X6_MEDIA
        EXPECT number-up-supported WITH-VALUE 2 DEFINE-MATCH OPTIONAL_2UP
        EXPECT print-quality WITH-VALUE 3 DEFINE-MATCH OPTIONAL_DRAFT_QUALITY
        EXPECT print-quality WITH-VALUE 4 DEFINE-MATCH OPTIONAL_NORMAL_QUALITY
@@ -972,6 +988,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 {
        SKIP-IF-NOT-DEFINED OPTIONAL_CREATE_JOB
        SKIP-IF-NOT-DEFINED OPTIONAL_SEND_DOCUMENT
+       SKIP-PREVIOUS-ERROR yes
 
        NAME "RFC 2911 section 3.3.1: Send-Document Operation"
        OPERATION Send-Document
@@ -1025,6 +1042,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 {
        SKIP-IF-NOT-DEFINED OPTIONAL_CREATE_JOB
        SKIP-IF-NOT-DEFINED OPTIONAL_SEND_DOCUMENT
+       SKIP-PREVIOUS-ERROR yes
 
        NAME "Send-Document missing last-document: Send-Document Operation"
        OPERATION Send-Document
@@ -1045,6 +1063,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 {
        SKIP-IF-NOT-DEFINED OPTIONAL_CREATE_JOB
        SKIP-IF-NOT-DEFINED OPTIONAL_SEND_DOCUMENT
+       SKIP-PREVIOUS-ERROR yes
 
        NAME "RFC 2911 section 3.3.3: Cancel-Job Operation"
        OPERATION Cancel-Job
@@ -1094,6 +1113,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        SKIP-IF-NOT-DEFINED OPTIONAL_CREATE_JOB
        SKIP-IF-NOT-DEFINED OPTIONAL_SEND_URI
        SKIP-IF-NOT-DEFINED document-uri
+       SKIP-PREVIOUS-ERROR yes
 
        NAME "RFC 2911 section 3.3.2: Send-URI Operation"
        OPERATION Send-URI
@@ -1146,6 +1166,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 {
        SKIP-IF-NOT-DEFINED OPTIONAL_CREATE_JOB
        SKIP-IF-NOT-DEFINED OPTIONAL_SEND_URI
+       SKIP-PREVIOUS-ERROR yes
 
        NAME "Send-URI with bad URI: Send-URI Operation (bad URI)"
        OPERATION Send-URI
@@ -1167,6 +1188,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 {
        SKIP-IF-NOT-DEFINED OPTIONAL_CREATE_JOB
        SKIP-IF-NOT-DEFINED OPTIONAL_SEND_URI
+       SKIP-PREVIOUS-ERROR yes
 
        NAME "Send-URI with bad URI: Cancel-Job Operation"
        OPERATION Cancel-Job
@@ -1237,7 +1259,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        FILE document-a4.pdf
 
        STATUS successful-ok
@@ -1273,7 +1295,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR keyword sides two-sided-long-edge
        FILE document-a4.pdf
 
@@ -1309,7 +1331,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        FILE document-letter.pdf
 
        STATUS successful-ok
@@ -1345,7 +1367,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR keyword sides two-sided-long-edge
        FILE document-letter.pdf
 
@@ -1383,7 +1405,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        FILE document-a4.ps
 
        STATUS successful-ok
@@ -1419,7 +1441,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR keyword sides two-sided-long-edge
        FILE document-a4.ps
 
@@ -1455,7 +1477,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        FILE document-letter.ps
 
        STATUS successful-ok
@@ -1491,7 +1513,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR keyword sides two-sided-long-edge
        FILE document-letter.ps
 
@@ -1529,7 +1551,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        FILE color.jpg
 
        STATUS successful-ok
@@ -1564,7 +1586,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        FILE color.jpg
 
        STATUS successful-ok
@@ -1599,7 +1621,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_index-4x6_4x6in
+       ATTR keyword media $OPTIONAL_4X6_MEDIA
        FILE color.jpg
 
        STATUS successful-ok
@@ -1634,7 +1656,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        FILE gray.jpg
 
        STATUS successful-ok
@@ -1669,7 +1691,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        FILE gray.jpg
 
        STATUS successful-ok
@@ -1704,7 +1726,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_index-4x6_4x6in
+       ATTR keyword media $OPTIONAL_4X6_MEDIA
        FILE gray.jpg
 
        STATUS successful-ok
@@ -1742,7 +1764,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR keyword job-sheets standard
        FILE document-a4.pdf
 
@@ -1779,7 +1801,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR keyword job-sheets standard
        FILE document-a4.pdf
 
@@ -1816,7 +1838,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR keyword job-sheets standard
        FILE document-a4.ps
 
@@ -1853,7 +1875,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR keyword job-sheets standard
        FILE document-a4.ps
 
@@ -1892,7 +1914,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR integer number-up 2
        FILE document-a4.pdf
 
@@ -1929,7 +1951,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR integer number-up 2
        FILE document-letter.pdf
 
@@ -1966,7 +1988,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR integer number-up 2
        FILE document-a4.ps
 
@@ -2003,7 +2025,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/postscript
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR integer number-up 2
        FILE document-letter.ps
 
@@ -2042,7 +2064,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_index-4x6_4x6in
+       ATTR keyword media $OPTIONAL_4X6_MEDIA
        ATTR enum print-quality 3
        FILE color.jpeg
 
@@ -2079,7 +2101,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_index-4x6_4x6in
+       ATTR keyword media $OPTIONAL_4X6_MEDIA
        ATTR enum print-quality 4
        FILE color.jpeg
 
@@ -2116,7 +2138,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format image/jpeg
        GROUP job-attributes-tag
-       ATTR keyword media na_index-4x6_4x6in
+       ATTR keyword media $OPTIONAL_4X6_MEDIA
        ATTR enum print-quality 5
        FILE color.jpeg
 
@@ -2153,7 +2175,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media iso_a4_210x297mm
+       ATTR keyword media $OPTIONAL_A4_MEDIA
        ATTR enum print-quality 3
        FILE document-a4.pdf
 
@@ -2190,7 +2212,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR keyword compression none
        ATTR mimeMediaType document-format application/pdf
        GROUP job-attributes-tag
-       ATTR keyword media na_letter_8.5x11in
+       ATTR keyword media $OPTIONAL_LETTER_MEDIA
        ATTR enum print-quality 3
        FILE document-letter.pdf
 
@@ -2210,6 +2232,57 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 }
 
 
+# Test hold/release in the context of Print-Job w/job-hold-until + Release-Job
+{
+       SKIP-IF-NOT-DEFINED OPTIONAL_HOLD_JOB
+
+       NAME "Print-Job with job-hold-until"
+       OPERATION Print-Job
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR uri printer-uri $uri
+       ATTR name requesting-user-name $user
+       ATTR name job-name "Test Document w/Hold"
+       ATTR name document-name $filename
+       ATTR keyword compression none
+       ATTR mimeMediaType document-format $filetype
+       GROUP job-attributes-tag
+       ATTR keyword job-hold-until indefinite
+       FILE $filename
+
+       STATUS successful-ok
+       STATUS server-error-job-canceled
+       STATUS server-error-busy REPEAT-MATCH
+
+       EXPECT job-uri OF-TYPE uri COUNT 1 IN-GROUP job-attributes-tag WITH-VALUE "$IPP_URI_SCHEME"
+       EXPECT job-id OF-TYPE integer COUNT 1 IN-GROUP job-attributes-tag
+              WITH-VALUE >0
+       EXPECT job-state OF-TYPE enum COUNT 1 IN-GROUP job-attributes-tag
+              WITH-VALUE 3,4,5,6,7,8,9
+       EXPECT job-state-reasons OF-TYPE keyword IN-GROUP job-attributes-tag
+       EXPECT ?job-state-message OF-TYPE text IN-GROUP job-attributes-tag
+       EXPECT ?number-of-intervening-jobs OF-TYPE integer
+              IN-GROUP job-attributes-tag WITH-VALUE >-1
+}
+
+{
+       SKIP-IF-NOT-DEFINED OPTIONAL_HOLD_JOB
+
+       NAME "Release-Job"
+       OPERATION Release-Job
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR uri printer-uri $uri
+       ATTR integer job-id $job-id
+       ATTR name requesting-user-name $user
+
+       STATUS successful-ok
+       STATUS client-error-not-possible
+}
+
+
 #
 # End of "$Id$".
 #
index 4993831fbacac59a8136ce8897a89529ad6d350a..e8ddae4d11ad2d10c50170c02f1f138360808022 100644 (file)
@@ -14,7 +14,7 @@
 #
 # Usage:
 #
-#   ./ipptool -V 2.1 {-d PRINTER_IS_COLOR=1} -f filename -t printer-uri ipp-2.1.test
+#   ./ipptool -V 2.1 -f filename -t printer-uri ipp-2.1.test
 #
 
 # Do all of the IPP/1.1 and IPP/2.0 tests as an IPP/2.1 client
index d910c8be93c3c7849c60ca00e1b289f4854a18c6..935a62da91d45a80266029c2bb717b8523b33a60 100644 (file)
@@ -14,7 +14,7 @@
 #
 # Usage:
 #
-#   ./ipptool -V 2.2 {-d PRINTER_IS_COLOR=1} -f filename -t printer-uri ipp-2.2.test
+#   ./ipptool -V 2.2 -f filename -t printer-uri ipp-2.2.test
 #
 
 # Do all of the IPP/1.1, IPP/2.0, and IPP/2.1 tests as an IPP/2.2 client
index dbd847e7cb60e56670b5f27bdcd4be8181ab0a6e..de47d8fe5bddc0524315a25920275a712d595ca1 100644 (file)
@@ -144,7 +144,11 @@ int                Cancel = 0,             /* Cancel test? */
                IgnoreErrors = 0,       /* Ignore errors? */
                Verbosity = 0,          /* Show all attributes? */
                Version = 11,           /* Default IPP version */
-               XMLHeader = 0;          /* 1 if header is written */
+               XMLHeader = 0,          /* 1 if header is written */
+               TestCount = 0,          /* Number of tests run */
+               PassCount = 0,          /* Number of passing tests */
+               FailCount = 0,          /* Number of failing tests */
+               SkipCount = 0;          /* Number of skipped tests */
 char           *Password = NULL;       /* Password from URI */
 const char * const URIStatusStrings[] =        /* URI status strings */
 {
@@ -202,7 +206,7 @@ static int  timeout_cb(http_t *http, void *user_data);
 static void    usage(void) __attribute__((noreturn));
 static int     validate_attr(ipp_attribute_t *attr, int print);
 static int      with_value(char *value, int regex, ipp_attribute_t *attr,
-                          int report);
+                          int report, char *matchbuf, size_t matchlen);
 
 
 /*
@@ -398,15 +402,30 @@ main(int  argc,                           /* I - Number of command-line args */
               if (vars.filename)
                free(vars.filename);
 
-              if (access(argv[i], 0) && argv[i][0] != '/')
+              if (access(argv[i], 0))
               {
-                snprintf(filename, sizeof(filename), "%s/ipptool/%s",
-                         cg->cups_datadir, argv[i]);
-                if (access(argv[i], 0))
-                 vars.filename = strdup(argv[i]);
-                else
-                  vars.filename = strdup(filename);
-              }
+               /*
+                * Try filename.gz...
+                */
+
+               snprintf(filename, sizeof(filename), "%s.gz", argv[i]);
+                if (access(filename, 0) && filename[0] != '/')
+               {
+                 snprintf(filename, sizeof(filename), "%s/ipptool/%s",
+                          cg->cups_datadir, argv[i]);
+                 if (access(filename, 0))
+                 {
+                   snprintf(filename, sizeof(filename), "%s/ipptool/%s.gz",
+                            cg->cups_datadir, argv[i]);
+                   if (access(filename, 0))
+                     vars.filename = strdup(argv[i]);
+                 }
+                 else
+                   vars.filename = strdup(filename);
+               }
+               else
+                 vars.filename = strdup(filename);
+             }
               else
                vars.filename = strdup(argv[i]);
 
@@ -419,7 +438,9 @@ main(int  argc,                             /* I - Number of command-line args */
                 if (!_cups_strcasecmp(ext, ".gif"))
                   set_variable(&vars, "filetype", "image/gif");
                 else if (!_cups_strcasecmp(ext, ".htm") ||
-                         !_cups_strcasecmp(ext, ".html"))
+                         !_cups_strcasecmp(ext, ".htm.gz") ||
+                         !_cups_strcasecmp(ext, ".html") ||
+                         !_cups_strcasecmp(ext, ".html.gz"))
                   set_variable(&vars, "filetype", "text/html");
                 else if (!_cups_strcasecmp(ext, ".jpg"))
                   set_variable(&vars, "filetype", "image/jpeg");
@@ -427,11 +448,14 @@ main(int  argc,                           /* I - Number of command-line args */
                   set_variable(&vars, "filetype", "application/pdf");
                 else if (!_cups_strcasecmp(ext, ".png"))
                   set_variable(&vars, "filetype", "image/png");
-                else if (!_cups_strcasecmp(ext, ".ps"))
+                else if (!_cups_strcasecmp(ext, ".ps") ||
+                         !_cups_strcasecmp(ext, ".ps.gz"))
                   set_variable(&vars, "filetype", "application/postscript");
-                else if (!_cups_strcasecmp(ext, ".ras"))
+                else if (!_cups_strcasecmp(ext, ".ras") ||
+                         !_cups_strcasecmp(ext, ".ras.gz"))
                   set_variable(&vars, "filetype", "image/pwg-raster");
-                else if (!_cups_strcasecmp(ext, ".txt"))
+                else if (!_cups_strcasecmp(ext, ".txt") ||
+                         !_cups_strcasecmp(ext, ".txt.gz"))
                   set_variable(&vars, "filetype", "text/plain");
                 else if (!_cups_strcasecmp(ext, ".xps"))
                   set_variable(&vars, "filetype", "application/openxps");
@@ -627,6 +651,16 @@ main(int  argc,                            /* I - Number of command-line args */
       do_tests(&vars, testfile);
     }
   }
+  else if (Output == _CUPS_OUTPUT_TEST && TestCount > 1)
+  {
+   /*
+    * Show a summary report if there were multiple tests...
+    */
+
+    printf("\nSummary: %d tests, %d passed, %d failed, %d skipped\n"
+           "Score: %d%%\n", TestCount, PassCount, FailCount, SkipCount,
+           100 * (PassCount + SkipCount) / TestCount);
+  }
 
  /*
   * Exit...
@@ -676,7 +710,7 @@ do_tests(_cups_vars_t *vars,                /* I - Variables */
                *response = NULL;       /* IPP response */
   size_t       length;                 /* Length of IPP request */
   http_status_t        status;                 /* HTTP status */
-  int          fd;                     /* File to send */
+  cups_file_t  *reqfile;               /* File to send */
   ssize_t      bytes;                  /* Bytes read/written */
   char         attr[128];              /* Attribute name */
   ipp_op_t     op;                     /* Operation */
@@ -1054,6 +1088,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
     last_expect   = NULL;
     last_status   = NULL;
     filename[0]   = '\0';
+    skip_previous = 0;
     skip_test     = 0;
     version       = Version;
     transfer      = Transfer;
@@ -2036,6 +2071,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
     * Submit the IPP request...
     */
 
+    TestCount ++;
+
     request->request.op.version[0]   = version / 10;
     request->request.op.version[1]   = version % 10;
     request->request.op.operation_id = op;
@@ -2077,6 +2114,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
 
     if ((skip_previous && !prev_pass) || skip_test)
     {
+      SkipCount ++;
+
       ippDelete(request);
       request = NULL;
 
@@ -2117,20 +2156,16 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
 
        length = ippLength(request);
 
-       if (filename[0])
+       if (filename[0] && (reqfile = cupsFileOpen(filename, "r")) != NULL)
        {
-         struct stat   fileinfo;       /* File information */
+        /*
+         * Read the file to get the uncompressed file size...
+         */
 
-         if (stat(filename, &fileinfo))
-         {
-           snprintf(buffer, sizeof(buffer), "%s: %s", filename,
-                    strerror(errno));
-           _cupsSetError(IPP_INTERNAL_ERROR, buffer, 0);
+         while ((bytes = cupsFileRead(reqfile, buffer, sizeof(buffer))) > 0)
+           length += bytes;
 
-           status = HTTP_ERROR;
-         }
-         else
-           length += fileinfo.st_size;
+         cupsFileClose(reqfile);
        }
       }
 
@@ -2138,23 +2173,29 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
       * Send the request...
       */
 
-      response = NULL;
+      response    = NULL;
+      repeat_test = 0;
+      prev_pass   = 1;
 
       if (status != HTTP_ERROR)
       {
-       while (!response && !Cancel)
+       while (!response && !Cancel && prev_pass)
        {
          status = cupsSendRequest(http, request, resource, length);
 
          if (!Cancel && status == HTTP_CONTINUE &&
              request->state == IPP_DATA && filename[0])
          {
-           if ((fd = open(filename, O_RDONLY | O_BINARY)) >= 0)
+           if ((reqfile = cupsFileOpen(filename, "r")) != NULL)
            {
-             while (!Cancel && (bytes = read(fd, buffer, sizeof(buffer))) > 0)
+             while (!Cancel &&
+                    (bytes = cupsFileRead(reqfile, buffer,
+                                          sizeof(buffer))) > 0)
                if ((status = cupsWriteRequestData(http, buffer,
                                                   bytes)) != HTTP_CONTINUE)
                  break;
+
+             cupsFileClose(reqfile);
            }
            else
            {
@@ -2184,13 +2225,14 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
 #endif /* WIN32 */
          {
            if (httpReconnect(http))
-           {
-             print_fatal_error("Unable to connect to %s on port %d - %s",
-                               vars->hostname, vars->port,
-                               cupsLastErrorString());
-             pass = 0;
-             goto test_exit;
-           }
+             prev_pass = 0;
+         }
+         else if (status == HTTP_ERROR)
+         {
+           if (!Cancel)
+             httpReconnect(http);
+
+           prev_pass = 0;
          }
        }
       }
@@ -2199,9 +2241,6 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
       * Check results of request...
       */
 
-      repeat_test = 0;
-      prev_pass   = 1;
-
       if (!response)
        prev_pass = pass = 0;
       else
@@ -2345,12 +2384,16 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
              continue;
            }
 
+           if (found)
+             _ippAttrString(found, buffer, sizeof(buffer));
+
            if (found &&
-               !with_value(expect->with_value, expect->with_regex, found, 0))
+               !with_value(expect->with_value, expect->with_regex, found, 0,
+                           buffer, sizeof(buffer)))
            {
              if (expect->define_no_match)
                set_variable(vars, expect->define_no_match, "1");
-             else if (!expect->define_match)
+             else if (!expect->define_match && !expect->define_value)
                prev_pass = pass = 0;
 
               if (expect->repeat_no_match)
@@ -2364,7 +2407,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
            {
              if (expect->define_no_match)
                set_variable(vars, expect->define_no_match, "1");
-             else if (!expect->define_match)
+             else if (!expect->define_match && !expect->define_value)
                prev_pass = pass = 0;
 
               if (expect->repeat_no_match)
@@ -2382,7 +2425,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
              {
                if (expect->define_no_match)
                  set_variable(vars, expect->define_no_match, "1");
-               else if (!expect->define_match)
+               else if (!expect->define_match && !expect->define_value)
                  prev_pass = pass = 0;
 
                if (expect->repeat_no_match)
@@ -2396,10 +2439,7 @@ do_tests(_cups_vars_t *vars,             /* I - Variables */
              set_variable(vars, expect->define_match, "1");
 
            if (found && expect->define_value)
-           {
-             _ippAttrString(found, token, sizeof(token));
-             set_variable(vars, expect->define_value, token);
-           }
+             set_variable(vars, expect->define_value, buffer);
 
             if (found && expect->repeat_match)
              repeat_test = 1;
@@ -2419,7 +2459,12 @@ do_tests(_cups_vars_t *vars,             /* I - Variables */
 
     ippDelete(request);
 
-    request   = NULL;
+    request = NULL;
+
+    if (prev_pass)
+      PassCount ++;
+    else
+      FailCount ++;
 
     if (Output == _CUPS_OUTPUT_PLIST)
     {
@@ -2701,7 +2746,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
 
        for (i = num_expects, expect = expects; i > 0; i --, expect ++)
        {
-         if (expect->define_match || expect->define_no_match)
+         if (expect->define_match || expect->define_no_match ||
+             expect->define_value)
            continue;
 
          if (expect->if_defined && !get_variable(vars, expect->if_defined))
@@ -2729,7 +2775,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
                               expect->name, ippTagString(expect->in_group),
                               ippTagString(found->group_tag));
 
-           if (!with_value(expect->with_value, expect->with_regex, found, 0))
+           if (!with_value(expect->with_value, expect->with_regex, found, 0,
+                           buffer, sizeof(buffer)))
            {
              if (expect->with_regex)
                print_test_error("EXPECTED: %s WITH-VALUE /%s/",
@@ -2738,7 +2785,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
                print_test_error("EXPECTED: %s WITH-VALUE \"%s\"",
                                 expect->name, expect->with_value);
 
-             with_value(expect->with_value, expect->with_regex, found, 1);
+             with_value(expect->with_value, expect->with_regex, found, 1,
+                        buffer, sizeof(buffer));
            }
 
            if (expect->count > 0 && found->num_values != expect->count)
@@ -3509,146 +3557,149 @@ print_attr(ipp_attribute_t *attr,     /* I  - Attribute to print */
     print_xml_string("key", attr->name);
     if (attr->num_values > 1)
       puts("<array>");
-  }
-  else if (Output == _CUPS_OUTPUT_TEST)
-  {
-    if (!attr->name)
-    {
-      puts("        -- separator --");
-      return;
-    }
 
-    printf("        %s (%s%s) = ", attr->name,
-          attr->num_values > 1 ? "1setOf " : "",
-          ippTagString(attr->value_tag));
-  }
+    switch (attr->value_tag)
+    {
+      case IPP_TAG_INTEGER :
+      case IPP_TAG_ENUM :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+             printf("<integer>%d</integer>\n", attr->values[i].integer);
+           else
+             printf("%d ", attr->values[i].integer);
+         break;
 
-  switch (attr->value_tag)
-  {
-    case IPP_TAG_INTEGER :
-    case IPP_TAG_ENUM :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
-           printf("<integer>%d</integer>\n", attr->values[i].integer);
-         else
-           printf("%d ", attr->values[i].integer);
-       break;
+      case IPP_TAG_BOOLEAN :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+             puts(attr->values[i].boolean ? "<true />" : "<false />");
+           else if (attr->values[i].boolean)
+             fputs("true ", stdout);
+           else
+             fputs("false ", stdout);
+         break;
 
-    case IPP_TAG_BOOLEAN :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
-           puts(attr->values[i].boolean ? "<true />" : "<false />");
-         else if (attr->values[i].boolean)
-           fputs("true ", stdout);
-         else
-           fputs("false ", stdout);
-       break;
+      case IPP_TAG_RANGE :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+             printf("<dict><key>lower</key><integer>%d</integer>"
+                    "<key>upper</key><integer>%d</integer></dict>\n",
+                    attr->values[i].range.lower, attr->values[i].range.upper);
+           else
+             printf("%d-%d ", attr->values[i].range.lower,
+                    attr->values[i].range.upper);
+         break;
 
-    case IPP_TAG_RANGE :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
-           printf("<dict><key>lower</key><integer>%d</integer>"
-                  "<key>upper</key><integer>%d</integer></dict>\n",
-                  attr->values[i].range.lower, attr->values[i].range.upper);
-         else
-           printf("%d-%d ", attr->values[i].range.lower,
-                  attr->values[i].range.upper);
-       break;
+      case IPP_TAG_RESOLUTION :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+             printf("<dict><key>xres</key><integer>%d</integer>"
+                    "<key>yres</key><integer>%d</integer>"
+                    "<key>units</key><string>%s</string></dict>\n",
+                    attr->values[i].resolution.xres,
+                    attr->values[i].resolution.yres,
+                    attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+                        "dpi" : "dpc");
+           else
+             printf("%dx%d%s ", attr->values[i].resolution.xres,
+                    attr->values[i].resolution.yres,
+                    attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+                        "dpi" : "dpc");
+         break;
 
-    case IPP_TAG_RESOLUTION :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
-           printf("<dict><key>xres</key><integer>%d</integer>"
-                  "<key>yres</key><integer>%d</integer>"
-                  "<key>units</key><string>%s</string></dict>\n",
-                  attr->values[i].resolution.xres,
-                  attr->values[i].resolution.yres,
-                  attr->values[i].resolution.units == IPP_RES_PER_INCH ?
-                      "dpi" : "dpc");
-         else
-           printf("%dx%d%s ", attr->values[i].resolution.xres,
-                  attr->values[i].resolution.yres,
-                  attr->values[i].resolution.units == IPP_RES_PER_INCH ?
-                      "dpi" : "dpc");
-       break;
+      case IPP_TAG_DATE :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+             printf("<date>%s</date>\n", iso_date(attr->values[i].date));
+           else
+             printf("%s ", iso_date(attr->values[i].date));
+         break;
 
-    case IPP_TAG_DATE :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
-            printf("<date>%s</date>\n", iso_date(attr->values[i].date));
-          else
-           printf("%s ", iso_date(attr->values[i].date));
-        break;
+      case IPP_TAG_STRING :
+      case IPP_TAG_TEXT :
+      case IPP_TAG_NAME :
+      case IPP_TAG_KEYWORD :
+      case IPP_TAG_CHARSET :
+      case IPP_TAG_URI :
+      case IPP_TAG_MIMETYPE :
+      case IPP_TAG_LANGUAGE :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+             print_xml_string("string", attr->values[i].string.text);
+           else
+             printf("\"%s\" ", attr->values[i].string.text);
+         break;
 
-    case IPP_TAG_STRING :
-    case IPP_TAG_TEXT :
-    case IPP_TAG_NAME :
-    case IPP_TAG_KEYWORD :
-    case IPP_TAG_CHARSET :
-    case IPP_TAG_URI :
-    case IPP_TAG_MIMETYPE :
-    case IPP_TAG_LANGUAGE :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
-           print_xml_string("string", attr->values[i].string.text);
-         else
-           printf("\"%s\" ", attr->values[i].string.text);
-       break;
+      case IPP_TAG_TEXTLANG :
+      case IPP_TAG_NAMELANG :
+         for (i = 0; i < attr->num_values; i ++)
+           if (Output == _CUPS_OUTPUT_PLIST)
+           {
+             fputs("<dict><key>language</key><string>", stdout);
+             print_xml_string(NULL, attr->values[i].string.charset);
+             fputs("</string><key>string</key><string>", stdout);
+             print_xml_string(NULL, attr->values[i].string.text);
+             puts("</string></dict>");
+           }
+           else
+             printf("\"%s\"(%s) ", attr->values[i].string.text,
+                    attr->values[i].string.charset);
+         break;
 
-    case IPP_TAG_TEXTLANG :
-    case IPP_TAG_NAMELANG :
-       for (i = 0; i < attr->num_values; i ++)
-         if (Output == _CUPS_OUTPUT_PLIST)
+      case IPP_TAG_BEGIN_COLLECTION :
+         for (i = 0; i < attr->num_values; i ++)
          {
-           fputs("<dict><key>language</key><string>", stdout);
-           print_xml_string(NULL, attr->values[i].string.charset);
-           fputs("</string><key>string</key><string>", stdout);
-           print_xml_string(NULL, attr->values[i].string.text);
-           puts("</string></dict>");
+           if (Output == _CUPS_OUTPUT_PLIST)
+           {
+             puts("<dict>");
+             for (colattr = attr->values[i].collection->attrs;
+                  colattr;
+                  colattr = colattr->next)
+               print_attr(colattr, NULL);
+             puts("</dict>");
+           }
+           else
+           {
+             if (i)
+               putchar(' ');
+
+             print_col(attr->values[i].collection);
+           }
          }
-         else
-           printf("\"%s\"(%s) ", attr->values[i].string.text,
-                  attr->values[i].string.charset);
-       break;
+         break;
 
-    case IPP_TAG_BEGIN_COLLECTION :
-       for (i = 0; i < attr->num_values; i ++)
-       {
+      default :
          if (Output == _CUPS_OUTPUT_PLIST)
-         {
-           puts("<dict>");
-           for (colattr = attr->values[i].collection->attrs;
-                colattr;
-                colattr = colattr->next)
-             print_attr(colattr, NULL);
-           puts("</dict>");
-         }
+           printf("<string>&lt;&lt;%s&gt;&gt;</string>\n",
+                  ippTagString(attr->value_tag));
          else
-         {
-           if (i)
-             putchar(' ');
-
-           print_col(attr->values[i].collection);
-          }
-       }
-       break;
-
-    default :
-       if (Output == _CUPS_OUTPUT_PLIST)
-         printf("<string>&lt;&lt;%s&gt;&gt;</string>\n",
-                ippTagString(attr->value_tag));
-       else
-         fputs(ippTagString(attr->value_tag), stdout);
-       break;
-  }
+           fputs(ippTagString(attr->value_tag), stdout);
+         break;
+    }
 
-  if (Output == _CUPS_OUTPUT_PLIST)
-  {
     if (attr->num_values > 1)
       puts("</array>");
   }
   else
-    putchar('\n');
+  {
+    char       buffer[8192];           /* Value buffer */
+
+    if (Output == _CUPS_OUTPUT_TEST)
+    {
+      if (!attr->name)
+      {
+        puts("        -- separator --");
+        return;
+      }
+
+      printf("        %s (%s%s) = ", attr->name,
+            attr->num_values > 1 ? "1setOf " : "",
+            ippTagString(attr->value_tag));
+    }
+
+    _ippAttrString(attr, buffer, sizeof(buffer));
+    puts(buffer);
+  }
 }
 
 
@@ -4176,6 +4227,9 @@ sigterm_handler(int sig)          /* I - Signal number (unused) */
   (void)sig;
 
   Cancel = 1;
+
+  signal(SIGINT, SIG_DFL);
+  signal(SIGTERM, SIG_DFL);
 }
 #endif /* !WIN32 */
 
@@ -4969,12 +5023,16 @@ static int                              /* O - 1 on match, 0 on non-match */
 with_value(char            *value,     /* I - Value string */
            int             regex,      /* I - Value is a regular expression */
            ipp_attribute_t *attr,      /* I - Attribute to compare */
-          int             report)      /* I - 1 = report failures */
+          int             report,      /* I - 1 = report failures */
+          char            *matchbuf,   /* I - Buffer to hold matching value */
+          size_t          matchlen)    /* I - Length of match buffer */
 {
   int  i;                              /* Looping var */
   char *valptr;                        /* Pointer into value */
 
 
+  *matchbuf = '\0';
+
  /*
   * NULL matches everything.
   */
@@ -5025,15 +5083,24 @@ with_value(char            *value,      /* I - Value string */
            {
              case '=' :
                  if (attr->values[i].integer == intvalue)
+                 {
+                   snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
                    return (1);
+                 }
                  break;
              case '<' :
                  if (attr->values[i].integer < intvalue)
+                 {
+                   snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
                    return (1);
+                 }
                  break;
              case '>' :
                  if (attr->values[i].integer > intvalue)
+                 {
+                   snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
                    return (1);
+                 }
                  break;
            }
          }
@@ -5083,15 +5150,30 @@ with_value(char            *value,      /* I - Value string */
              case '=' :
                  if (attr->values[i].range.lower == intvalue ||
                      attr->values[i].range.upper == intvalue)
+                 {
+                   snprintf(matchbuf, matchlen, "%d-%d",
+                            attr->values[i].range.lower,
+                            attr->values[i].range.upper);
                    return (1);
+                 }
                  break;
              case '<' :
                  if (attr->values[i].range.upper < intvalue)
+                 {
+                   snprintf(matchbuf, matchlen, "%d-%d",
+                            attr->values[i].range.lower,
+                            attr->values[i].range.upper);
                    return (1);
+                 }
                  break;
              case '>' :
-                 if (attr->values[i].range.upper > intvalue)
+                 if (attr->values[i].range.lower > intvalue)
+                 {
+                   snprintf(matchbuf, matchlen, "%d-%d",
+                            attr->values[i].range.lower,
+                            attr->values[i].range.upper);
                    return (1);
+                 }
                  break;
            }
          }
@@ -5110,7 +5192,10 @@ with_value(char            *value,       /* I - Value string */
        for (i = 0; i < attr->num_values; i ++)
        {
           if (!strcmp(value, "true") == attr->values[i].boolean)
+          {
+            strlcpy(matchbuf, value, matchlen);
            return (1);
+         }
        }
 
        if (report)
@@ -5122,7 +5207,13 @@ with_value(char            *value,       /* I - Value string */
        break;
 
     case IPP_TAG_NOVALUE :
-        return (!strcmp(value, "no-value") || !strncmp(value, "no-value,", 9));
+        if (!strcmp(value, "no-value") || !strncmp(value, "no-value,", 9))
+        {
+          strlcpy(matchbuf, "no-value", matchlen);
+          return (1);
+        }
+        else
+          return (0);
 
     case IPP_TAG_CHARSET :
     case IPP_TAG_KEYWORD :
@@ -5171,6 +5262,9 @@ with_value(char            *value,        /* I - Value string */
 
          regfree(&re);
 
+          if (i == attr->num_values)
+            strlcpy(matchbuf, attr->values[0].string.text, matchlen);
+
           return (i == attr->num_values);
        }
        else
@@ -5183,7 +5277,10 @@ with_value(char            *value,       /* I - Value string */
          for (i = 0; i < attr->num_values; i ++)
          {
            if (!strcmp(value, attr->values[i].string.text))
+           {
+             strlcpy(matchbuf, attr->values[i].string.text, matchlen);
              return (1);
+           }
          }
 
          if (report)
diff --git a/test/xmltotest.c b/test/xmltotest.c
new file mode 100644 (file)
index 0000000..14ecf57
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * "$Id$"
+ *
+ *   IANA XML registration to test file generator for CUPS.
+ *
+ *   Copyright 2011 by Apple Inc.
+ *
+ *   These coded instructions, statements, and computer programs are the
+ *   property of Apple Inc. and are protected by Federal copyright
+ *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ *   which should have been included with this file.  If this file is
+ *   file is missing or damaged, see the license at "http://www.cups.org/".
+ *
+ *   This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Usage:
+ *
+ *   ./xmltotest [--ref standard] {--job|--printer} [XML file/URL] >file.test
+ *
+ *   If not specified, loads the XML registrations from:
+ *
+ *     http://www.iana.org/assignments/ipp-registrations/ipp-registrations.xml
+ *
+ *   "Standard" is of the form "rfcNNNN" or "pwgNNNN.N".
+ *
+ * Contents:
+ *
+ *   main()        - Process command-line arguments.
+ *   compare_reg()  - Compare two registrations.
+ *   load_xml()     - Load the XML registration file or URL.
+ *   match_xref()   - Compare the xref against the named standard.
+ *   new_reg()     - Create a new registration record.
+ *   usage()       - Show usage message.
+ *   write_expect() - Write an EXPECT test for an attribute.
+ */
+
+#include <mxml.h>
+#include <cups/cups.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+/*
+ * Local types...
+ */
+
+typedef struct _cups_reg_s             /**** Registration data ****/
+{
+  char *name,                          /* Attribute name */
+       *member,                        /* Member attribute name */
+       *sub_member,                    /* Sub-member attribute name */
+       *syntax;                        /* Attribute syntax */
+} _cups_reg_t;
+
+
+/*
+ * Local functions...
+ */
+
+static int             compare_reg(_cups_reg_t *a, _cups_reg_t *b);
+static mxml_node_t     *load_xml(const char *reg_file);
+static int             match_xref(mxml_node_t *xref, const char *standard);
+static _cups_reg_t     *new_reg(mxml_node_t *name, mxml_node_t *member,
+                                mxml_node_t *sub_member, mxml_node_t *syntax);
+static int             usage(void);
+static void            write_expect(_cups_reg_t *reg, ipp_tag_t group);
+
+
+/*
+ * 'main()' - Process command-line arguments.
+ */
+
+int
+main(int  argc,                                /* I - Number of command-line args */
+     char *argv[])                     /* I - Command-line arguments */
+{
+  int          i;                      /* Looping var */
+  const char   *reg_file = NULL,       /* Registration file/URL to use */
+               *reg_standard = NULL;   /* Which standard to extract */
+  mxml_node_t  *reg_xml,               /* Registration XML data */
+               *reg_2,                 /* ipp-registrations-2 */
+               *reg_record,            /* <record> */
+               *reg_collection,        /* <collection> */
+               *reg_name,              /* <name> */
+               *reg_member,            /* <member_attribute> */
+               *reg_sub_member,        /* <sub-member_attribute> */
+               *reg_syntax,            /* <syntax> */
+               *reg_xref;              /* <xref> */
+  cups_array_t *attrs;                 /* Attribute registrations */
+  _cups_reg_t  *current;               /* Current attribute registration */
+  ipp_tag_t    group = IPP_TAG_ZERO,   /* Which attributes to test */
+               reg_group;              /* Group for registration */
+
+
+ /*
+  * Parse command-line...
+  */
+
+  for (i = 1; i < argc; i ++)
+  {
+    if (!strcmp(argv[i], "--job") && group == IPP_TAG_ZERO)
+      group = IPP_TAG_JOB;
+    else if (!strcmp(argv[i], "--ref"))
+    {
+      i ++;
+      if (i >= argc)
+        return (usage());
+
+      reg_standard = argv[i];
+    }
+    else if (!strcmp(argv[i], "--printer") && group == IPP_TAG_ZERO)
+      group = IPP_TAG_PRINTER;
+    else if (argv[i][0] == '-' || reg_file)
+      return (usage());
+    else
+      reg_file = argv[i];
+  }
+
+  if (group == IPP_TAG_ZERO)
+    return (usage());
+
+ /*
+  * Read registrations...
+  */
+
+  if (!reg_file)
+    reg_file = "http://www.iana.org/assignments/ipp-registrations/"
+              "ipp-registrations.xml";
+
+  if ((reg_xml = load_xml(reg_file)) == NULL)
+    return (1);
+
+ /*
+  * Scan registrations for attributes...
+  */
+
+  if ((reg_2 = mxmlFindElement(reg_xml, reg_xml, "registry", "id",
+                               "ipp-registrations-2",
+                               MXML_DESCEND)) == NULL)
+  {
+    fprintf(stderr, "xmltotest: No IPP attribute registrations in \"%s\".\n",
+            reg_file);
+    return (1);
+  }
+
+  attrs = cupsArrayNew((cups_array_func_t)compare_reg, NULL);
+
+  for (reg_record = mxmlFindElement(reg_2, reg_2, "record", NULL, NULL,
+                                   MXML_DESCEND);
+       reg_record;
+       reg_record = mxmlFindElement(reg_record, reg_2, "record", NULL, NULL,
+                                    MXML_NO_DESCEND))
+  {
+   /*
+    * Get the values from the current record...
+    */
+
+    reg_collection = mxmlFindElement(reg_record, reg_record, "collection",
+                                     NULL, NULL, MXML_DESCEND);
+    reg_name       = mxmlFindElement(reg_record, reg_record, "name", NULL, NULL,
+                                     MXML_DESCEND);
+    reg_member     = mxmlFindElement(reg_record, reg_record, "member_attribute",
+                                     NULL, NULL, MXML_DESCEND);
+    reg_sub_member = mxmlFindElement(reg_record, reg_record,
+                                     "sub-member_attribute", NULL, NULL,
+                                     MXML_DESCEND);
+    reg_syntax     = mxmlFindElement(reg_record, reg_record, "syntax", NULL,
+                                     NULL, MXML_DESCEND);
+    reg_xref       = mxmlFindElement(reg_record, reg_record, "xref", NULL, NULL,
+                                     MXML_DESCEND);
+
+    if (!reg_collection || !reg_name || !reg_syntax || !reg_xref)
+      continue;
+
+   /*
+    * Filter based on group and standard...
+    */
+
+    if (!strcmp(reg_collection->child->value.opaque, "Printer Description"))
+      reg_group = IPP_TAG_PRINTER;
+    else if (!strcmp(reg_collection->child->value.opaque, "Job Description"))
+      reg_group = IPP_TAG_JOB;
+    else if (!strcmp(reg_collection->child->value.opaque, "Job Template"))
+    {
+      if (strstr(reg_name->child->value.opaque, "-default") ||
+          strstr(reg_name->child->value.opaque, "-supported"))
+       reg_group = IPP_TAG_PRINTER;
+      else
+       reg_group = IPP_TAG_JOB;
+    }
+    else
+      reg_group = IPP_TAG_ZERO;
+
+    if (reg_group != group)
+      continue;
+
+    if (reg_standard && !match_xref(reg_xref, reg_standard))
+      continue;
+
+   /*
+    * Add the record to the array...
+    */
+
+    if ((current = new_reg(reg_name, reg_member, reg_sub_member,
+                           reg_syntax)) != NULL)
+      cupsArrayAdd(attrs, current);
+  }
+
+ /*
+  * Write out a test for all of the selected attributes...
+  */
+
+  puts("{");
+
+  if (group == IPP_TAG_PRINTER)
+  {
+    puts("\tOPERATION Get-Printer-Attributes");
+    puts("\tGROUP operation-attributes-tag");
+    puts("\tATTR charset attributes-charset utf-8");
+    puts("\tATTR naturalLanguage attributes-natural-language en");
+    puts("\tATTR uri printer-uri $uri");
+    puts("\tATTR name requesting-user-name $user");
+    puts("\tATTR keyword requested-attributes all,media-col-database");
+    puts("");
+    puts("\tSTATUS successful-ok");
+    puts("\tSTATUS successful-ok-ignored-or-substituted-attributes");
+    puts("");
+  }
+  else
+  {
+    puts("\tOPERATION Get-Job-Attributes");
+    puts("\tGROUP operation-attributes-tag");
+    puts("\tATTR charset attributes-charset utf-8");
+    puts("\tATTR naturalLanguage attributes-natural-language en");
+    puts("\tATTR uri printer-uri $uri");
+    puts("\tATTR integer job-id $job-id");
+    puts("\tATTR name requesting-user-name $user");
+    puts("");
+    puts("\tSTATUS successful-ok");
+    puts("");
+  }
+
+  for (current = cupsArrayFirst(attrs);
+       current;
+       current = cupsArrayNext(attrs))
+    write_expect(current, group);
+
+  puts("}");
+
+  return (0);
+}
+
+
+/*
+ * 'compare_reg()' - Compare two registrations.
+ */
+
+static int                             /* O - Result of comparison */
+compare_reg(_cups_reg_t *a,            /* I - First registration */
+            _cups_reg_t *b)            /* I - Second registration */
+{
+  int  retval;                         /* Return value */
+
+
+  if ((retval = strcmp(a->name, b->name)) != 0)
+    return (retval);
+
+  if (a->member && b->member)
+    retval = strcmp(a->member, b->member);
+  else if (a->member)
+    retval = 1;
+  else if (b->member)
+    retval = -1;
+
+  if (retval)
+    return (retval);
+
+  if (a->sub_member && b->sub_member)
+    retval = strcmp(a->sub_member, b->sub_member);
+  else if (a->sub_member)
+    retval = 1;
+  else if (b->sub_member)
+    retval = -1;
+
+  return (retval);
+}
+
+
+/*
+ * 'load_xml()' - Load the XML registration file or URL.
+ */
+
+static mxml_node_t *                   /* O - XML file or NULL */
+load_xml(const char *reg_file)         /* I - Filename or URL */
+{
+  mxml_node_t          *xml;           /* XML file */
+  char                 scheme[256],    /* Scheme */
+                       userpass[256],  /* Username and password */
+                       hostname[256],  /* Hostname */
+                       resource[1024], /* Resource path */
+                       filename[1024]; /* Temporary file */
+  int                  port,           /* Port number */
+                       fd;             /* File descriptor */
+
+
+  if (httpSeparateURI(HTTP_URI_CODING_ALL, reg_file, scheme, sizeof(scheme),
+                      userpass, sizeof(userpass), hostname, sizeof(hostname),
+                      &port, resource, sizeof(resource)) < HTTP_URI_OK)
+  {
+    fprintf(stderr, "xmltotest: Bad URI or filename \"%s\".\n", reg_file);
+    return (NULL);
+  }
+
+  if (!strcmp(scheme, "file"))
+  {
+   /*
+    * Local file...
+    */
+
+    if ((fd = open(resource, O_RDONLY)) < 0)
+    {
+      fprintf(stderr, "xmltotest: Unable to open \"%s\": %s\n", resource,
+              strerror(errno));
+      return (NULL);
+    }
+
+    filename[0] = '\0';
+  }
+  else if (strcmp(scheme, "http") && strcmp(scheme, "https"))
+  {
+    fprintf(stderr, "xmltotest: Unsupported URI scheme \"%s\".\n", scheme);
+    return (NULL);
+  }
+  else
+  {
+    http_t             *http;          /* HTTP connection */
+    http_encryption_t  encryption;     /* Encryption to use */
+    http_status_t      status;         /* Status of HTTP GET */
+
+    if (!strcmp(scheme, "https") || port == 443)
+      encryption = HTTP_ENCRYPT_ALWAYS;
+    else
+      encryption = HTTP_ENCRYPT_IF_REQUESTED;
+
+    if ((http = httpConnectEncrypt(hostname, port, encryption)) == NULL)
+    {
+      fprintf(stderr, "xmltotest: Unable to connect to \"%s\": %s\n", hostname,
+              cupsLastErrorString());
+      return (NULL);
+    }
+
+    if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
+    {
+      fprintf(stderr, "xmltotest: Unable to create temporary file: %s\n",
+              strerror(errno));
+      httpClose(http);
+      return (NULL);
+    }
+
+    status = cupsGetFd(http, resource, fd);
+    httpClose(http);
+
+    if (status != HTTP_OK)
+    {
+      fprintf(stderr, "mxmltotest: Unable to get \"%s\": %d\n", reg_file,
+              status);
+      close(fd);
+      unlink(filename);
+      return (NULL);
+    }
+
+    lseek(fd, 0, SEEK_SET);
+  }
+
+ /*
+  * Load the XML file...
+  */
+
+  xml = mxmlLoadFd(NULL, fd, MXML_OPAQUE_CALLBACK);
+
+  close(fd);
+
+  if (filename[0])
+    unlink(filename);
+
+  return (xml);
+}
+
+
+/*
+ * 'match_xref()' - Compare the xref against the named standard.
+ */
+
+static int                             /* O - 1 if match, 0 if not */
+match_xref(mxml_node_t *xref,          /* I - <xref> node */
+           const char  *standard)      /* I - Name of standard */
+{
+  const char   *data;                  /* "data" attribute */
+  char         s[256];                 /* String to look for */
+
+
+  if ((data = mxmlElementGetAttr(xref, "data")) == NULL)
+    return (1);
+
+  if (!strcmp(data, standard))
+    return (1);
+
+  if (!strncmp(standard, "pwg", 3))
+  {
+    snprintf(s, sizeof(s), "-%s.pdf", standard + 3);
+    return (strstr(data, s) != NULL);
+  }
+  else
+    return (0);
+}
+
+
+/*
+ * 'new_reg()' - Create a new registration record.
+ */
+
+static _cups_reg_t *                   /* O - New record */
+new_reg(mxml_node_t *name,             /* I - Attribute name */
+        mxml_node_t *member,           /* I - Member attribute, if any */
+        mxml_node_t *sub_member,       /* I - Sub-member attribute, if any */
+        mxml_node_t *syntax)           /* I - Syntax */
+{
+  _cups_reg_t  *reg;                   /* New record */
+
+
+  if ((reg = calloc(1, sizeof(_cups_reg_t))) != NULL)
+  {
+    reg->name   = name->child->value.opaque;
+    reg->syntax = syntax->child->value.opaque;
+
+    if (member)
+      reg->member = member->child->value.opaque;
+
+    if (sub_member)
+      reg->sub_member = sub_member->child->value.opaque;
+  }
+
+  return (reg);
+}
+
+
+/*
+ * 'usage()' - Show usage message.
+ */
+
+static int                             /* O - Exit status */
+usage(void)
+{
+  puts("Usage ./xmltotest [--ref standard] {--job|--printer} [XML file/URL] "
+       ">file.test");
+  return (1);
+}
+
+
+/*
+ * 'write_expect()' - Write an EXPECT test for an attribute.
+ */
+
+static void
+write_expect(_cups_reg_t *reg,         /* I - Registration information */
+             ipp_tag_t   group)                /* I - Attribute group tag */
+{
+  const char   *syntax;                /* Pointer into syntax string */
+  int          single = 1,             /* Single valued? */
+               skip = 0;               /* Skip characters? */
+
+
+  printf("\tEXPECT ?%s OF-TYPE ", reg->name);
+
+  syntax = reg->syntax;
+
+  while (*syntax)
+  {
+    if (!strncmp(syntax, "1setOf", 6))
+    {
+      single = 0;
+      syntax += 6;
+
+      while (isspace(*syntax & 255))
+        syntax ++;
+
+      if (*syntax == '(')
+        syntax ++;
+    }
+    else if (!strncmp(syntax, "type1", 5) || !strncmp(syntax, "type2", 5) ||
+             !strncmp(syntax, "type3", 5))
+      syntax += 5;
+    else if (*syntax == '(')
+    {
+      skip = 1;
+      syntax ++;
+    }
+    else if (*syntax == ')')
+    {
+      skip = 0;
+      syntax ++;
+    }
+    else if (!skip && (*syntax == '|' || isalpha(*syntax & 255)))
+      putchar(*syntax++);
+    else
+      syntax ++;
+  }
+
+  if (single)
+    printf(" IN-GROUP %s COUNT 1\n", ippTagString(group));
+  else
+    printf(" IN-GROUP %s\n", ippTagString(group));
+}
+
+
+/*
+ * End of "$Id$".
+ */
index 46fdf2fa6ed650876e77014d2e215a8de13f1707..ba471ca066ace6caae474b78d32ed63bf91fd376 100644 (file)
@@ -27,11 +27,9 @@ if test $# = 0; then
        echo Updating to get snapshot version...
        svn up
        rev=`svnversion . | sed -e '1,$s/[a-zA-Z]//g'`
-       fileversion="1.5svn-r$rev"
-       version=snapshots
+       fileversion="`date '+%Y%m%d'`-r$rev"
 else
        fileversion=$1
-       version=$1
 fi
 
 if (svn st | grep -qv '^\?'); then
@@ -47,13 +45,19 @@ test -d $pkgdir && rm -r $pkgdir
 mkdir $pkgdir || exit 1
 
 echo Copying package files
-cp IPPTOOL.txt LICENSE.txt $pkgdir
+cp CHANGES-IPPTOOL.txt IPPTOOL.txt LICENSE.txt $pkgdir
 cp doc/help/man-ipptool*.html $pkgdir
+cp test/color.jpg $pkgdir
 cp test/create-printer-subscription.test $pkgdir
+cp test/document-*.pdf $pkgdir
+cp test/document-*.ps $pkgdir
 cp test/get-completed-jobs.test test/get-jobs.test $pkgdir
 cp test/get-printer-attributes.test $pkgdir
+cp test/gray.jpg $pkgdir
 cp test/ipp-[12].*.test $pkgdir
 cp test/ipptool-static $pkgdir/ipptool
+cp test/onepage-*.pdf $pkgdir
+cp test/onepage-*.ps $pkgdir
 cp test/testfile.* $pkgdir
 
 if test `uname` = Darwin; then
@@ -69,9 +73,9 @@ else
 fi
 
 if test -x /usr/bin/md5sum; then
-        (md5sum $pkgfile | awk '{print $1, "'$fileversion' cups/'$version'/" $2}')
+        (md5sum $pkgfile | awk '{print $1, "'$fileversion' cups/ipptool/" $2}')
 elif test -x /sbin/md5; then
-        (md5 $pkgfile | awk '{print $4, "'$fileversion' cups/'$version'/" substr($2, 2, length($2) - 2)}')
+        (md5 $pkgfile | awk '{print $4, "'$fileversion' cups/ipptool/" substr($2, 2, length($2) - 2)}')
 fi
 
 echo Removing temporary files...