]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.5svn-r9000.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Thu, 25 Feb 2010 00:52:27 +0000 (00:52 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Thu, 25 Feb 2010 00:52:27 +0000 (00:52 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@1912 a1ca3aef-8c08-0410-bb20-df032aa958be

331 files changed:
CHANGES-1.4.txt
CHANGES.txt
Makedefs.in
Makefile
backend/Dependencies
backend/Makefile
backend/ieee1284.c
backend/scsi-irix.c [deleted file]
backend/scsi-linux.c [deleted file]
backend/scsi.c [deleted file]
backend/socket.c
backend/usb-libusb.c
cgi-bin/Dependencies
cgi-bin/Makefile
cgi-bin/admin.c
cgi-bin/cgi.h
cgi-bin/libcupscgi.exp
cgi-bin/template.c
cgi-bin/var.c
conf/mime.convs.in
conf/mime.types
config-scripts/cups-common.m4
config-scripts/cups-defaults.m4
config-scripts/cups-launchd.m4
config-scripts/cups-sharedlibs.m4
config-scripts/cups-ssl.m4
configure.in
cups/Makefile
cups/attr.c
cups/debug.c
cups/globals.c
cups/globals.h
cups/http.c
cups/i18n.h
cups/ipp-support.c
cups/ipp.c
cups/libcups.exp
cups/libcups2.def
cups/libcups_s.exp
cups/options.c
cups/page.c
cups/ppd-private.h
cups/tempfile.c
data/HPGLprolog [deleted file]
data/Makefile
doc/help/ref-cupsd-conf.html.in
doc/help/ref-page_log.html
doc/help/spec-cmp.html
driver/Dependencies
driver/Makefile
filter/Dependencies
filter/Makefile
filter/form-main.c [deleted file]
filter/form-ps.c [deleted file]
filter/form-tree.c [deleted file]
filter/form.h [deleted file]
filter/hpgl-attr.c [deleted file]
filter/hpgl-char.c [deleted file]
filter/hpgl-config.c [deleted file]
filter/hpgl-input.c [deleted file]
filter/hpgl-main.c [deleted file]
filter/hpgl-polygon.c [deleted file]
filter/hpgl-prolog.c [deleted file]
filter/hpgl-vector.c [deleted file]
filter/hpgltops.h [deleted file]
man/Makefile
man/cupsd.conf.man.in
man/ipp.test.man [new file with mode: 0644]
man/ipptest.man [new file with mode: 0644]
packaging/cups.list.in
packaging/cups.spec.in
ppdc/Makefile
scheduler/Dependencies
scheduler/Makefile
scheduler/cert.c
scheduler/classes.c
scheduler/classes.h
scheduler/client.c
scheduler/conf.c
scheduler/conf.h
scheduler/cups-driverd.cxx
scheduler/ipp.c
scheduler/job.c
scheduler/listen.c
scheduler/main.c
scheduler/printers.c
scheduler/printers.h
standards/Makefile
standards/rfc2046.txt [new file with mode: 0644]
standards/rfc3282.txt [new file with mode: 0644]
standards/rfc4646.txt [new file with mode: 0644]
systemv/Dependencies
systemv/Makefile
systemv/lppasswd.c
systemv/lpstat.c
templates/add-class.tmpl
templates/add-printer.tmpl
templates/add-rss-subscription.tmpl
templates/admin.tmpl
templates/choose-device.tmpl
templates/choose-make.tmpl
templates/choose-model.tmpl
templates/choose-serial.tmpl
templates/choose-uri.tmpl
templates/class-confirm.tmpl
templates/class.tmpl
templates/de/add-class.tmpl
templates/de/add-printer.tmpl
templates/de/add-rss-subscription.tmpl
templates/de/admin.tmpl
templates/de/choose-device.tmpl
templates/de/choose-make.tmpl
templates/de/choose-model.tmpl
templates/de/choose-serial.tmpl
templates/de/choose-uri.tmpl
templates/de/class-confirm.tmpl
templates/de/class.tmpl
templates/de/edit-config.tmpl
templates/de/job-move.tmpl
templates/de/jobs.tmpl
templates/de/list-available-printers.tmpl
templates/de/modify-class.tmpl
templates/de/modify-printer.tmpl
templates/de/printer-confirm.tmpl
templates/de/printer.tmpl
templates/de/samba-export.tmpl
templates/de/set-printer-options-header.tmpl
templates/de/users.tmpl
templates/edit-config.tmpl
templates/es/add-class.tmpl
templates/es/add-printer.tmpl
templates/es/add-rss-subscription.tmpl
templates/es/admin.tmpl
templates/es/choose-device.tmpl
templates/es/choose-make.tmpl
templates/es/choose-model.tmpl
templates/es/choose-serial.tmpl
templates/es/choose-uri.tmpl
templates/es/class-confirm.tmpl
templates/es/class.tmpl
templates/es/edit-config.tmpl
templates/es/job-move.tmpl
templates/es/jobs.tmpl
templates/es/list-available-printers.tmpl
templates/es/modify-class.tmpl
templates/es/modify-printer.tmpl
templates/es/printer-confirm.tmpl
templates/es/printer.tmpl
templates/es/samba-export.tmpl
templates/es/set-printer-options-header.tmpl
templates/es/users.tmpl
templates/eu/add-class.tmpl
templates/eu/add-printer.tmpl
templates/eu/add-rss-subscription.tmpl
templates/eu/admin.tmpl
templates/eu/choose-device.tmpl
templates/eu/choose-make.tmpl
templates/eu/choose-model.tmpl
templates/eu/choose-serial.tmpl
templates/eu/choose-uri.tmpl
templates/eu/class-confirm.tmpl
templates/eu/class.tmpl
templates/eu/edit-config.tmpl
templates/eu/job-move.tmpl
templates/eu/jobs.tmpl
templates/eu/list-available-printers.tmpl
templates/eu/modify-class.tmpl
templates/eu/modify-printer.tmpl
templates/eu/printer-confirm.tmpl
templates/eu/printer.tmpl
templates/eu/samba-export.tmpl
templates/eu/set-printer-options-header.tmpl
templates/eu/users.tmpl
templates/id/add-class.tmpl
templates/id/add-printer.tmpl
templates/id/add-rss-subscription.tmpl
templates/id/admin.tmpl
templates/id/choose-device.tmpl
templates/id/choose-make.tmpl
templates/id/choose-model.tmpl
templates/id/choose-serial.tmpl
templates/id/choose-uri.tmpl
templates/id/class-confirm.tmpl
templates/id/class.tmpl
templates/id/edit-config.tmpl
templates/id/job-move.tmpl
templates/id/jobs.tmpl
templates/id/list-available-printers.tmpl
templates/id/modify-class.tmpl
templates/id/modify-printer.tmpl
templates/id/printer-confirm.tmpl
templates/id/printer.tmpl
templates/id/samba-export.tmpl
templates/id/set-printer-options-header.tmpl
templates/id/users.tmpl
templates/it/add-class.tmpl
templates/it/add-printer.tmpl
templates/it/add-rss-subscription.tmpl
templates/it/admin.tmpl
templates/it/choose-device.tmpl
templates/it/choose-make.tmpl
templates/it/choose-model.tmpl
templates/it/choose-serial.tmpl
templates/it/choose-uri.tmpl
templates/it/class-confirm.tmpl
templates/it/class.tmpl
templates/it/edit-config.tmpl
templates/it/job-move.tmpl
templates/it/jobs.tmpl
templates/it/list-available-printers.tmpl
templates/it/modify-class.tmpl
templates/it/modify-printer.tmpl
templates/it/printer-confirm.tmpl
templates/it/printer.tmpl
templates/it/samba-export.tmpl
templates/it/set-printer-options-header.tmpl
templates/it/users.tmpl
templates/ja/add-class.tmpl
templates/ja/add-printer.tmpl
templates/ja/add-rss-subscription.tmpl
templates/ja/admin.tmpl
templates/ja/choose-device.tmpl
templates/ja/choose-make.tmpl
templates/ja/choose-model.tmpl
templates/ja/choose-serial.tmpl
templates/ja/choose-uri.tmpl
templates/ja/class-confirm.tmpl
templates/ja/class.tmpl
templates/ja/edit-config.tmpl
templates/ja/job-move.tmpl
templates/ja/jobs.tmpl
templates/ja/list-available-printers.tmpl
templates/ja/modify-class.tmpl
templates/ja/modify-printer.tmpl
templates/ja/printer-confirm.tmpl
templates/ja/printer.tmpl
templates/ja/samba-export.tmpl
templates/ja/set-printer-options-header.tmpl
templates/ja/users.tmpl
templates/job-move.tmpl
templates/jobs.tmpl
templates/list-available-printers.tmpl
templates/modify-class.tmpl
templates/modify-printer.tmpl
templates/pl/add-class.tmpl
templates/pl/add-printer.tmpl
templates/pl/add-rss-subscription.tmpl
templates/pl/admin.tmpl
templates/pl/choose-device.tmpl
templates/pl/choose-make.tmpl
templates/pl/choose-model.tmpl
templates/pl/choose-serial.tmpl
templates/pl/choose-uri.tmpl
templates/pl/class-confirm.tmpl
templates/pl/class.tmpl
templates/pl/edit-config.tmpl
templates/pl/job-move.tmpl
templates/pl/jobs.tmpl
templates/pl/list-available-printers.tmpl
templates/pl/modify-class.tmpl
templates/pl/modify-printer.tmpl
templates/pl/printer-confirm.tmpl
templates/pl/printer.tmpl
templates/pl/samba-export.tmpl
templates/pl/set-printer-options-header.tmpl
templates/pl/users.tmpl
templates/printer-confirm.tmpl
templates/printer.tmpl
templates/ru/add-class.tmpl
templates/ru/add-printer.tmpl
templates/ru/add-rss-subscription.tmpl
templates/ru/admin.tmpl
templates/ru/choose-device.tmpl
templates/ru/choose-make.tmpl
templates/ru/choose-model.tmpl
templates/ru/choose-serial.tmpl
templates/ru/choose-uri.tmpl
templates/ru/class-confirm.tmpl
templates/ru/class.tmpl
templates/ru/edit-config.tmpl
templates/ru/job-move.tmpl
templates/ru/jobs.tmpl
templates/ru/list-available-printers.tmpl
templates/ru/modify-class.tmpl
templates/ru/modify-printer.tmpl
templates/ru/printer-confirm.tmpl
templates/ru/printer.tmpl
templates/ru/samba-export.tmpl
templates/ru/set-printer-options-header.tmpl
templates/ru/users.tmpl
templates/samba-export.tmpl
templates/set-printer-options-header.tmpl
templates/users.tmpl
test/Dependencies
test/Makefile
test/ipp-1.1.test [new file with mode: 0644]
test/ipp-2.0.test [new file with mode: 0644]
test/ipp-2.1.test [new file with mode: 0644]
test/ipptest.c
test/print-job-media-col.test [new file with mode: 0644]
test/str-header.html
vc2005/ipptest.vcproj [new file with mode: 0644]
vcnet/config.h
vcnet/cups.sln
vcnet/ipptest.vcproj [new file with mode: 0644]
vcnet/regex/COPYRIGHT [new file with mode: 0644]
vcnet/regex/Makefile [new file with mode: 0644]
vcnet/regex/README [new file with mode: 0644]
vcnet/regex/WHATSNEW [new file with mode: 0644]
vcnet/regex/cclass.h [new file with mode: 0644]
vcnet/regex/cname.h [new file with mode: 0644]
vcnet/regex/debug.c [new file with mode: 0644]
vcnet/regex/debug.ih [new file with mode: 0644]
vcnet/regex/engine.c [new file with mode: 0644]
vcnet/regex/engine.ih [new file with mode: 0644]
vcnet/regex/main.c [new file with mode: 0644]
vcnet/regex/main.ih [new file with mode: 0644]
vcnet/regex/mkh [new file with mode: 0644]
vcnet/regex/regcomp.c [new file with mode: 0644]
vcnet/regex/regcomp.ih [new file with mode: 0644]
vcnet/regex/regerror.c [new file with mode: 0644]
vcnet/regex/regerror.ih [new file with mode: 0644]
vcnet/regex/regex.3 [new file with mode: 0644]
vcnet/regex/regex.7 [new file with mode: 0644]
vcnet/regex/regex.h [new file with mode: 0644]
vcnet/regex/regex2.h [new file with mode: 0644]
vcnet/regex/regexec.c [new file with mode: 0644]
vcnet/regex/regfree.c [new file with mode: 0644]
vcnet/regex/split.c [new file with mode: 0644]
vcnet/regex/tests [new file with mode: 0644]
vcnet/regex/utils.h [new file with mode: 0644]

index 2cdd32e730049fd0ae3ca1c03703245c7be8f8d6..ba74e6465ce1025febea4e1e6db1b4172833aa40 100644 (file)
@@ -1,13 +1,26 @@
 CHANGES-1.4.txt
 ---------------
 
+CHANGES IN CUPS V1.4.4
+
+       - The scheduler did not update the classes.conf file when deleting a
+         printer belonging to a class (STR #3505)
+       - The lppasswd command did not use localized password prompts
+         (STR #3492)
+       - The socket backend no longer waits for back-channel data on platforms
+         other than Mac OS X (STR #3495)
+       - The scheduler didn't send events when a printer started accepting or
+         rejecting jobs (STR #3480)
+       - The web interface now includes additional CSRF protection (STR #3498)
+
+
 CHANGES IN CUPS V1.4.3
 
        - SECURITY: The scheduler could try responding on a closed client
          connection, leading to a crash (STR #3200)
        - Localization updates (STR #3352, STR #3409, STR #3422, STR #3452,
-         STR #3473)
-       - Documentation update (STR #3451)
+         STR #3473, STR #3502)
+       - Documentation updates (STR #3451, STR #3504)
        - The IPP backend now sets the printer-state-message to "Ready to
          print." at the end of a successful job (STR #3460)
        - The PPD compiler did not correctly add the manufacturer to the output
index b8f215201d6610b9d7d7b002e0d7938808a32ee7..ee9680d740117e580ca96ea6e4df4ee5d6bfc4c5 100644 (file)
@@ -1,8 +1,10 @@
-CHANGES.txt - 2009-11-19
+CHANGES.txt - 2010-02-12
 ------------------------
 
 CHANGES IN CUPS V1.5b1
 
+       - The ipptest tool is now a first-class user program and has several
+         improvements along with new documentation (STR #3484)
        - The cupstestppd tool now warns about non-unique filenames and
          provides a way to ignore all filename warnings.
        - Dropped support for the recoverable: and recovered: message prefixes.
@@ -10,3 +12,5 @@ CHANGES IN CUPS V1.5b1
          permissions disabled.
        - The PPD compiler now checks for overlapping filenames when writing
          PPD files.
+       - The HP-GL/2 filter is no longer included with CUPS (STR #3322)
+       - The SCSI backend is no longer included with CUPS (STR #3500)
index e557871d2124b3da1f105b483500b80828069c86..d173cb7be430d98f5339fb6a9c85c226a32ea14b 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makedefs.in 7900 2008-09-03 13:47:57Z mike $"
 #
-#   Common makefile definitions for the Common UNIX Printing System (CUPS).
+#   Common makefile definitions for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -83,6 +83,7 @@ LIBCUPSDRIVER =       @LIBCUPSDRIVER@
 LIBCUPSIMAGE   =       @LIBCUPSIMAGE@
 LIBCUPSMIME    =       @LIBCUPSMIME@
 LIBCUPSPPDC    =       @LIBCUPSPPDC@
+LIBCUPSSTATIC  =       @LIBCUPSSTATIC@
 LIBJPEG                =       @LIBJPEG@
 LIBLDAP                =       @LIBLDAP@
 LIBMALLOC      =       @LIBMALLOC@
index 9ccc129921f7da6ca68e8164366ffb51323043b8..82c29d66ce315dadc9bd3e4bdf1fafc1c19d5fcd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7961 2008-09-17 19:52:46Z mike $"
 #
-#   Top-level Makefile for the Common UNIX Printing System (CUPS).
+#   Top-level Makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -142,10 +142,12 @@ depend:
 # (at least checker-231 is required for scan-build to work this way)
 #
 
-.PHONY: clang
+.PHONY: clang clang-changes
 clang:
        $(RM) -r clang
        scan-build -V -k -o `pwd`/clang $(MAKE) $(MFLAGS) clean all
+clang-changes:
+       scan-build -V -k -o `pwd`/clang $(MAKE) $(MFLAGS) all
 
 
 #
@@ -282,7 +284,7 @@ docset:     apihelp
 
 
 #
-# Make software distributions using EPM (http://www.easysw.com/epm/)...
+# Make software distributions using EPM (http://www.epmhome.org/)...
 #
 
 EPMFLAGS       =       -v --output-dir dist $(EPMARCH)
index 9051be05c3d90cf1d7ee81413977ddcefa7e3fef..429398ab1fbac40c264384cfc7d06452cc532ed5 100644 (file)
@@ -28,10 +28,6 @@ parallel.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
 parallel.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h
 parallel.o: ../cups/transcode.h ../cups/snmp-private.h ../cups/string.h
 parallel.o: ../config.h
-scsi.o: ../cups/backend.h ../cups/versioning.h ../cups/cups.h ../cups/ipp.h
-scsi.o: ../cups/http.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-scsi.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
-scsi.o: ../cups/string.h ../config.h
 serial.o: backend-private.h ../cups/backend.h ../cups/versioning.h
 serial.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
 serial.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
@@ -57,7 +53,9 @@ test1284.o: ../cups/backend.h ../cups/versioning.h ../cups/sidechannel.h
 test1284.o: ../cups/ppd-private.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 test1284.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
 test1284.o: ../cups/debug.h ../cups/i18n.h ../cups/transcode.h
-test1284.o: ../cups/snmp-private.h
+test1284.o: ../cups/snmp-private.h ../cups/globals.h ../cups/string.h
+test1284.o: ../cups/http-private.h ../cups/md5.h ../cups/ipp-private.h
+test1284.o: ../cups/i18n.h
 testbackend.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
 testbackend.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 testbackend.o: ../cups/array.h ../cups/file.h ../cups/language.h
index 807b4c4e6c11231e6e9f738c07f36937493a179f..6b217462fa7aabeb9818f338f3b2b08bac2e8545 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7924 2008-09-10 17:36:13Z mike $"
 #
-#   Backend makefile for the Common UNIX Printing System (CUPS).
+#   Backend makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
 
 include ../Makedefs
 
+#
+# Object files...
+#
+
 RBACKENDS =    ipp lpd $(DNSSD_BACKEND)
 UBACKENDS =    $(PAP) $(LEGACY_BACKENDS) serial snmp socket usb
 UNITTESTS =    test1284 testbackend testsupplies
 TARGETS =      libbackend.a $(RBACKENDS) $(UBACKENDS)
 LIBOBJS        =       ieee1284.o network.o runloop.o snmp-supplies.o
-OBJS   =       ipp.o lpd.o dnssd.o pap.o parallel.o scsi.o serial.o snmp.o \
+OBJS   =       ipp.o lpd.o dnssd.o pap.o parallel.o serial.o snmp.o \
                socket.o test1284.o testbackend.o testsupplies.o usb.o
 
 
@@ -134,9 +138,9 @@ uninstall:
 # test1284
 #
 
-test1284:      test1284.o ../cups/libcups.a
+test1284:      test1284.o ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o test1284 test1284.o ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o test1284 test1284.o ../cups/$(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
@@ -144,9 +148,9 @@ test1284:   test1284.o ../cups/libcups.a
 # testbackend
 #
 
-testbackend:   testbackend.o ../cups/libcups.a
+testbackend:   testbackend.o ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o testbackend testbackend.o ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o testbackend testbackend.o ../cups/$(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
@@ -154,10 +158,10 @@ testbackend:      testbackend.o ../cups/libcups.a
 # testsupplies
 #
 
-testsupplies:  testsupplies.o libbackend.a ../cups/libcups.a
+testsupplies:  testsupplies.o libbackend.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(LDFLAGS) -o testsupplies testsupplies.o libbackend.a \
-               ../cups/libcups.a $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
                $(COMMONLIBS) $(LIBZ)
 
 
@@ -221,17 +225,6 @@ parallel:  parallel.o ../cups/$(LIBCUPS) libbackend.a
        $(CC) $(LDFLAGS) -o parallel parallel.o libbackend.a $(LIBS)
 
 
-#
-# scsi
-#
-
-scsi:  scsi.o ../cups/$(LIBCUPS)
-       echo Linking $@...
-       $(CC) $(LDFLAGS) -o scsi scsi.o $(LIBS)
-
-scsi.o:        scsi.c scsi-irix.c scsi-linux.c
-
-
 #
 # serial
 #
index 6b2d010f0b893ab4cbcf2152652ab7c95d45363a..434db87399180a2c8f597611d273c3e5e0a8c83e 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "backend-private.h"
+#include <cups/globals.h>
 
 
 /*
@@ -264,7 +265,7 @@ backendGetDeviceID(
     * Get the make, model, and serial numbers...
     */
 
-    num_values = _ppdGet1284Values(device_id, &values);
+    num_values = _cupsGet1284Values(device_id, &values);
 
     if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
       if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
@@ -354,7 +355,7 @@ backendGetMakeModel(
   * Look for the description field...
   */
 
-  num_values = _ppdGet1284Values(device_id, &values);
+  num_values = _cupsGet1284Values(device_id, &values);
 
   if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL)
     mdl = cupsGetOption("MDL", num_values, values);
diff --git a/backend/scsi-irix.c b/backend/scsi-irix.c
deleted file mode 100644 (file)
index f4a6010..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * "$Id: scsi-irix.c 6834 2007-08-22 18:29:25Z mike $"
- *
- *   IRIX SCSI printer support for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007-2009 by Apple Inc.
- *   Copyright 2003-2005 by Easy Software Products, all rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or
- *   without modification, are permitted provided that the
- *   following conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *       copyright notice, this list of conditions and the
- *       following disclaimer.
- *
- *     2. Redistributions in binary form must reproduce the
- *       above copyright notice, this list of conditions and
- *       the following disclaimer in the documentation and/or
- *       other materials provided with the distribution.
- *
- *     3. All advertising materials mentioning features or use
- *       of this software must display the following
- *       acknowledgement:
- *
- *         This product includes software developed by Easy
- *         Software Products.
- *
- *     4. The name of Easy Software Products may not be used to
- *       endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
- *   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- *   BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
- *   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- *   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- *   DAMAGE.
- *
- * Contents:
- *
- *   list_devices() - List the available SCSI printer devices.
- *   print_device() - Print a file to a SCSI device.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include <bstring.h>           /* memcpy() and friends */
-#include <sys/dsreq.h>         /* SCSI interface stuff */
-
-
-/*
- * 'list_devices()' - List the available SCSI printer devices.
- */
-
-void
-list_devices(void)
-{
-  printf("direct scsi \"Unknown\" \"%s\"\n",
-         _cupsLangString(cupsLangDefault(), _("SCSI Printer")));
-}
-
-
-/*
- * 'print_device()' - Print a file to a SCSI device.
- */
-
-int                                    /* O - Print status */
-print_device(const char *resource,     /* I - SCSI device */
-             int        fd,            /* I - File to print */
-            int        copies)         /* I - Number of copies to print */
-{
-  int          scsi_fd;                /* SCSI file descriptor */
-  char         buffer[8192];           /* Data buffer */
-  int          bytes;                  /* Number of bytes */
-  int          try;                    /* Current try */
-  dsreq_t      scsi_req;               /* SCSI request */
-  char         scsi_cmd[6];            /* SCSI command data */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
-  * Make sure we have a valid resource name...
-  */
-
-  if (strncmp(resource, "/dev/scsi/", 10) != 0)
-  {
-    _cupsLangPrintf(stderr, _("ERROR: Bad SCSI device file \"%s\"\n"),
-                    resource);
-    return (CUPS_BACKEND_STOP);
-  }
-
- /*
-  * Open the SCSI device file...
-  */
-
-  fputs("STATE: +connecting-to-device\n", stderr);
-
-  do
-  {
-    if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
-    {
-      if (getenv("CLASS") != NULL)
-      {
-       /*
-        * If the CLASS environment variable is set, the job was submitted
-       * to a class and not to a specific queue.  In this case, we want
-       * to abort immediately so that the job can be requeued on the next
-       * available printer in the class.
-       */
-
-        _cupsLangPuts(stderr,
-                     _("INFO: Unable to contact printer, queuing on next "
-                       "printer in class...\n"));
-
-       /*
-        * Sleep 5 seconds to keep the job from requeuing too rapidly...
-       */
-
-       sleep(5);
-
-        return (1);
-      }
-
-      if (errno != EAGAIN && errno != EBUSY)
-      {
-       _cupsLangPrintf(stderr,
-                       _("ERROR: Unable to open device file \"%s\": %s\n"),
-                       resource, strerror(errno));
-       return (CUPS_BACKEND_FAILED);
-      }
-      else
-      {
-        _cupsLangPuts(stderr,
-                     _("INFO: Printer busy; will retry in 30 seconds...\n"));
-        sleep(30);
-      }
-    }
-  }
-  while (scsi_fd == -1);
-
-  fputs("STATE: -connecting-to-device\n", stderr);
-
- /*
-  * Now that we are "connected" to the port, ignore SIGTERM so that we
-  * can finish out any page data the driver sends (e.g. to eject the
-  * current page...  Only ignore SIGTERM if we are printing data from
-  * stdin (otherwise you can't cancel raw jobs...)
-  */
-
-  if (fd != 0)
-  {
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
-    sigset(SIGTERM, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
-    memset(&action, 0, sizeof(action));
-
-    sigemptyset(&action.sa_mask);
-    action.sa_handler = SIG_IGN;
-    sigaction(SIGTERM, &action, NULL);
-#else
-    signal(SIGTERM, SIG_IGN);
-#endif /* HAVE_SIGSET */
-  }
-
- /*
-  * Copy the print file to the device...
-  */
-
-  while (copies > 0)
-  {
-    if (fd != 0)
-      lseek(fd, 0, SEEK_SET);
-
-    while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
-    {
-      memset(&scsi_req, 0, sizeof(scsi_req));
-
-      scsi_req.ds_flags   = DSRQ_WRITE;
-      scsi_req.ds_time    = 60 * 1000;
-      scsi_req.ds_cmdbuf  = scsi_cmd;
-      scsi_req.ds_cmdlen  = 6;
-      scsi_req.ds_databuf = buffer;
-      scsi_req.ds_datalen = bytes;
-
-      scsi_cmd[0] = 0x0a;      /* Group 0 print command */
-      scsi_cmd[1] = 0x00;
-      scsi_cmd[2] = bytes / 65536;
-      scsi_cmd[3] = bytes / 256;
-      scsi_cmd[4] = bytes;
-      scsi_cmd[5] = 0x00;
-
-      for (try = 0; try < 10; try ++)
-       if (ioctl(scsi_fd, DS_ENTER, &scsi_req) < 0 ||
-            scsi_req.ds_status != 0)
-        {
-         _cupsLangPrintf(stderr,
-                         _("WARNING: SCSI command timed out (%d); "
-                           "retrying...\n"), scsi_req.ds_status);
-          sleep(try + 1);
-       }
-       else
-          break;
-
-      if (try >= 10)
-      {
-       _cupsLangPrintf(stderr, _("ERROR: Unable to send print data (%d)\n"),
-                       scsi_req.ds_status);
-        close(scsi_fd);
-       return (CUPS_BACKEND_FAILED);
-      }
-    }
-
-    copies --;
-  }
-
- /*
-  * Close the device and return...
-  */
-
-  close(fd);
-
-  return (CUPS_BACKEND_OK);
-}
-
-
-/*
- * End of "$Id: scsi-irix.c 6834 2007-08-22 18:29:25Z mike $".
- */
diff --git a/backend/scsi-linux.c b/backend/scsi-linux.c
deleted file mode 100644 (file)
index 934a626..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * "$Id: scsi-linux.c 6834 2007-08-22 18:29:25Z mike $"
- *
- *   Linux SCSI printer support for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007-2009 by Apple Inc.
- *   Copyright 2003-2005 by Easy Software Products, all rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or
- *   without modification, are permitted provided that the
- *   following conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *       copyright notice, this list of conditions and the
- *       following disclaimer.
- *
- *     2. Redistributions in binary form must reproduce the
- *       above copyright notice, this list of conditions and
- *       the following disclaimer in the documentation and/or
- *       other materials provided with the distribution.
- *
- *     3. All advertising materials mentioning features or use
- *       of this software must display the following
- *       acknowledgement:
- *
- *         This product includes software developed by Easy
- *         Software Products.
- *
- *     4. The name of Easy Software Products may not be used to
- *       endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
- *   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- *   BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
- *   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- *   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- *   DAMAGE.
- *
- * Contents:
- *
- *   list_devices() - List the available SCSI printer devices.
- *   print_device() - Print a file to a SCSI device.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include <scsi/sg.h>
-#include <cups/i18n.h>
-
-
-/*
- * We currently only support the Linux 2.4 generic SCSI interface.
- */
-
-#ifndef SG_DXFER_TO_DEV
-/*
- * Dummy functions that do nothing on unsupported platforms...
- */
-void   list_devices(void) {}
-int    print_device(const char *resource, int fd, int copies) { return (1); }
-#else
-
-
-/*
- * 'list_devices()' - List the available SCSI printer devices.
- */
-
-void
-list_devices(void)
-{
-  printf("direct scsi \"Unknown\" \"%s\"\n",
-         _cupsLangString(cupsLangDefault(), _("SCSI Printer")));
-}
-
-
-/*
- * 'print_device()' - Print a file to a SCSI device.
- */
-
-int                                    /* O - Print status */
-print_device(const char *resource,     /* I - SCSI device */
-             int        fd,            /* I - File to print */
-            int        copies)         /* I - Number of copies to print */
-{
-  int          scsi_fd;                /* SCSI file descriptor */
-  char         buffer[8192];           /* Data buffer */
-  int          bytes;                  /* Number of bytes */
-  int          try;                    /* Current try */
-  sg_io_hdr_t  scsi_req;               /* SCSI request */
-  unsigned char        scsi_cmd[6],            /* SCSI command data */
-               scsi_sense[32];         /* SCSI sense data */
-#  if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Actions for POSIX signals */
-#  endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
-  * Make sure we have a valid resource name...
-  */
-
-  if (strncmp(resource, "/dev/sg", 7) != 0)
-  {
-    _cupsLangPrintf(stderr, _("ERROR: Bad SCSI device file \"%s\"\n"),
-                    resource);
-    return (CUPS_BACKEND_STOP);
-  }
-
- /*
-  * Open the SCSI device file...
-  */
-
-  fputs("STATE: +connecting-to-device\n", stderr);
-
-  do
-  {
-    if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
-    {
-      if (getenv("CLASS") != NULL)
-      {
-       /*
-        * If the CLASS environment variable is set, the job was submitted
-       * to a class and not to a specific queue.  In this case, we want
-       * to abort immediately so that the job can be requeued on the next
-       * available printer in the class.
-       */
-
-        _cupsLangPuts(stderr,
-                     _("INFO: Unable to contact printer, queuing on next "
-                       "printer in class...\n"));
-
-       /*
-        * Sleep 5 seconds to keep the job from requeuing too rapidly...
-       */
-
-       sleep(5);
-
-        return (CUPS_BACKEND_FAILED);
-      }
-
-      if (errno != EAGAIN && errno != EBUSY)
-      {
-       _cupsLangPrintf(stderr,
-                       _("ERROR: Unable to open device file \"%s\": %s\n"),
-                       resource, strerror(errno));
-       return (CUPS_BACKEND_FAILED);
-      }
-      else
-      {
-        _cupsLangPuts(stderr,
-                     _("INFO: Printer busy; will retry in 30 seconds...\n"));
-        sleep(30);
-      }
-    }
-  }
-  while (scsi_fd == -1);
-
-  fputs("STATE: -connecting-to-device\n", stderr);
-
- /*
-  * Now that we are "connected" to the port, ignore SIGTERM so that we
-  * can finish out any page data the driver sends (e.g. to eject the
-  * current page...  Only ignore SIGTERM if we are printing data from
-  * stdin (otherwise you can't cancel raw jobs...)
-  */
-
-  if (fd != 0)
-  {
-#  ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
-    sigset(SIGTERM, SIG_IGN);
-#  elif defined(HAVE_SIGACTION)
-    memset(&action, 0, sizeof(action));
-
-    sigemptyset(&action.sa_mask);
-    action.sa_handler = SIG_IGN;
-    sigaction(SIGTERM, &action, NULL);
-#  else
-    signal(SIGTERM, SIG_IGN);
-#  endif /* HAVE_SIGSET */
-  }
-
- /*
-  * Copy the print file to the device...
-  */
-
-  while (copies > 0)
-  {
-    if (fd != 0)
-      lseek(fd, 0, SEEK_SET);
-
-    while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
-    {
-      memset(&scsi_req, 0, sizeof(scsi_req));
-
-      scsi_req.interface_id    = 'S';
-      scsi_req.dxfer_direction = SG_DXFER_TO_DEV;
-      scsi_req.cmd_len         = 6;
-      scsi_req.mx_sb_len       = sizeof(scsi_sense);
-      scsi_req.iovec_count     = 0;
-      scsi_req.dxfer_len       = bytes;
-      scsi_req.dxferp          = buffer;
-      scsi_req.cmdp            = scsi_cmd;
-      scsi_req.sbp             = scsi_sense;
-      scsi_req.timeout         = 60 * 1000;
-      
-      scsi_cmd[0] = 0x0a;      /* Group 0 print command */
-      scsi_cmd[1] = 0x00;
-      scsi_cmd[2] = bytes / 65536;
-      scsi_cmd[3] = bytes / 256;
-      scsi_cmd[4] = bytes;
-      scsi_cmd[5] = 0x00;
-
-      for (try = 0; try < 10; try ++)
-       if (ioctl(scsi_fd, SG_IO, &scsi_req) < 0 ||
-            scsi_req.status != 0)
-        {
-         _cupsLangPrintf(stderr,
-                         _("WARNING: SCSI command timed out (%d); "
-                           "retrying...\n"), scsi_req.status);
-          sleep(try + 1);
-       }
-       else
-          break;
-
-      if (try >= 10)
-      {
-       _cupsLangPrintf(stderr, _("ERROR: Unable to send print data (%d)\n"),
-                       scsi_req.status);
-        close(scsi_fd);
-       return (CUPS_BACKEND_FAILED);
-      }
-    }
-
-    copies --;
-  }
-
- /*
-  * Close the device and return...
-  */
-
-  close(fd);
-
-  return (CUPS_BACKEND_OK);
-}
-#endif /* !SG_DXFER_TO_DEV */
-
-
-/*
- * End of "$Id: scsi-linux.c 6834 2007-08-22 18:29:25Z mike $".
- */
diff --git a/backend/scsi.c b/backend/scsi.c
deleted file mode 100644 (file)
index 7040d4b..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * "$Id: scsi.c 7193 2008-01-07 23:01:40Z mike $"
- *
- *   SCSI printer backend for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 2003-2006 by Easy Software Products, all rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or
- *   without modification, are permitted provided that the
- *   following conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *       copyright notice, this list of conditions and the
- *       following disclaimer.
- *
- *     2. Redistributions in binary form must reproduce the
- *       above copyright notice, this list of conditions and
- *       the following disclaimer in the documentation and/or
- *       other materials provided with the distribution.
- *
- *     3. All advertising materials mentioning features or use
- *       of this software must display the following
- *       acknowledgement:
- *
- *         This product includes software developed by Easy
- *         Software Products.
- *
- *     4. The name of Easy Software Products may not be used to
- *       endorse or promote products derived from this software
- *       without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
- *   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- *   BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
- *   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- *   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- *   DAMAGE.
- *
- * Contents:
- *
- *   main() - Send a file to the specified SCSI printer.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include <cups/backend.h>
-#include <cups/cups.h>
-#include <cups/i18n.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <cups/string.h>
-#include <cups/i18n.h>
-#include <signal.h>
-
-#ifdef WIN32
-#  include <io.h>
-#else
-#  include <unistd.h>
-#  include <fcntl.h>
-#  ifdef HAVE_SYS_IOCTL_H
-#    include <sys/ioctl.h>
-#  endif /* HAVE_SYS_IOCTL_H */
-#endif /* WIN32 */
-
-
-/*
- * Local functions...
- */
-
-void   list_devices(void);
-int    print_device(const char *resource, int fd, int copies);
-
-
-#if defined(__linux__) && defined(HAVE_SCSI_SG_H)
-#  include "scsi-linux.c"
-#elif defined(__sgi)
-#  include "scsi-irix.c"
-#else
-/*
- * Dummy functions that do nothing on unsupported platforms...
- */
-void   list_devices(void) {}
-int    print_device(const char *resource, int fd, int copies) { return (CUPS_BACKEND_FAILED); }
-#endif /* __linux && HAVE_SCSI_SG_H */
-
-
-/*
- * 'main()' - Send a file to the specified SCSI printer.
- *
- * Usage:
- *
- *    printer-uri job-id user title copies options [file]
- */
-
-int                    /* O - Exit status */
-main(int  argc,                /* I - Number of command-line arguments (6 or 7) */
-     char *argv[])     /* I - Command-line arguments */
-{
-  char         method[255],    /* Method in URI */
-               hostname[1024], /* Hostname */
-               username[255],  /* Username info (not used) */
-               resource[1024], /* Resource info (device and options) */
-               *options;       /* Pointer to options */
-  int          port;           /* Port number (not used) */
-  int          fp;             /* Print file */
-  int          copies;         /* Number of copies to print */
-  int          status;         /* Exit status */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;     /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
-  * Make sure status messages are not buffered...
-  */
-
-  setbuf(stderr, NULL);
-
- /*
-  * Ignore SIGPIPE signals...
-  */
-
-#ifdef HAVE_SIGSET
-  sigset(SIGPIPE, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
-  memset(&action, 0, sizeof(action));
-  action.sa_handler = SIG_IGN;
-  sigaction(SIGPIPE, &action, NULL);
-#else
-  signal(SIGPIPE, SIG_IGN);
-#endif /* HAVE_SIGSET */
-
- /*
-  * Check command-line...
-  */
-
-  if (argc == 1)
-  {
-    list_devices();
-    return (CUPS_BACKEND_OK);
-  }
-  else if (argc < 6 || argc > 7)
-  {
-    _cupsLangPrintf(stderr,
-                    _("Usage: %s job-id user title copies options [file]\n"),
-                   argv[0]);
-    return (CUPS_BACKEND_FAILED);
-  }
-
- /*
-  * If we have 7 arguments, print the file named on the command-line.
-  * Otherwise, send stdin instead...
-  */
-
-  if (argc == 6)
-  {
-    fp     = 0;
-    copies = 1;
-  }
-  else
-  {
-   /*
-    * Try to open the print file...
-    */
-
-    if ((fp = open(argv[6], O_RDONLY)) < 0)
-    {
-      _cupsLangPrintf(stderr,
-                      _("ERROR: Unable to open print file \"%s\": %s\n"),
-                     argv[6], strerror(errno));
-      return (CUPS_BACKEND_FAILED);
-    }
-
-    copies = atoi(argv[4]);
-  }
-
- /*
-  * Extract the device name and options from the URI...
-  */
-
-  httpSeparateURI(HTTP_URI_CODING_ALL, cupsBackendDeviceURI(argv),
-                  method, sizeof(method), username, sizeof(username),
-                 hostname, sizeof(hostname), &port,
-                 resource, sizeof(resource));
-
- /*
-  * See if there are any options...
-  */
-
-  if ((options = strchr(resource, '?')) != NULL)
-  {
-   /*
-    * Yup, terminate the device name string and move to the first
-    * character of the options...
-    */
-
-    *options++ = '\0';
-  }
-
- /*
-  * Finally, send the print file...
-  */
-
-  status = print_device(resource, fp, copies);
-
- /*
-  * Close input file and return...
-  */
-
-  if (fp != 0)
-    close(fp);
-
-  return (status);
-}
-
-
-/*
- * End of "$Id: scsi.c 7193 2008-01-07 23:01:40Z mike $".
- */
index 46d7f5edad389390fb6a982bf67f1f40b86f69c2..53f8dc0b57bd219cdeb97f3f25db43e4afc94c8f 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   AppSocket backend for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -72,9 +72,11 @@ main(int  argc,                              /* I - Number of command-line arguments (6 or 7) */
                sep;                    /* Option separator */
   int          print_fd;               /* Print file */
   int          copies;                 /* Number of copies to print */
-  time_t       start_time,             /* Time of first connect */
-               current_time,           /* Current time */
+  time_t       start_time;             /* Time of first connect */
+#ifdef __APPLE__
+  time_t       current_time,           /* Current time */
                wait_time;              /* Time to wait before shutting down socket */
+#endif /* __APPLE__ */
   int          contimeout;             /* Connection timeout */
   int          waiteof;                /* Wait for end-of-file? */
   int          port;                   /* Port number */
@@ -388,6 +390,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
                      CUPS_LLCAST tbytes);
   }
 
+#ifdef __APPLE__
  /*
   * Wait up to 5 seconds to get any pending back-channel data...
   */
@@ -396,6 +399,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   while (wait_time >= time(&current_time))
     if (wait_bc(device_fd, wait_time - current_time) <= 0)
       break;
+#endif /* __APPLE__ */
 
   if (waiteof)
   {
index 2efece7efba21036e3841806ff69ed1fa6301d18..e46e6ea9de1b672797fb4211a2e67122b91461e2 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <usb.h>
 #include <poll.h>
+#include <cups/globals.h>
 
 
 /*
@@ -514,7 +515,7 @@ make_device_uri(
   * Get the make, model, and serial numbers...
   */
 
-  num_values = _ppdGet1284Values(device_id, &values);
+  num_values = _cupsGet1284Values(device_id, &values);
 
   if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
     if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
index f018cd0a0a9536e7b6f9b9311ac879cc4ace4894..83c8d7e09a21b8683740143cdb0b25297a438ead 100644 (file)
@@ -25,6 +25,7 @@ var.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 var.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 var.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h
 var.o: ../cups/i18n.h ../cups/transcode.h ../cups/string.h ../config.h
+var.o: ../cups/http.h ../cups/md5.h
 admin.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 admin.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 admin.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h
index 7b1abb6f9943918b21f5642fdf1d1dac82373f18..f967f46aa071119a7a84cc05f4bac341e26725d6 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7871 2008-08-27 21:12:43Z mike $"
 #
-#   CGI makefile for the Common UNIX Printing System (CUPS).
+#   CGI makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -118,7 +118,7 @@ install-exec:
        done
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               for file in $(TARGETS); do \
+               for file in $(CGIS); do \
                        cp $$file $(SYMROOT); \
                done \
        fi
@@ -307,10 +307,10 @@ jobs.cgi: jobs.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI)
 # makedocset
 #
 
-makedocset:    makedocset.o ../Makedefs libcupscgi.a ../cups/libcups.a
+makedocset:    makedocset.o ../Makedefs libcupscgi.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ makedocset.o libcupscgi.a \
-               ../cups/libcups.a $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
                $(LIBZ) $(LIBGSSAPI)
 
 
@@ -327,10 +327,10 @@ printers.cgi:     printers.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSCGI)
 # testcgi
 #
 
-testcgi:       testcgi.o ../Makedefs libcupscgi.a ../cups/libcups.a
+testcgi:       testcgi.o ../Makedefs libcupscgi.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testcgi.o libcupscgi.a \
-               ../cups/libcups.a $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
                $(LIBZ) $(LIBGSSAPI)
        echo Testing CGI API...
        ./testcgi
@@ -340,10 +340,10 @@ testcgi:  testcgi.o ../Makedefs libcupscgi.a ../cups/libcups.a
 # testhi
 #
 
-testhi:        testhi.o ../Makedefs libcupscgi.a ../cups/libcups.a
+testhi:        testhi.o ../Makedefs libcupscgi.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testhi.o libcupscgi.a \
-               ../cups/libcups.a $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
                $(LIBZ) $(LIBGSSAPI)
        echo Testing help index API...
        ./testhi
@@ -353,9 +353,9 @@ testhi:     testhi.o ../Makedefs libcupscgi.a ../cups/libcups.a
 # testtemplate
 #
 
-testtemplate:  testtemplate.o ../Makedefs libcupscgi.a ../cups/libcups.a
+testtemplate:  testtemplate.o ../Makedefs libcupscgi.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ testtemplate.o libcupscgi.a ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o $@ testtemplate.o libcupscgi.a ../cups/$(LIBCUPSSTATIC) \
                $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) $(LIBZ) $(LIBGSSAPI)
 
 
@@ -363,10 +363,10 @@ testtemplate:     testtemplate.o ../Makedefs libcupscgi.a ../cups/libcups.a
 # websearch
 #
 
-websearch:     websearch.o ../Makedefs libcupscgi.a ../cups/libcups.a
+websearch:     websearch.o ../Makedefs libcupscgi.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ websearch.o libcupscgi.a \
-               ../cups/libcups.a $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(SSLLIBS) $(DNSSDLIBS) \
                $(LIBZ) $(LIBGSSAPI)
 
 
index ccf10de5782d82f8709471819ee4898ba7a3c5b9..5617be2247bb0f268ef117014553fc1b2e46d901 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Administration CGI for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
 #include <limits.h>
 
 
+/*
+ * Local globals...
+ */
+
+static int     current_device = 0;     /* Current device shown */
+
+
 /*
  * Local functions...
  */
@@ -57,7 +64,7 @@ static void   choose_device_cb(const char *device_class,
                                  const char *device_make_and_model,
                                  const char *device_uri,
                                  const char *device_location,
-                                int *current_device);
+                                const char *title);
 static void    do_add_rss_subscription(http_t *http);
 static void    do_am_class(http_t *http, int modify);
 static void    do_am_printer(http_t *http, int modify);
@@ -282,20 +289,35 @@ choose_device_cb(
     const char *device_make_and_model, /* I - Make and model */
     const char *device_uri,            /* I - Device URI */
     const char *device_location,       /* I - Location */
-    int        *current_device)                /* I - Current device index */
+    const char *title)                 /* I - Page title */
 {
+ /*
+  * For modern browsers, start a multi-part page so we can show that something
+  * is happening.  Non-modern browsers just get everything at the end...
+  */
+
+  if (current_device == 0 && cgiSupportsMultipart())
+  {
+    cgiStartMultipart();
+    cgiStartHTML(title);
+    cgiCopyTemplateLang("choose-device.tmpl");
+    cgiEndHTML();
+    fflush(stdout);
+  }
+
+
  /*
   * Add the device to the array...
   */
 
-  cgiSetArray("device_class", *current_device, device_class);
-  cgiSetArray("device_id", *current_device, device_id);
-  cgiSetArray("device_info", *current_device, device_info);
-  cgiSetArray("device_make_and_model", *current_device, device_make_and_model);
-  cgiSetArray("device_uri", *current_device, device_uri);
-  cgiSetArray("device_location", *current_device, device_location);
+  cgiSetArray("device_class", current_device, device_class);
+  cgiSetArray("device_id", current_device, device_id);
+  cgiSetArray("device_info", current_device, device_info);
+  cgiSetArray("device_make_and_model", current_device, device_make_and_model);
+  cgiSetArray("device_uri", current_device, device_uri);
+  cgiSetArray("device_location", current_device, device_location);
 
-  (*current_device) ++;
+  current_device ++;
 }
 
 
@@ -816,7 +838,6 @@ do_am_printer(http_t *http,         /* I - HTTP connection */
   const char   *name,                  /* Pointer to class name */
                *ptr;                   /* Pointer to CGI variable */
   const char   *title;                 /* Title of page */
-  int          current_device;         /* Index of current device */
   static int   baudrates[] =           /* Baud rates */
                {
                  1200,
@@ -977,20 +998,6 @@ do_am_printer(http_t *http,                /* I - HTTP connection */
       cgiSetVariable("CURRENT_DEVICE_SCHEME", uri);
     }
 
-   /*
-    * For modern browsers, start a multi-part page so we can show that something
-    * is happening.  Non-modern browsers just get everything at the end...
-    */
-
-    if (cgiSupportsMultipart())
-    {
-      cgiStartMultipart();
-      cgiStartHTML(title);
-      cgiCopyTemplateLang("choose-device.tmpl");
-      cgiEndHTML();
-      fflush(stdout);
-    }
-
    /*
     * Scan for devices for up to 30 seconds...
     */
@@ -1000,7 +1007,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
     current_device = 0;
     if (cupsGetDevices(http, 30, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE,
                        (cups_device_cb_t)choose_device_cb,
-                      &current_device) == IPP_OK)
+                      (void *)title) == IPP_OK)
     {
       fputs("DEBUG: Got device list!\n", stderr);
 
index 52368ee3512a16ca44678caf74fe779d0334f56c..bceb5f519c220d8cde354727e9b9a28dc87cc700 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: cgi.h 6649 2007-07-11 21:46:42Z mike $"
  *
- *   CGI support library definitions.
+ *   CGI support library definitions for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -69,11 +69,12 @@ extern void         cgiCopyTemplateLang(const char *tmpl);
 extern int             cgiDoSearch(void *search, const char *text);
 extern void            cgiEndHTML(void);
 extern void            cgiEndMultipart(void);
-extern char            *cgiFormEncode(char *dst, const char *src, size_t dstsize);
+extern char            *cgiFormEncode(char *dst, const char *src,
+                                      size_t dstsize);
 extern void            cgiFreeSearch(void *search);
 extern const char      *cgiGetArray(const char *name, int element);
 extern void            cgiGetAttributes(ipp_t *request, const char *tmpl);
-extern char            *cgiGetCookie(const char *name, char *buf, int buflen);
+extern const char      *cgiGetCookie(const char *name);
 extern const cgi_file_t        *cgiGetFile(void);
 extern cups_array_t    *cgiGetIPPObjects(ipp_t *response, void *search);
 extern int             cgiGetSize(const char *name);
index 1997cdb1069b9f9b5059cea8427334881e7e189d..3a26229d79be045777d2b449b67687cc5a815e2f 100644 (file)
@@ -10,6 +10,7 @@ _cgiFormEncode
 _cgiFreeSearch
 _cgiGetArray
 _cgiGetAttributes
+_cgiGetCookie
 _cgiGetFile
 _cgiGetIPPObjects
 _cgiGetSize
@@ -24,6 +25,7 @@ _cgiRewriteURL
 _cgiSetArray
 _cgiSetIPPObjectVars
 _cgiSetIPPVars
+_cgiSetCookie
 _cgiSetServerVersion
 _cgiSetSize
 _cgiSetVariable
index 6e9cc5ec6827a81df5fe5c80f3a426cd46dd90d3..8ec653878740158edcdca8b4819f7cda1b83ec84 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   CGI template function.
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -369,6 +369,20 @@ cgi_copy(FILE *out,                        /* I - Output file */
 
         continue;
       }
+      else if (name[0] == '$')
+      {
+       /*
+        * Insert cookie value or nothing if not defined.
+       */
+
+        if ((value = cgiGetCookie(name + 1)) != NULL)
+         outptr = value;
+       else
+       {
+         outval[0] = '\0';
+         outptr    = outval;
+       }
+      }
       else
       {
        /*
@@ -437,7 +451,14 @@ cgi_copy(FILE *out,                        /* I - Output file */
         * Test for existance...
        */
 
-        result     = cgiGetArray(name, element) != NULL && outptr[0];
+        if (name[0] == '?')
+         result = cgiGetArray(name + 1, element) != NULL;
+       else if (name[0] == '#')
+         result = cgiGetVariable(name + 1) != NULL;
+        else
+          result = cgiGetArray(name, element) != NULL;
+
+       result     = result && outptr[0];
        compare[0] = '\0';
       }
       else
index 1467bd878d4f5fd0b0089f53d1c4cac15d128301..d376d100937da566058e6c4ec8e14d5b82f74e43 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: var.c 7460 2008-04-16 02:19:54Z mike $"
  *
- *   CGI form variable and array functions.
+ *   CGI form variable and array functions for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  *
  * Contents:
  *
- *   cgiCheckVariables()        - Check for the presence of "required" variables.
+ *   cgiCheckVariables()        - Check for the presence of "required"
+ *                                variables.
  *   cgiClearVariables()        - Clear all form variables.
- *   cgiGetArray()              - Get an element from a form array...
- *   cgiGetFile()               - Get the file (if any) that was submitted in the form.
+ *   cgiGetArray()              - Get an element from a form array.
+ *   cgiGetCookie()             - Get a cookie value.
+ *   cgiGetFile()               - Get the file (if any) that was submitted in
+ *                                the form.
  *   cgiGetSize()               - Get the size of a form array value.
- *   cgiGetVariable()           - Get a CGI variable from the database...
- *   cgiInitialize()            - Initialize the CGI variable "database"...
+ *   cgiGetVariable()           - Get a CGI variable from the database.
+ *   cgiInitialize()            - Initialize the CGI variable "database".
  *   cgiIsPOST()                - Determine whether this page was POSTed.
  *   cgiSetArray()              - Set array element N to the specified string.
+ *   cgiSetCookie()             - Set a cookie value.
  *   cgiSetSize()               - Set the array size.
- *   cgiSetVariable()           - Set a CGI variable in the database...
+ *   cgiSetVariable()           - Set a CGI variable in the database.
  *   cgi_add_variable()         - Add a form variable.
  *   cgi_compare_variables()    - Compare two variables.
- *   cgi_find_variable()        - Find a variable...
- *   cgi_initialize_get()       - Initialize form variables using the GET method.
- *   cgi_initialize_multipart() - Initialize variables and file using the POST method.
+ *   cgi_find_variable()        - Find a variable.
+ *   cgi_initialize_cookies()   - Initialize cookies.
+ *   cgi_initialize_get()       - Initialize form variables using the GET
+ *                                method.
+ *   cgi_initialize_multipart() - Initialize variables and file using the POST
+ *                                method.
  *   cgi_initialize_post()      - Initialize variables using the POST method.
  *   cgi_initialize_string()    - Initialize form variables from a string.
- *   cgi_passwd()               - Catch authentication requests and notify the server.
+ *   cgi_passwd()               - Catch authentication requests and notify the
+ *                                server.
+ *   cgi_set_sid()              - Set the CUPS session ID.
  *   cgi_sort_variables()       - Sort all form variables for faster lookup.
  *   cgi_unlink_file()          - Remove the uploaded form.
  */
 /*#define DEBUG*/
 #include "cgi-private.h"
 #include <errno.h>
+#include <cups/http.h>
+#include <cups/md5.h>
+
+
+/*
+ * Session ID name
+ */
+
+#define CUPS_SID       "org.cups.sid"
 
 
 /*
@@ -59,6 +77,8 @@ typedef struct                                /**** Form variable structure ****/
  * Local globals...
  */
 
+static int             num_cookies = 0;/* Number of cookies */
+static cups_option_t   *cookies = NULL;/* Cookies */
 static int             form_count = 0, /* Form variable count */
                        form_alloc = 0; /* Number of variables allocated */
 static _cgi_var_t      *form_vars = NULL;
@@ -76,11 +96,13 @@ static void         cgi_add_variable(const char *name, int element,
 static int             cgi_compare_variables(const _cgi_var_t *v1,
                                              const _cgi_var_t *v2);
 static _cgi_var_t      *cgi_find_variable(const char *name);
+static void            cgi_initialize_cookies(void);
 static int             cgi_initialize_get(void);
 static int             cgi_initialize_multipart(const char *boundary);
 static int             cgi_initialize_post(void);
 static int             cgi_initialize_string(const char *data);
 static const char      *cgi_passwd(const char *prompt);
+static const char      *cgi_set_sid(void);
 static void            cgi_sort_variables(void);
 static void            cgi_unlink_file(void);
 
@@ -161,7 +183,7 @@ cgiClearVariables(void)
 
 
 /*
- * 'cgiGetArray()' - Get an element from a form array...
+ * 'cgiGetArray()' - Get an element from a form array.
  */
 
 const char *                           /* O - Element value or NULL */
@@ -181,6 +203,17 @@ cgiGetArray(const char *name,              /* I - Name of array variable */
 }
 
 
+/*
+ * 'cgiGetCookie()' - Get a cookie value.
+ */
+
+const char *                           /* O - Value or NULL */
+cgiGetCookie(const char *name)         /* I - Name of cookie */
+{
+  return (cupsGetOption(name, num_cookies, cookies));
+}
+
+
 /*
  * 'cgiGetFile()' - Get the file (if any) that was submitted in the form.
  */
@@ -210,10 +243,10 @@ cgiGetSize(const char *name)              /* I - Name of variable */
 
 
 /*
- * 'cgiGetVariable()' - Get a CGI variable from the database...
+ * 'cgiGetVariable()' - Get a CGI variable from the database.
  *
  * Returns NULL if the variable doesn't exist.  If the variable is an
- * array of values, returns the last element...
+ * array of values, returns the last element.
  */
 
 const char *                           /* O - Value of variable */
@@ -237,14 +270,16 @@ cgiGetVariable(const char *name)  /* I - Name of variable */
 
 
 /*
- * 'cgiInitialize()' - Initialize the CGI variable "database"...
+ * 'cgiInitialize()' - Initialize the CGI variable "database".
  */
 
 int                                    /* O - Non-zero if there was form data */
 cgiInitialize(void)
 {
-  const char   *method;                /* Form posting method */
-  const char   *content_type;          /* Content-Type of post data */
+  const char   *method,                /* Form posting method */
+               *content_type,          /* Content-Type of post data */
+               *cups_sid_cookie,       /* SID cookie */
+               *cups_sid_form;         /* SID form variable */
 
 
  /*
@@ -267,6 +302,20 @@ cgiInitialize(void)
   setbuf(stdout, NULL);
 #endif /* DEBUG */
 
+ /*
+  * Get cookies...
+  */
+
+  cgi_initialize_cookies();
+
+  if ((cups_sid_cookie = cgiGetCookie(CUPS_SID)) == NULL)
+  {
+    fputs("DEBUG: " CUPS_SID " cookie not found, initializing!\n", stderr);
+    cups_sid_cookie = cgi_set_sid();
+  }
+
+  fprintf(stderr, "DEBUG: " CUPS_SID " cookie is \"%s\"\n", cups_sid_cookie);
+
  /*
   * Get the request method (GET or POST)...
   */
@@ -290,9 +339,27 @@ cgiInitialize(void)
       boundary += 9;
 
     if (content_type && !strncmp(content_type, "multipart/form-data; ", 21))
-      return (cgi_initialize_multipart(boundary));
+    {
+      if (!cgi_initialize_multipart(boundary))
+        return (0);
+    }
+    else if (!cgi_initialize_post())
+      return (0);
+
+    if ((cups_sid_form = cgiGetVariable(CUPS_SID)) == NULL ||
+       strcmp(cups_sid_cookie, cups_sid_form))
+    {
+      if (cups_sid_form)
+       fprintf(stderr, "DEBUG: " CUPS_SID " form variable is \"%s\"\n",
+               cups_sid_form);
+      else
+       fputs("DEBUG: " CUPS_SID " form variable is not present.\n", stderr);
+
+      cgiClearVariables();
+      return (0);
+    }
     else
-      return (cgi_initialize_post());
+      return (1);
   }
   else
     return (0);
@@ -370,6 +437,38 @@ cgiSetArray(const char *name,              /* I - Name of variable */
 }
 
 
+/*
+ * 'cgiSetCookie()' - Set a cookie value.
+ */
+
+void
+cgiSetCookie(const char *name,         /* I - Name */
+             const char *value,                /* I - Value */
+             const char *path,         /* I - Path (typically "/") */
+            const char *domain,        /* I - Domain name */
+            time_t     expires,        /* I - Expiration date (0 for session) */
+            int        secure)         /* I - Require SSL */
+{
+  num_cookies = cupsAddOption(name, value, num_cookies, &cookies);
+
+  printf("Set-Cookie: %s=%s;", name, value);
+  if (path)
+    printf("; path=%s", path);
+  if (domain)
+    printf("; domain=%s", domain);
+  if (expires)
+  {
+    char       date[256];              /* Date string */
+
+    printf("; expires=%s", httpGetDateString2(expires, date, sizeof(date)));
+  }
+  if (secure)
+    puts("; secure;");
+  else
+    puts(";");
+}
+
+
 /*
  * 'cgiSetSize()' - Set the array size.
  */
@@ -418,7 +517,7 @@ cgiSetSize(const char *name,                /* I - Name of variable */
 
 
 /*
- * 'cgiSetVariable()' - Set a CGI variable in the database...
+ * 'cgiSetVariable()' - Set a CGI variable in the database.
  *
  * If the variable is an array, this truncates the array to a single element.
  */
@@ -514,7 +613,7 @@ cgi_compare_variables(
 
 
 /*
- * 'cgi_find_variable()' - Find a variable...
+ * 'cgi_find_variable()' - Find a variable.
  */
 
 static _cgi_var_t *                    /* O - Variable pointer or NULL */
@@ -533,6 +632,91 @@ cgi_find_variable(const char *name)        /* I - Name of variable */
 }
 
 
+/*
+ * 'cgi_initialize_cookies()' - Initialize cookies.
+ */
+
+static void
+cgi_initialize_cookies(void)
+{
+  const char   *cookie;                /* HTTP_COOKIE environment variable */
+  char         name[128],              /* Name string */
+               value[512],             /* Value string */
+               *ptr;                   /* Pointer into name/value */
+
+
+  if ((cookie = getenv("HTTP_COOKIE")) == NULL)
+    return;
+
+  while (*cookie)
+  {
+   /*
+    * Skip leading whitespace...
+    */
+
+    while (isspace(*cookie & 255))
+      cookie ++;
+    if (!*cookie)
+      break;
+
+   /*
+    * Copy the name...
+    */
+
+    for (ptr = name; *cookie && *cookie != '=';)
+      if (ptr < (name + sizeof(name) - 1))
+        *ptr++ = *cookie++;
+      else
+        break;
+
+    if (*cookie != '=')
+      break;
+
+    *ptr = '\0';
+    cookie ++;
+
+   /*
+    * Then the value...
+    */
+
+    if (*cookie == '\"')
+    {
+      for (cookie ++, ptr = value; *cookie && *cookie != '\"';)
+        if (ptr < (value + sizeof(value) - 1))
+         *ptr++ = *cookie++;
+       else
+         break;
+
+      if (*cookie == '\"')
+        cookie ++;
+    }
+    else
+    {
+      for (ptr = value; *cookie && *cookie != ';';)
+        if (ptr < (value + sizeof(value) - 1))
+         *ptr++ = *cookie++;
+       else
+         break;
+    }
+
+    if (*cookie == ';')
+      cookie ++;
+    else if (*cookie)
+      break;
+
+    *ptr = '\0';
+
+   /*
+    * Then add the cookie to an array as long as the name doesn't start with
+    * "$"...
+    */
+
+    if (name[0] != '$')
+      num_cookies = cupsAddOption(name, value, num_cookies, &cookies);
+  }
+}
+
+
 /*
  * 'cgi_initialize_get()' - Initialize form variables using the GET method.
  */
@@ -562,7 +746,8 @@ cgi_initialize_get(void)
 
 
 /*
- * 'cgi_initialize_multipart()' - Initialize variables and file using the POST method.
+ * 'cgi_initialize_multipart()' - Initialize variables and file using the POST
+ *                                method.
  *
  * TODO: Update to support files > 2GB.
  */
@@ -874,7 +1059,7 @@ cgi_initialize_string(const char *data)    /* I - Form data string */
   char *s,                             /* Pointer to current form string */
        ch,                             /* Temporary character */
        name[255],                      /* Name of form variable */
-       value[65536];                   /* Variable value... */
+       value[65536];                   /* Variable value */
 
 
  /*
@@ -1014,6 +1199,46 @@ cgi_passwd(const char *prompt)           /* I - Prompt (not used) */
 }
 
 
+/*
+ * 'cgi_set_sid()' - Set the CUPS session ID.
+ */
+
+static const char *                    /* O - New session ID */
+cgi_set_sid(void)
+{
+  char                 buffer[512],    /* SID data */
+                       sid[33];        /* SID string */
+  _cups_md5_state_t    md5;            /* MD5 state */
+  unsigned char                sum[16];        /* MD5 sum */
+  const char           *remote_addr,   /* REMOTE_ADDR */
+                       *server_name,   /* SERVER_NAME */
+                       *server_port;   /* SERVER_PORT */
+
+
+  if ((remote_addr = getenv("REMOTE_ADDR")) == NULL)
+    remote_addr = "REMOTE_ADDR";
+  if ((server_name = getenv("SERVER_NAME")) == NULL)
+    server_name = "SERVER_NAME";
+  if ((server_port = getenv("SERVER_PORT")) == NULL)
+    server_port = "SERVER_PORT";
+
+  CUPS_SRAND(time(NULL));
+  snprintf(buffer, sizeof(buffer), "%s:%s:%s:%02X%02X%02X%02X%02X%02X%02X%02X",
+           remote_addr, server_name, server_port,
+          (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
+          (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
+          (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
+          (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255);
+  _cupsMD5Init(&md5);
+  _cupsMD5Append(&md5, (unsigned char *)buffer, (int)strlen(buffer));
+  _cupsMD5Finish(&md5, sum);
+  
+  cgiSetCookie(CUPS_SID, httpMD5String(sum, sid), "/", server_name, 0, 0);
+
+  return (cupsGetOption(CUPS_SID, num_cookies, cookies));
+}
+
+
 /*
  * 'cgi_sort_variables()' - Sort all form variables for faster lookup.
  */
index a141b5c097ea6879a8f96ca9595d40916242433a..9e6796ad4888a5564469a13fcf75040f6491fa83 100644 (file)
@@ -7,7 +7,7 @@
 #
 #   MIME converts file for the Common UNIX Printing System (CUPS).
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -40,7 +40,6 @@
 
 application/pdf                        application/vnd.cups-postscript 66      pdftops
 application/postscript         application/vnd.cups-postscript 66      pstops
-application/vnd.hp-HPGL                application/postscript          66      hpgltops
 application/x-cshell           application/postscript          33      texttops
 application/x-csource          application/postscript          33      texttops
 application/x-perl             application/postscript          33      texttops
index 8ef1c06a9e21fa9af365dd6bd05257517b151f84..dd28daaf603068b03e588f130b6344b45f4029db 100644 (file)
@@ -7,7 +7,7 @@
 #   VERSIONS OF CUPS.  Instead, create a "local.types" file that
 #   reflects your local configuration changes.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -79,14 +79,6 @@ application/postscript               ai eps ps string(0,%!) string(0,<04>%!) \
                                 contains(0,4096,"LANGUAGE = POSTSCRIPT") \
                                 (contains(0,4096,<0a>%!) + \
                                  !contains(0,4096,"ENTER LANGUAGE")))
-application/vnd.hp-HPGL                hpgl \
-                               string(0,<1B>E<1B>%0B) \
-                               string(0,<1B>%-1B) string(0,<201B>)\
-                               string(0,BP;) string(0,IN;) string(0,DF;) \
-                               string(0,BPINPS;) \
-                               (contains(0,128,<1B>%-12345X) + \
-                                (contains(0,4096,"LANGUAGE=HPGL") \
-                                 contains(0,4096,"LANGUAGE = HPGL")))
 
 ########################################################################
 #
index d47f142789570ca9178716e406c6ab76651ec9c2..3616619818e2c46f07a429281e4fe3b67853a273 100644 (file)
@@ -281,15 +281,14 @@ AC_SUBST(DBUS_NOTIFIERLIBS)
 dnl Extra platform-specific libraries...
 CUPS_DEFAULT_PRINTOPERATOR_AUTH="@SYSTEM"
 CUPS_SYSTEM_AUTHKEY=""
-FONTS="fonts"
-LEGACY_BACKENDS="parallel scsi"
+LEGACY_BACKENDS="parallel"
 
 case $uname in
         Darwin*)
                LEGACY_BACKENDS=""
                 BACKLIBS="$BACKLIBS -framework IOKit"
-                CUPSDLIBS="$CUPSDLIBS -sectorder __TEXT __text cupsd.order -e start -framework IOKit -framework SystemConfiguration -weak_framework ApplicationServices"
-                LIBS="-framework SystemConfiguration -framework CoreFoundation $LIBS"
+                CUPSDLIBS="$CUPSDLIBS -sectorder __TEXT __text cupsd.order -e start -framework IOKit -weak_framework ApplicationServices"
+                LIBS="-framework SystemConfiguration -framework CoreFoundation -framework Security $LIBS"
 
                dnl Check for framework headers...
                AC_CHECK_HEADER(CoreFoundation/CoreFoundation.h,AC_DEFINE(HAVE_COREFOUNDATION_H))
@@ -347,7 +346,6 @@ esac
 AC_SUBST(CUPS_DEFAULT_PRINTOPERATOR_AUTH)
 AC_DEFINE_UNQUOTED(CUPS_DEFAULT_PRINTOPERATOR_AUTH, "$CUPS_DEFAULT_PRINTOPERATOR_AUTH")
 AC_SUBST(CUPS_SYSTEM_AUTHKEY)
-AC_SUBST(FONTS)
 AC_SUBST(LEGACY_BACKENDS)
 
 dnl
index 4f455a8232f9733f27d584426c8e13ec4c605cb6..2864cbad4ef533f651087adb624ec4a90c9efc1f 100644 (file)
@@ -447,6 +447,15 @@ fi
 AC_SUBST(BANNERTOPS)
 AC_SUBST(TEXTTOPS)
 
+dnl Fonts
+if test "x$BANNERTOPS" = x -a "x$TEXTTOPS" = x; then
+       FONTS=""
+else
+       FONTS="fonts"
+fi
+
+AC_SUBST(FONTS)
+
 dnl
 dnl End of "$Id: cups-defaults.m4 7959 2008-09-17 19:30:58Z mike $".
 dnl
index a6a893235e82c8164ada5131281ea2421f52813f..23a2295160289d9084a73d889c18e51e3eb7c4c9 100644 (file)
@@ -1,9 +1,9 @@
 dnl
 dnl "$Id: cups-launchd.m4 6649 2007-07-11 21:46:42Z mike $"
 dnl
-dnl   launchd stuff for the Common UNIX Printing System (CUPS).
+dnl   launchd stuff for CUPS.
 dnl
-dnl   Copyright 2007-2009 by Apple Inc.
+dnl   Copyright 2007-2010 by Apple Inc.
 dnl   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -35,7 +35,6 @@ if test x$enable_launchd != xno; then
        esac
 fi
 
-AC_DEFINE_UNQUOTED(CUPS_DEFAULT_LAUNCHD_CONF, "$DEFAULT_LAUNCHD_CONF")
 AC_SUBST(DEFAULT_LAUNCHD_CONF)
 AC_SUBST(LAUNCHDLIBS)
 
index 09c55f8975daa41895912941524de59fd7ba0d86..4363bfce2bff84161cc8938680aec30538203ec3 100644 (file)
@@ -1,9 +1,9 @@
 dnl
 dnl "$Id: cups-sharedlibs.m4 7630 2008-06-09 22:31:44Z mike $"
 dnl
-dnl   Shared library support for the Common UNIX Printing System (CUPS).
+dnl   Shared library support for CUPS.
 dnl
-dnl   Copyright 2007-2009 by Apple Inc.
+dnl   Copyright 2007-2010 by Apple Inc.
 dnl   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -18,10 +18,14 @@ DSOFLAGS="${DSOFLAGS:=}"
 
 AC_ARG_ENABLE(shared, [  --disable-shared        do not create shared libraries])
 
+cupsbase="cups"
+LIBCUPSBASE="lib$cupsbase"
+LIBCUPSSTATIC="lib$cupsbase.a"
+
 if test x$enable_shared != xno; then
        case "$uname" in
                SunOS*)
-                       LIBCUPS="libcups.so.2"
+                       LIBCUPS="lib$cupsbase.so.2"
                        LIBCUPSCGI="libcupscgi.so.1"
                        LIBCUPSDRIVER="libcupsdriver.so.1"
                        LIBCUPSIMAGE="libcupsimage.so.2"
@@ -32,7 +36,7 @@ if test x$enable_shared != xno; then
                        DSOFLAGS="$DSOFLAGS -Wl,-h\`basename \$@\` -G \$(OPTIM)"
                        ;;
                UNIX_S*)
-                       LIBCUPS="libcups.so.2"
+                       LIBCUPS="lib$cupsbase.so.2"
                        LIBCUPSCGI="libcupscgi.so.1"
                        LIBCUPSDRIVER="libcupsdriver.so.1"
                        LIBCUPSIMAGE="libcupsimage.so.2"
@@ -45,7 +49,7 @@ if test x$enable_shared != xno; then
                HP-UX*)
                        case "$uarch" in
                                ia64)
-                                       LIBCUPS="libcups.so.2"
+                                       LIBCUPS="lib$cupsbase.so.2"
                                        LIBCUPSCGI="libcupscgi.so.1"
                                        LIBCUPSDRIVER="libcupsdriver.so.1"
                                        LIBCUPSIMAGE="libcupsimage.so.2"
@@ -56,7 +60,7 @@ if test x$enable_shared != xno; then
                                        DSOFLAGS="$DSOFLAGS -Wl,-b,-z,+h,\`basename \$@\`"
                                        ;;
                                *)
-                                       LIBCUPS="libcups.sl.2"
+                                       LIBCUPS="lib$cupsbase.sl.2"
                                        LIBCUPSCGI="libcupscgi.sl.1"
                                        LIBCUPSDRIVER="libcupsdriver.sl.1"
                                        LIBCUPSIMAGE="libcupsimage.sl.2"
@@ -69,7 +73,7 @@ if test x$enable_shared != xno; then
                        esac
                        ;;
                IRIX)
-                       LIBCUPS="libcups.so.2"
+                       LIBCUPS="lib$cupsbase.so.2"
                        LIBCUPSCGI="libcupscgi.so.1"
                        LIBCUPSDRIVER="libcupsdriver.so.1"
                        LIBCUPSIMAGE="libcupsimage.so.2"
@@ -80,7 +84,7 @@ if test x$enable_shared != xno; then
                        DSOFLAGS="$DSOFLAGS -set_version,sgi2.6,-soname,\`basename \$@\` -shared \$(OPTIM)"
                        ;;
                OSF1* | Linux | GNU | *BSD*)
-                       LIBCUPS="libcups.so.2"
+                       LIBCUPS="lib$cupsbase.so.2"
                        LIBCUPSCGI="libcupscgi.so.1"
                        LIBCUPSDRIVER="libcupsdriver.so.1"
                        LIBCUPSIMAGE="libcupsimage.so.2"
@@ -91,7 +95,7 @@ if test x$enable_shared != xno; then
                        DSOFLAGS="$DSOFLAGS -Wl,-soname,\`basename \$@\` -shared \$(OPTIM)"
                        ;;
                Darwin*)
-                       LIBCUPS="libcups.2.dylib"
+                       LIBCUPS="lib$cupsbase.2.dylib"
                        LIBCUPSCGI="libcupscgi.1.dylib"
                        LIBCUPSDRIVER="libcupsdriver.1.dylib"
                        LIBCUPSIMAGE="libcupsimage.2.dylib"
@@ -102,7 +106,8 @@ if test x$enable_shared != xno; then
                        DSOFLAGS="$DSOFLAGS -dynamiclib -single_module -lc"
                        ;;
                AIX*)
-                       LIBCUPS="libcups_s.a"
+                       LIBCUPS="lib${cupsbase}_s.a"
+                       LIBCUPSBASE="${cupsbase}_s"
                        LIBCUPSCGI="libcupscgi_s.a"
                        LIBCUPSDRIVER="libcupsdriver_s.a"
                        LIBCUPSIMAGE="libcupsimage_s.a"
@@ -115,7 +120,7 @@ if test x$enable_shared != xno; then
                *)
                        echo "Warning: shared libraries may not be supported.  Trying -shared"
                        echo "         option with compiler."
-                       LIBCUPS="libcups.so.2"
+                       LIBCUPS="lib$cupsbase.so.2"
                        LIBCUPSCGI="libcupscgi.so.1"
                        LIBCUPSDRIVER="libcupsdriver.so.1"
                        LIBCUPSIMAGE="libcupsimage.so.2"
@@ -128,7 +133,7 @@ if test x$enable_shared != xno; then
        esac
 else
        PICFLAG=0
-       LIBCUPS="libcups.a"
+       LIBCUPS="lib$cupsbase.a"
        LIBCUPSCGI="libcupscgi.a"
        LIBCUPSDRIVER="libcupsdriver.a"
        LIBCUPSIMAGE="libcupsimage.a"
@@ -149,21 +154,23 @@ AC_SUBST(DSOFLAGS)
 AC_SUBST(DSO32FLAGS)
 AC_SUBST(DSO64FLAGS)
 AC_SUBST(LIBCUPS)
+AC_SUBST(LIBCUPSBASE)
 AC_SUBST(LIBCUPSCGI)
 AC_SUBST(LIBCUPSDRIVER)
 AC_SUBST(LIBCUPSIMAGE)
 AC_SUBST(LIBCUPSMIME)
 AC_SUBST(LIBCUPSPPDC)
+AC_SUBST(LIBCUPSSTATIC)
 
 if test x$enable_shared = xno; then
-       LINKCUPS="../cups/libcups.a"
+       LINKCUPS="../cups/lib$cupsbase.a"
        LINKCUPSIMAGE="../filter/libcupsimage.a"
 else
        if test $uname = AIX; then
-               LINKCUPS="-lcups_s"
+               LINKCUPS="-l${cupsbase}_s"
                LINKCUPSIMAGE="-lcupsimage_s"
        else
-               LINKCUPS="-lcups"
+               LINKCUPS="-l${cupsbase}"
                LINKCUPSIMAGE="-lcupsimage"
        fi
 fi
index 7e20ecd90528c7cdd6596b47ef16f37523da2f82..b0139c78c255b31e185ea2a9ac80af4e46ae8d56 100644 (file)
@@ -1,9 +1,9 @@
 dnl
 dnl "$Id: cups-ssl.m4 7241 2008-01-22 22:34:52Z mike $"
 dnl
-dnl   OpenSSL/GNUTLS stuff for the Common UNIX Printing System (CUPS).
+dnl   OpenSSL/GNUTLS stuff for CUPS.
 dnl
-dnl   Copyright 2007-2009 by Apple Inc.
+dnl   Copyright 2007-2010 by Apple Inc.
 dnl   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -26,13 +26,14 @@ AC_ARG_WITH(openssl-includes, [  --with-openssl-includes set directory for OpenS
 
 SSLFLAGS=""
 SSLLIBS=""
+have_ssl=0
 
 if test x$enable_ssl != xno; then
     dnl Look for CDSA...
-    if test "x${SSLLIBS}" = "x" -a "x${enable_cdsassl}" != "xno"; then
+    if test $have_ssl = 0 -a "x${enable_cdsassl}" != "xno"; then
        if test $uname = Darwin; then
            AC_CHECK_HEADER(Security/SecureTransport.h, [
-               SSLLIBS="-framework CoreFoundation -framework Security"
+               have_ssl=1
                AC_DEFINE(HAVE_SSL)
                AC_DEFINE(HAVE_CDSASSL)
 
@@ -58,9 +59,10 @@ if test x$enable_ssl != xno; then
     fi
 
     dnl Then look for GNU TLS...
-    if test "x${SSLLIBS}" = "x" -a "x${enable_gnutls}" != "xno" -a "x$PKGCONFIG" != x; then
+    if test $have_ssl = 0 -a "x${enable_gnutls}" != "xno" -a "x$PKGCONFIG" != x; then
        AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config)
        if $PKGCONFIG --exists gnutls; then
+           have_ssl=1
            SSLLIBS=`$PKGCONFIG --libs gnutls`
            SSLFLAGS=`$PKGCONFIG --cflags gnutls`
            AC_DEFINE(HAVE_SSL)
@@ -69,7 +71,7 @@ if test x$enable_ssl != xno; then
     fi
 
     dnl Check for the OpenSSL library last...
-    if test "x${SSLLIBS}" = "x" -a "x${enable_openssl}" != "xno"; then
+    if test $have_ssl = 0 -a "x${enable_openssl}" != "xno"; then
        AC_CHECK_HEADER(openssl/ssl.h,
            dnl Save the current libraries so the crypto stuff isn't always
            dnl included...
@@ -87,7 +89,8 @@ if test x$enable_ssl != xno; then
                "-lcrypto -lRSAglue -lrsaref"
            do
                AC_CHECK_LIB(ssl,SSL_new,
-                   [SSLFLAGS="-DOPENSSL_DISABLE_OLD_DES_SUPPORT"
+                   [have_ssl=1
+                    SSLFLAGS="-DOPENSSL_DISABLE_OLD_DES_SUPPORT"
                     SSLLIBS="-lssl $libcrypto"
                     AC_DEFINE(HAVE_SSL)
                     AC_DEFINE(HAVE_LIBSSL)],,
@@ -102,7 +105,7 @@ if test x$enable_ssl != xno; then
     fi
 fi
 
-if test "x$SSLLIBS" != x; then
+if test $have_ssl = 1; then
     AC_MSG_RESULT([    Using SSLLIBS="$SSLLIBS"])
     AC_MSG_RESULT([    Using SSLFLAGS="$SSLFLAGS"])
 fi
index 91f193d1d4f6db23696a070244147bacb68dd5c1..34198e412c481ec4be72d7e499d714d9e6f2ab93 100644 (file)
@@ -1,9 +1,9 @@
 dnl
 dnl "$Id: configure.in 7833 2008-08-04 20:55:13Z mike $"
 dnl
-dnl   Configuration script for the Common UNIX Printing System (CUPS).
+dnl   Configuration script for CUPS.
 dnl
-dnl   Copyright 2007 by Apple Inc.
+dnl   Copyright 2007-2010 by Apple Inc.
 dnl   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
index 088611143e4a8730f1444901a211fc2cc9323e25..b7e9a8d8a71e31856f41d0c9bfcf9ed33f7236e0 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7871 2008-08-27 21:12:43Z mike $"
 #
-#   API library Makefile for the Common UNIX Printing System (CUPS).
+#   API library Makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -113,10 +113,10 @@ HEADERS   =       \
 #
 
 LIBTARGETS =   \
+               $(LIBCUPSSTATIC) \
                $(LIBCUPS) \
                $(LIB32CUPS) \
-               $(LIB64CUPS) \
-               libcups.a
+               $(LIB64CUPS)
 
 UNITTARGETS =  \
                testadmin \
@@ -140,7 +140,7 @@ TARGETS     =       \
 # Make all targets...
 #
 
-all:   $(TARGETS)
+all:           $(TARGETS)
 
 
 #
@@ -237,9 +237,9 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64)
 
 installstatic:
        $(INSTALL_DIR) -m 755 $(LIBDIR)
-       $(INSTALL_LIB) -m 755 libcups.a $(LIBDIR)
-       $(RANLIB) $(LIBDIR)/libcups.a
-       $(CHMOD) 555 $(LIBDIR)/libcups.a
+       $(INSTALL_LIB) -m 755 $(LIBCUPSSTATIC) $(LIBDIR)
+       $(RANLIB) $(LIBDIR)/$(LIBCUPSSTATIC)
+       $(CHMOD) 555 $(LIBDIR)/$(LIBCUPSSTATIC)
 
 install32bit:
        echo Installing libraries in $(LIB32DIR)...
@@ -326,17 +326,21 @@ libcups.so.2 libcups.sl.2:        $(LIBOBJS)
 # libcups.2.dylib
 #
 
-libcups.2.dylib:       $(LIBOBJS) $(LIBCUPSORDER) libcups.exp
+libcups.2.dylib:       $(LIBOBJS) $(LIBCUPSORDER)
+       echo Creating export list for $@...
+       nm $(LIBOBJS) 2>/dev/null | grep "T _" | awk '{print $$3}' | \
+               grep -v -e '^(_cupsConnect|_cupsSetDefaults|_cupsSetHTTPError|_cupsUserDefault|_httpWait)$$' | \
+               sort >t.exp
        echo Linking $@...
        $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ \
                -install_name $(libdir)/$@ \
                -current_version 2.8.0 \
                -compatibility_version 2.0.0 \
-               -exported_symbols_list libcups.exp \
+               -exported_symbols_list t.exp \
                -sectorder __TEXT __text $(LIBCUPSORDER) \
                $(LIBOBJS) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
                $(COMMONLIBS) $(LIBZ)
-       $(RM) libcups.dylib
+       $(RM) libcups.dylib t.exp
        $(LN) $@ libcups.dylib
 
 
@@ -375,37 +379,13 @@ libcups.a:        $(LIBOBJS)
        $(RANLIB) $@
 
 
-#
-# CUPS language bindings for various scripting languages...
-#
-# NOTE: Not currently used or functional - see the scripting/php directory
-#       for the hand-written bindings...
-#
-
-phpcups.so:    $(LIBCUPS) php_cups_wrap.o
-       echo Linking $@...
-       if test `uname` = Darwin; then \
-               DSOFLAGS="-bundle -flat_namespace -undefined suppress"; \
-       else \
-               DSOFLAGS="$(DSOFLAGS)"; \
-       fi; \
-       $(DSO) $$DSOFLAGS -o $@ php_cups_wrap.o $(LIBS) `php-config --ldflags --libs`
-
-php_cups_wrap.o:       php_cups_wrap.c
-       echo Compiling $<...
-       $(CC) $(CFLAGS) `php-config --includes` -c $<
-php_cups_wrap.c:       cups.h
-       echo Creating $< using SWIG...
-       swig -php -o $@ -module cups cups.h
-
-
 #
 # testadmin (dependency on static CUPS library is intentional)
 #
 
-testadmin:     testadmin.o libcups.a
+testadmin:     testadmin.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ testadmin.o libcups.a \
+       $(CC) $(LDFLAGS) -o $@ testadmin.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
@@ -413,9 +393,9 @@ testadmin:  testadmin.o libcups.a
 # testarray (dependency on static CUPS library is intentional)
 #
 
-testarray:     testarray.o libcups.a
+testarray:     testarray.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testarray.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testarray.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running array API tests...
        ./testarray
@@ -425,9 +405,9 @@ testarray:  testarray.o libcups.a
 # testconflicts (dependency on static CUPS library is intentional)
 #
 
-testconflicts: testconflicts.o libcups.a
+testconflicts: testconflicts.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ testconflicts.o libcups.a \
+       $(CC) $(LDFLAGS) -o $@ testconflicts.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
@@ -435,9 +415,9 @@ testconflicts:      testconflicts.o libcups.a
 # testcups (dependency on static CUPS library is intentional)
 #
 
-testcups:      testcups.o libcups.a
+testcups:      testcups.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ testcups.o libcups.a \
+       $(CC) $(LDFLAGS) -o $@ testcups.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
@@ -445,9 +425,9 @@ testcups:   testcups.o libcups.a
 # testfile (dependency on static CUPS library is intentional)
 #
 
-testfile:      testfile.o libcups.a
+testfile:      testfile.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testfile.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testfile.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running file API tests...
        ./testfile
@@ -457,9 +437,9 @@ testfile:   testfile.o libcups.a
 # testhttp (dependency on static CUPS library is intentional)
 #
 
-testhttp:      testhttp.o libcups.a
+testhttp:      testhttp.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testhttp.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testhttp.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running HTTP API tests...
        ./testhttp
@@ -469,9 +449,9 @@ testhttp:   testhttp.o libcups.a
 # testipp (dependency on static CUPS library is intentional)
 #
 
-testipp:       testipp.o libcups.a
+testipp:       testipp.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testipp.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testipp.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running IPP API tests...
        ./testipp
@@ -481,9 +461,9 @@ testipp:    testipp.o libcups.a
 # testi18n (dependency on static CUPS library is intentional)
 #
 
-testi18n:      testi18n.o libcups.a
+testi18n:      testi18n.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testi18n.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testi18n.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running internationalization API tests...
        ./testi18n
@@ -493,9 +473,9 @@ testi18n:   testi18n.o libcups.a
 # testlang (dependency on static CUPS library is intentional)
 #
 
-testlang:      testlang.o libcups.a
+testlang:      testlang.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testlang.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testlang.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running language API tests...
        ./testlang
@@ -505,9 +485,9 @@ testlang:   testlang.o libcups.a
 # testoptions (dependency on static CUPS library is intentional)
 #
 
-testoptions:   testoptions.o libcups.a
+testoptions:   testoptions.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testoptions.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testoptions.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running option API tests...
        ./testoptions
@@ -517,9 +497,9 @@ testoptions:        testoptions.o libcups.a
 # testppd (dependency on static CUPS library is intentional)
 #
 
-testppd:       testppd.o libcups.a test.ppd test2.ppd
+testppd:       testppd.o $(LIBCUPSSTATIC) test.ppd test2.ppd
        echo Linking $@...
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testppd.o libcups.a \
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testppd.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Running PPD API tests...
        ./testppd
@@ -529,9 +509,9 @@ testppd:    testppd.o libcups.a test.ppd test2.ppd
 # testsnmp (dependency on static CUPS library is intentional)
 #
 
-testsnmp:      testsnmp.o libcups.a
+testsnmp:      testsnmp.o $(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ testsnmp.o libcups.a \
+       $(CC) $(LDFLAGS) -o $@ testsnmp.o $(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
index c2c6eb5128e91a17b827e99a7e86a53795457200..2cae04f3d65b6912760efa48a563fd979b1d7ad2 100644 (file)
@@ -1,10 +1,9 @@
 /*
  * "$Id: attr.c 7584 2008-05-16 22:55:53Z mike $"
  *
- *   PPD model-specific attribute routines for the Common UNIX Printing System
- *   (CUPS).
+ *   PPD model-specific attribute routines for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -15,8 +14,9 @@
  *
  * Contents:
  *
- *   ppdFindAttr()     - Find the first matching attribute.
- *   ppdFindNextAttr() - Find the next matching attribute.
+ *   ppdFindAttr()               - Find the first matching attribute.
+ *   ppdFindNextAttr()           - Find the next matching attribute.
+ *   _ppdNormalizeMakeAndModel() - Normalize a product/make-and-model string.
  */
 
 /*
@@ -140,89 +140,6 @@ ppdFindNextAttr(ppd_file_t *ppd,   /* I - PPD file data */
 }
 
 
-/*
- * '_ppdGet1284Values()' - Get 1284 device ID keys and values.
- *
- * The returned dictionary is a CUPS option array that can be queried with
- * cupsGetOption and freed with cupsFreeOptions.
- */
-
-int                                    /* O - Number of key/value pairs */
-_ppdGet1284Values(
-    const char *device_id,             /* I - IEEE-1284 device ID string */
-    cups_option_t **values)            /* O - Array of key/value pairs */
-{
-  int          num_values;             /* Number of values */
-  char         key[256],               /* Key string */
-               value[256],             /* Value string */
-               *ptr;                   /* Pointer into key/value */
-
-
- /*
-  * Range check input...
-  */
-
-  if (values)
-    *values = NULL;
-
-  if (!device_id || !values)
-    return (0);
-
- /*
-  * Parse the 1284 device ID value into keys and values.  The format is
-  * repeating sequences of:
-  *
-  *   [whitespace]key:value[whitespace];
-  */
-
-  num_values = 0;
-  while (*device_id)
-  {
-    while (isspace(*device_id & 255))
-      device_id ++;
-
-    if (!*device_id)
-      break;
-
-    for (ptr = key; *device_id && *device_id != ':'; device_id ++)
-      if (ptr < (key + sizeof(key) - 1))
-        *ptr++ = *device_id;
-
-    if (!*device_id)
-      break;
-
-    while (ptr > key && isspace(ptr[-1] & 255))
-      ptr --;
-
-    *ptr = '\0';
-    device_id ++;
-
-    while (isspace(*device_id & 255))
-      device_id ++;
-
-    if (!*device_id)
-      break;
-
-    for (ptr = value; *device_id && *device_id != ';'; device_id ++)
-      if (ptr < (value + sizeof(value) - 1))
-        *ptr++ = *device_id;
-
-    if (!*device_id)
-      break;
-
-    while (ptr > value && isspace(ptr[-1] & 255))
-      ptr --;
-
-    *ptr = '\0';
-    device_id ++;
-
-    num_values = cupsAddOption(key, value, num_values, values);
-  }
-
-  return (num_values);
-}
-
-
 /*
  * '_ppdNormalizeMakeAndModel()' - Normalize a product/make-and-model string.
  *
index f3d2f1c5b5487c85a86629de414f130c787c123e..137edffc4e3d44b941dc8d6c54ccb1596ab4e8d0 100644 (file)
@@ -68,7 +68,7 @@ static pthread_mutex_t        debug_mutex = PTHREAD_MUTEX_INITIALIZER;
  * 'debug_vsnprintf()' - Format a string into a fixed size buffer.
  */
 
-int                                    /* O - Number of bytes formatted */
+static int                             /* O - Number of bytes formatted */
 debug_vsnprintf(char       *buffer,    /* O - Output buffer */
                 size_t     bufsize,    /* O - Size of output buffer */
                const char *format,     /* I - printf-style format string */
index 4e49109fc9d2bc41dbc40a24cd42347e5da5dc78..8207312ce918c97a00755a5facdaf6c993e29d49 100644 (file)
 static void
 cups_env_init(_cups_globals_t *g)      /* I - Global data */
 {
+#ifdef WIN32
+  HKEY         key;                    /* Registry key */
+  DWORD                size;                   /* Size of string */
+  static char  installdir[1024],       /* Install directory */
+               confdir[1024],          /* Server root directory */
+               localedir[1024];        /* Locale directory */
+
+
+ /*
+  * Open the registry...
+  */
+
+  strcpy(installdir, "C:/Program Files/cups.org");
+
+  if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\cups.org", 0, KEY_READ,
+                    &key))
+  {
+   /*
+    * Grab the installation directory...
+    */
+
+    size = sizeof(installdir);
+    RegQueryValueEx(key, "installdir", NULL, NULL, installdir, &size);
+    RegCloseKey(key);
+  }
+
+  snprintf(confdir, sizeof(confdir), "%s/conf", installdir);
+  snprintf(localedir, sizeof(localedir), "%s/locale", installdir);
+
+  if ((g->cups_datadir = getenv("CUPS_DATADIR")) == NULL)
+    g->cups_datadir = installdir;
+
+  if ((g->cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
+    g->cups_serverbin = installdir;
+
+  if ((g->cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
+    g->cups_serverroot = confdir;
+
+  if ((g->cups_statedir = getenv("CUPS_STATEDIR")) == NULL)
+    g->cups_statedir = confdir;
+
+  if ((g->localedir = getenv("LOCALEDIR")) == NULL)
+    g->localedir = localedir;
+
+#else
   if ((g->cups_datadir = getenv("CUPS_DATADIR")) == NULL)
     g->cups_datadir = CUPS_DATADIR;
 
@@ -52,6 +97,7 @@ cups_env_init(_cups_globals_t *g)     /* I - Global data */
 
   if ((g->localedir = getenv("LOCALEDIR")) == NULL)
     g->localedir = CUPS_LOCALEDIR;
+#endif /* WIN32 */
 }
 
 
index fecbeb3d7021fa0708e9bc962c22f2d9dc6bba1f..1e07daac64f854d111ba0081f8e57cae19edac25 100644 (file)
@@ -141,6 +141,8 @@ typedef struct _cups_globals_s              /**** CUPS global state data ****/
  */
 
 extern http_t          *_cupsConnect(void);
+extern int             _cupsGet1284Values(const char *device_id,
+                                          cups_option_t **values);
 extern const char      *_cupsGetPassword(const char *prompt);
 extern _cups_globals_t *_cupsGlobals(void);
 extern void            _cupsSetDefaults(void);
index abd24130560d9a311d91e67e9ee3e631e1c1b7a6..084e88e9b03bc425a9bbdde999a8f81ec5862712 100644 (file)
@@ -559,8 +559,9 @@ httpError(http_t *http)                     /* I - Connection to server */
 void
 httpFlush(http_t *http)                        /* I - Connection to server */
 {
-  char buffer[8192];                   /* Junk buffer */
-  int  blocking;                       /* To block or not to block */
+  char         buffer[8192];           /* Junk buffer */
+  int          blocking;               /* To block or not to block */
+  http_state_t oldstate;               /* Old state */
 
 
   DEBUG_printf(("httpFlush(http=%p), state=%s", http,
@@ -577,6 +578,7 @@ httpFlush(http_t *http)                     /* I - Connection to server */
   * Read any data we can...
   */
 
+  oldstate = http->state;
   while (httpRead2(http, buffer, sizeof(buffer)) > 0);
 
  /*
@@ -586,7 +588,7 @@ httpFlush(http_t *http)                     /* I - Connection to server */
 
   http->blocking = blocking;
 
-  if (http->state != HTTP_WAITING && http->fd >= 0)
+  if (http->state == oldstate && http->fd >= 0)
   {
    /*
     * Didn't get the data back, so close the current connection.
@@ -625,7 +627,11 @@ httpFlushWrite(http_t *http)               /* I - Connection to server */
   DEBUG_printf(("httpFlushWrite(http=%p)", http));
 
   if (!http || !http->wused)
+  {
+    DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." :
+                      "1httpFlushWrite: No connection.");
     return (0);
+  }
 
   if (http->data_encoding == HTTP_ENCODE_CHUNKED)
     bytes = http_write_chunk(http, http->wbuffer, http->wused);
@@ -634,6 +640,8 @@ httpFlushWrite(http_t *http)                /* I - Connection to server */
 
   http->wused = 0;
 
+  DEBUG_printf(("1httpFlushWrite: Returning %d.", bytes));
+
   return (bytes);
 }
 
@@ -2167,7 +2175,10 @@ _httpWait(http_t *http,                  /* I - Connection to server */
   DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
 
   if (http->fd < 0)
+  {
+    DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
     return (0);
+  }
 
  /*
   * Check the SSL/TLS buffers for data first...
@@ -2178,16 +2189,27 @@ _httpWait(http_t *http,                 /* I - Connection to server */
   {
 #  ifdef HAVE_LIBSSL
     if (SSL_pending((SSL *)(http->tls)))
+    {
+      DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
       return (1);
+    }
+
 #  elif defined(HAVE_GNUTLS)
     if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
+    {
+      DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
       return (1);
+    }
+
 #  elif defined(HAVE_CDSASSL)
     size_t bytes;                      /* Bytes that are available */
 
     if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
         bytes > 0)
+    {
+      DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
       return (1);
+    }
 #  endif /* HAVE_LIBSSL */
   }
 #endif /* HAVE_SSL */
@@ -2230,7 +2252,8 @@ _httpWait(http_t *http,                   /* I - Connection to server */
 #  endif /* WIN32 */
 #endif /* HAVE_POLL */
 
-  DEBUG_printf(("5_httpWait: returning with nfds=%d...", nfds));
+  DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
+                errno));
 
   return (nfds > 0);
 }
@@ -3258,6 +3281,8 @@ http_write(http_t     *http,              /* I - Connection to server */
        bytes;                          /* Bytes sent */
 
 
+  DEBUG_printf(("2http_write(http=%p, buffer=%p, length=%d)", http, buffer,
+                length));
   http->error = 0;
   tbytes      = 0;
 
@@ -3288,7 +3313,8 @@ http_write(http_t     *http,              /* I - Connection to server */
       }
 #endif /* WIN32 */
 
-      DEBUG_puts("8http_write: error writing data...");
+      DEBUG_printf(("3http_write: error writing data (%s).",
+                    strerror(http->error)));
 
       return (-1);
     }
@@ -3302,6 +3328,8 @@ http_write(http_t     *http,              /* I - Connection to server */
   http_debug_hex("http_write", buffer - tbytes, tbytes);
 #endif /* DEBUG */
 
+  DEBUG_printf(("3http_write: Returning %d.", tbytes));
+
   return (tbytes);
 }
 
@@ -3359,12 +3387,15 @@ http_write_ssl(http_t     *http,        /* I - Connection to server */
               const char *buf,         /* I - Buffer holding data */
               int        len)          /* I - Length of buffer */
 {
+  ssize_t      result;                 /* Return value */
+
+
+  DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
+
 #  if defined(HAVE_LIBSSL)
-  return (SSL_write((SSL *)(http->tls), buf, len));
+  result = SSL_write((SSL *)(http->tls), buf, len);
 
 #  elif defined(HAVE_GNUTLS)
-  ssize_t      result;                 /* Return value */
-
   result = gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len);
 
   if (result < 0 && !errno)
@@ -3391,10 +3422,7 @@ http_write_ssl(http_t     *http, /* I - Connection to server */
     result = -1;
   }
 
-  return ((int)result);
-
 #  elif defined(HAVE_CDSASSL)
-  int          result;                 /* Return value */
   OSStatus     error;                  /* Error info */
   size_t       processed;              /* Number of bytes processed */
 
@@ -3423,9 +3451,11 @@ http_write_ssl(http_t     *http, /* I - Connection to server */
        result = -1;
        break;
   }
-
-  return (result);
 #  endif /* HAVE_LIBSSL */
+
+  DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
+
+  return ((int)result);
 }
 #endif /* HAVE_SSL */
 
index c61be42c4c60aa4dc4e2afe884b3b21a7d3e6388..bc6e779b0c17417f57ab9d4b443b97058cda0b95 100644 (file)
@@ -82,19 +82,19 @@ typedef struct _cups_vmap_s         /**** VBCS Charmap Struct ****/
  * Prototypes...
  */
 
-#ifdef __APPLE__
+#  ifdef __APPLE__
 extern const char      *_cupsAppleLanguage(const char *locale, char *language,
                                            size_t langsize);
-#endif /* __APPLE__ */
+#  endif /* __APPLE__ */
 extern void            _cupsCharmapFlush(void);
 extern void            _cupsCharmapFree(const cups_encoding_t encoding);
 extern void            *_cupsCharmapGet(const cups_encoding_t encoding);
 extern const char      *_cupsEncodingName(cups_encoding_t encoding);
 extern void            _cupsLangPrintError(const char *message);
 extern int             _cupsLangPrintf(FILE *fp, const char *message, ...)
-#    ifdef __GNUC__
+#  ifdef __GNUC__
 __attribute__ ((__format__ (__printf__, 2, 3)))
-#    endif /* __GNUC__ */
+#  endif /* __GNUC__ */
 ;
 extern int             _cupsLangPuts(FILE *fp, const char *message);
 extern const char      *_cupsLangString(cups_lang_t *lang, const char *message);
index 82200ae7d29660dee27333ac2ab4a62ee2c48198..663ba3ed7d157278b39a2d357bd212555afda4a1 100644 (file)
@@ -217,7 +217,7 @@ static char * const ipp_std_ops[] =
                  "dateTime",           /* 0x31 */
                  "resolution",         /* 0x32 */
                  "rangeOfInteger",     /* 0x33 */
-                 "begCollection",      /* 0x34 */
+                 "collection",         /* 0x34 */
                  "textWithLanguage",   /* 0x35 */
                  "nameWithLanguage",   /* 0x36 */
                  "endCollection",      /* 0x37 */
index 70fb41f3813afbe73d46d7510e01f5775585adc7..2f12f85b4fd581807600c7bf461c919a23ab2447 100644 (file)
@@ -425,7 +425,8 @@ ippAddString(ipp_t      *ipp,               /* I - IPP message */
     value = "en";
 
  /*
-  * Convert language values to lowercase and change _ to - as needed...
+  * Convert language and charset values to lowercase and change _ to - as
+  * needed...
   */
 
   if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && value)
@@ -473,6 +474,8 @@ ippAddStrings(
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
   ipp_value_t          *value;         /* Current value */
+  char                 buffer[1024],   /* Language/charset value buffer */
+                       *bufptr;        /* Pointer into buffer */
 
 
   DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
@@ -506,16 +509,36 @@ ippAddStrings(
 
     if (values != NULL)
     {
-     /*
-      * Force language to be English for the POSIX locale...
-      */
+      if ((int)type & IPP_TAG_COPY)
+        value->string.text = (char *)values[i];
+      else if (type == IPP_TAG_LANGUAGE && !strcasecmp(values[i], "C"))
+      {
+       /*
+       * Force language to be English for the POSIX locale...
+       */
 
-      if (type == IPP_TAG_LANGUAGE && !strcasecmp(values[i], "C"))
        value->string.text = ((int)type & IPP_TAG_COPY) ? "en" :
                                       _cupsStrAlloc("en");
+      }
+      else if (type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET)
+      {
+       /*
+       * Convert language values to lowercase and change _ to - as needed...
+       */
+
+       strlcpy(buffer, values[i], sizeof(buffer));
+
+       for (bufptr = buffer; *bufptr; bufptr ++)
+         if (*bufptr == '_')
+           *bufptr = '-';
+         else
+           *bufptr = tolower(*bufptr & 255);
+
+       value->string.text = _cupsStrAlloc(buffer);
+      }
       else
-       value->string.text = ((int)type & IPP_TAG_COPY) ? (char *)values[i] :
-                                      _cupsStrAlloc(values[i]);
+       value->string.text = _cupsStrAlloc(values[i]);
+
     }
   }
 
index 16fa94d1df61940dbd85100ea673b944a97349a1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,356 +0,0 @@
-__cups_debug_fd
-__cups_debug_printf
-__cups_debug_puts
-__cups_strcpy
-__cupsAdminGetServerSettings
-__cupsAdminSetServerSettings
-__cupsAppleLanguage
-__cupsCharmapFlush
-__cupsCharmapFree
-__cupsCharmapGet
-__cupsEncodingName
-__cupsGetPassword
-__cupsGlobals
-__cupsLangPrintError
-__cupsLangPrintf
-__cupsLangPuts
-__cupsLangString
-__cupsMD5Append
-__cupsMD5Finish
-__cupsMD5Init
-__cupsMessageFree
-__cupsMessageLoad
-__cupsMessageLookup
-__cupsPWGMediaByName
-__cupsPWGMediaByLegacy
-__cupsPWGMediaBySize
-__cupsSetError
-__cupsSetLocale
-__cupsSNMPClose
-__cupsSNMPCopyOID
-__cupsSNMPDefaultCommunity
-__cupsSNMPIsOID
-__cupsSNMPIsOIDPrefixed
-__cupsSNMPOIDToString
-__cupsSNMPOpen
-__cupsSNMPRead
-__cupsSNMPSetDebug
-__cupsSNMPStringToOID
-__cupsSNMPWalk
-__cupsSNMPWrite
-__cupsStrAlloc
-__cupsStrFlush
-__cupsStrFormatd
-__cupsStrFree
-__cupsStrRetain
-__cupsStrScand
-__cupsStrStatistics
-__httpAddrPort
-__httpCreate
-__httpEncodeURI
-__httpReadCDSA
-__httpResolveURI
-__httpWriteCDSA
-__ippAddAttr
-__ippFindOption
-__ippFreeAttr
-__ppdFreeLanguages
-__ppdGet1284Values
-__ppdGetEncoding
-__ppdGetLanguages
-__ppdHashName
-__ppdLocalizedAttr
-__ppdNormalizeMakeAndModel
-__ppdParseOptions
-_cupsAddDest
-_cupsAddOption
-_cupsAdminCreateWindowsPPD
-_cupsAdminExportSamba
-_cupsAdminGetServerSettings
-_cupsAdminSetServerSettings
-_cupsArrayAdd
-_cupsArrayClear
-_cupsArrayCount
-_cupsArrayCurrent
-_cupsArrayDelete
-_cupsArrayDup
-_cupsArrayFind
-_cupsArrayFirst
-_cupsArrayGetIndex
-_cupsArrayGetInsert
-_cupsArrayIndex
-_cupsArrayInsert
-_cupsArrayLast
-_cupsArrayNew
-_cupsArrayNew2
-_cupsArrayNext
-_cupsArrayPrev
-_cupsArrayRemove
-_cupsArrayRestore
-_cupsArraySave
-_cupsArrayUserData
-_cupsBackChannelRead
-_cupsBackChannelWrite
-_cupsBackendDeviceURI
-_cupsBackendReport
-_cupsCancelJob
-_cupsCancelJob2
-_cupsCharsetToUTF8
-_cupsCreateJob
-_cupsDirClose
-_cupsDirOpen
-_cupsDirRead
-_cupsDirRewind
-_cupsDoAuthentication
-_cupsDoFileRequest
-_cupsDoIORequest
-_cupsDoRequest
-_cupsEncodeOptions
-_cupsEncodeOptions2
-_cupsEncryption
-_cupsFileClose
-_cupsFileCompression
-_cupsFileEOF
-_cupsFileFind
-_cupsFileFlush
-_cupsFileGetChar
-_cupsFileGetConf
-_cupsFileGetLine
-_cupsFileGets
-_cupsFileLock
-_cupsFileNumber
-_cupsFileOpen
-_cupsFileOpenFd
-_cupsFilePeekChar
-_cupsFilePrintf
-_cupsFilePutChar
-_cupsFilePutConf
-_cupsFilePuts
-_cupsFileRead
-_cupsFileRewind
-_cupsFileSeek
-_cupsFileStderr
-_cupsFileStdin
-_cupsFileStdout
-_cupsFileTell
-_cupsFileUnlock
-_cupsFileWrite
-_cupsFinishDocument
-_cupsFreeDests
-_cupsFreeJobs
-_cupsFreeOptions
-_cupsGetClasses
-_cupsGetConflicts
-_cupsGetDefault
-_cupsGetDefault2
-_cupsGetDest
-_cupsGetDests
-_cupsGetDests2
-_cupsGetDevices
-_cupsGetFd
-_cupsGetFile
-_cupsGetJobs
-_cupsGetJobs2
-_cupsGetNamedDest
-_cupsGetOption
-_cupsGetPassword
-_cupsGetPassword2
-_cupsGetPPD
-_cupsGetPPD2
-_cupsGetPPD3
-_cupsGetPrinters
-_cupsGetResponse
-_cupsGetServerPPD
-_cupsLangDefault
-_cupsLangEncoding
-_cupsLangFlush
-_cupsLangFree
-_cupsLangGet
-_cupsLastError
-_cupsLastErrorString
-_cupsMarkOptions
-_cupsNotifySubject
-_cupsNotifyText
-_cupsParseOptions
-_cupsPrintFile
-_cupsPrintFile2
-_cupsPrintFiles
-_cupsPrintFiles2
-_cupsPutFd
-_cupsPutFile
-_cupsReadResponseData
-_cupsRemoveDest
-_cupsRemoveOption
-_cupsResolveConflicts
-_cupsSendRequest
-_cupsServer
-_cupsSetDefaultDest
-_cupsSetDests
-_cupsSetDests2
-_cupsSetEncryption
-_cupsSetPasswordCB
-_cupsSetPasswordCB2
-_cupsSetServer
-_cupsSetUser
-_cupsSideChannelDoRequest
-_cupsSideChannelRead
-_cupsSideChannelWrite
-_cupsSideChannelSNMPGet
-_cupsSideChannelSNMPWalk
-_cupsStartDocument
-_cupsTempFd
-_cupsTempFile
-_cupsTempFile2
-_cupsUser
-_cupsUTF32ToUTF8
-_cupsUTF8ToCharset
-_cupsUTF8ToUTF32
-_cupsWriteRequestData
-_httpAddrAny
-_httpAddrConnect
-_httpAddrEqual
-_httpAddrFreeList
-_httpAddrGetList
-_httpAddrLength
-_httpAddrLocalhost
-_httpAddrLookup
-_httpAddrString
-_httpAssembleURI
-_httpAssembleURIf
-_httpBlocking
-_httpCheck
-_httpClearCookie
-_httpClearFields
-_httpClose
-_httpConnect
-_httpConnectEncrypt
-_httpDecode64
-_httpDecode64_2
-_httpDelete
-_httpEncode64
-_httpEncode64_2
-_httpEncryption
-_httpError
-_httpFlush
-_httpFlushWrite
-_httpGet
-_httpGetAuthString
-_httpGetBlocking
-_httpGetCookie
-_httpGetDateString
-_httpGetDateString2
-_httpGetDateTime
-_httpGetFd
-_httpGetField
-_httpGetHostByName
-_httpGetHostname
-_httpGetLength
-_httpGetLength2
-_httpGets
-_httpGetStatus
-_httpGetSubField
-_httpGetSubField2
-_httpHead
-_httpInitialize
-_httpMD5
-_httpMD5Final
-_httpMD5String
-_httpOptions
-_httpPost
-_httpPrintf
-_httpPut
-_httpRead
-_httpRead2
-_httpReconnect
-_httpSeparate
-_httpSeparate2
-_httpSeparateURI
-_httpSetAuthString
-_httpSetCookie
-_httpSetExpect
-_httpSetField
-_httpSetLength
-_httpStatus
-_httpTrace
-_httpUpdate
-_httpWait
-_httpWrite
-_httpWrite2
-_ippAddBoolean
-_ippAddBooleans
-_ippAddCollection
-_ippAddCollections
-_ippAddDate
-_ippAddInteger
-_ippAddIntegers
-_ippAddOctetString
-_ippAddRange
-_ippAddRanges
-_ippAddResolution
-_ippAddResolutions
-_ippAddSeparator
-_ippAddString
-_ippAddStrings
-_ippDateToTime
-_ippDelete
-_ippDeleteAttribute
-_ippErrorString
-_ippErrorValue
-_ippFindAttribute
-_ippFindNextAttribute
-_ippLength
-_ippNew
-_ippNewRequest
-_ippOpString
-_ippOpValue
-_ippPort
-_ippRead
-_ippReadFile
-_ippReadIO
-_ippSetPort
-_ippTagString
-_ippTagValue
-_ippTimeToDate
-_ippWrite
-_ippWriteFile
-_ippWriteIO
-_ppdClose
-_ppdCollect
-_ppdCollect2
-_ppdConflicts
-_ppdEmit
-_ppdEmitAfterOrder
-_ppdEmitFd
-_ppdEmitJCL
-_ppdEmitJCLEnd
-_ppdEmitString
-_ppdErrorString
-_ppdFindAttr
-_ppdFindChoice
-_ppdFindCustomOption
-_ppdFindCustomParam
-_ppdFindMarkedChoice
-_ppdFindNextAttr
-_ppdFindOption
-_ppdFirstCustomParam
-_ppdFirstOption
-_ppdInstallableConflict
-_ppdIsMarked
-_ppdLastError
-_ppdLocalize
-_ppdLocalizeAttr
-_ppdLocalizeIPPReason
-_ppdLocalizeMarkerName
-_ppdMarkDefaults
-_ppdMarkOption
-_ppdNextCustomParam
-_ppdNextOption
-_ppdOpen
-_ppdOpen2
-_ppdOpenFd
-_ppdOpenFile
-_ppdPageLength
-_ppdPageSize
-_ppdPageSizeLimits
-_ppdPageWidth
-_ppdSetConformance
index 1f99d8888eb9e118e5da05cc6c83284791ed1691..65f59bd1cbf330e4af687499849840c935cf2568 100644 (file)
@@ -1,5 +1,5 @@
 LIBRARY libcups2
-VERSION 2.7
+VERSION 2.8
 EXPORTS
 _cupsAdminGetServerSettings
 _cupsAdminSetServerSettings
@@ -67,6 +67,7 @@ cupsDirRead
 cupsDirRewind
 cupsDoAuthentication
 cupsDoFileRequest
+cupsDoIORequest
 cupsDoRequest
 cupsEncodeOptions
 cupsEncodeOptions2
@@ -115,6 +116,7 @@ cupsGetPPD
 cupsGetPPD2
 cupsGetPassword
 cupsGetPrinters
+cupsGetResponse
 cupsLangDefault
 cupsLangEncoding
 cupsLangFlush
@@ -134,6 +136,7 @@ cupsPutFd
 cupsPutFile
 cupsRemoveOption
 cupsResolveConflicts
+cupsSendRequest
 cupsServer
 cupsSetDests
 cupsSetDests2
@@ -148,6 +151,7 @@ cupsUTF32ToUTF8
 cupsUTF8ToCharset
 cupsUTF8ToUTF32
 cupsUser
+cupsWriteRequestData
 httpAddrAny
 httpAddrConnect
 httpAddrEqual
@@ -248,6 +252,8 @@ ippRead
 ippReadFile
 ippReadIO
 ippSetPort
+ippTagString
+ippTagValue
 ippTimeToDate
 ippWrite
 ippWriteFile
index 1b45a396ac64f6d5e4f14aab641279707a2e7a44..1ad3017fe7604dcc94ae9daf465b962b62721162 100644 (file)
@@ -5,6 +5,7 @@ _cupsCharmapFlush
 _cupsCharmapFree
 _cupsCharmapGet
 _cupsEncodingName
+_cupsGet1284Values
 _cupsGetPassword
 _cupsGlobals
 _cupsLangPrintf
@@ -53,7 +54,6 @@ _httpResolveURI
 _ippAddAttr
 _ippFreeAttr
 _ppdFreeLanguages
-_ppdGet1284Values
 _ppdGetEncoding
 _ppdGetLanguages
 _ppdHashName
index 23e4dff1c3e00fa28d44f7436fe3f50e5e2ea94f..0c9069c096d5625848f0e178cf64432ef551afd8 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: options.c 8181 2008-12-10 17:29:57Z mike $"
  *
- *   Option routines for the Common UNIX Printing System (CUPS).
+ *   Option routines for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  *
  * Contents:
  *
- *   cupsAddOption()    - Add an option to an option array.
- *   cupsFreeOptions()  - Free all memory used by options.
- *   cupsGetOption()    - Get an option value.
- *   cupsParseOptions() - Parse options from a command-line argument.
- *   cupsRemoveOption() - Remove an option from an option array.
+ *   cupsAddOption()        - Add an option to an option array.
+ *   cupsFreeOptions()      - Free all memory used by options.
+ *   cupsGetOption()        - Get an option value.
+ *   cupsParseOptions()     - Parse options from a command-line argument.
+ *   cupsRemoveOption()     - Remove an option from an option array.
+ *   _cupsGet1284Values()   - Get 1284 device ID keys and values.
+ *   cups_compare_options() - Compare two options.
+ *   cups_find_option()     - Find an option using a binary search.
  */
 
 /*
@@ -500,6 +503,89 @@ cupsRemoveOption(
 }
 
 
+/*
+ * '_cupsGet1284Values()' - Get 1284 device ID keys and values.
+ *
+ * The returned dictionary is a CUPS option array that can be queried with
+ * cupsGetOption and freed with cupsFreeOptions.
+ */
+
+int                                    /* O - Number of key/value pairs */
+_cupsGet1284Values(
+    const char *device_id,             /* I - IEEE-1284 device ID string */
+    cups_option_t **values)            /* O - Array of key/value pairs */
+{
+  int          num_values;             /* Number of values */
+  char         key[256],               /* Key string */
+               value[256],             /* Value string */
+               *ptr;                   /* Pointer into key/value */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (values)
+    *values = NULL;
+
+  if (!device_id || !values)
+    return (0);
+
+ /*
+  * Parse the 1284 device ID value into keys and values.  The format is
+  * repeating sequences of:
+  *
+  *   [whitespace]key:value[whitespace];
+  */
+
+  num_values = 0;
+  while (*device_id)
+  {
+    while (isspace(*device_id & 255))
+      device_id ++;
+
+    if (!*device_id)
+      break;
+
+    for (ptr = key; *device_id && *device_id != ':'; device_id ++)
+      if (ptr < (key + sizeof(key) - 1))
+        *ptr++ = *device_id;
+
+    if (!*device_id)
+      break;
+
+    while (ptr > key && isspace(ptr[-1] & 255))
+      ptr --;
+
+    *ptr = '\0';
+    device_id ++;
+
+    while (isspace(*device_id & 255))
+      device_id ++;
+
+    if (!*device_id)
+      break;
+
+    for (ptr = value; *device_id && *device_id != ';'; device_id ++)
+      if (ptr < (value + sizeof(value) - 1))
+        *ptr++ = *device_id;
+
+    if (!*device_id)
+      break;
+
+    while (ptr > value && isspace(ptr[-1] & 255))
+      ptr --;
+
+    *ptr = '\0';
+    device_id ++;
+
+    num_values = cupsAddOption(key, value, num_values, values);
+  }
+
+  return (num_values);
+}
+
+
 /*
  * 'cups_compare_options()' - Compare two options.
  */
index 34f0a02d7a4dd9c6e4cbac01cea33e1099215cec..71817b6136285ff68371a59e4ac31998706ff697 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Page size functions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -250,6 +250,9 @@ ppdPageSizeLimits(ppd_file_t *ppd,  /* I - PPD file record */
   * Figure out the current minimum width and length...
   */
 
+  width  = ppd->custom_min[0];
+  length = ppd->custom_min[1];
+
   if (qualifier2)
   {
    /*
@@ -284,11 +287,6 @@ ppdPageSizeLimits(ppd_file_t *ppd, /* I - PPD file record */
       length = ppd->custom_min[1];
     }
   }
-  else
-  {
-    width  = ppd->custom_min[0];
-    length = ppd->custom_min[1];
-  }
 
   minimum->width  = width;
   minimum->length = length;
@@ -301,6 +299,9 @@ ppdPageSizeLimits(ppd_file_t *ppd,  /* I - PPD file record */
   * Figure out the current maximum width and length...
   */
 
+  width  = ppd->custom_max[0];
+  length = ppd->custom_max[1];
+
   if (qualifier2)
   {
    /*
@@ -335,11 +336,6 @@ ppdPageSizeLimits(ppd_file_t *ppd, /* I - PPD file record */
       length = ppd->custom_max[1];
     }
   }
-  else
-  {
-    width  = ppd->custom_max[0];
-    length = ppd->custom_max[1];
-  }
 
   maximum->width  = width;
   maximum->length = length;
index fa33e96c6ad1b27f60a93df1c91ff082e16a45f6..7b647b511da547647fb8449b439b45c859aab32e 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id$"
  *
- *   Private PPD definitions for the Common UNIX Printing System (CUPS).
+ *   Private PPD definitions for CUPS.
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -68,8 +68,6 @@ typedef struct _ppd_cups_uiconsts_s   /**** cupsUIConstraints ****/
  */
 
 extern void            _ppdFreeLanguages(cups_array_t *languages);
-extern int             _ppdGet1284Values(const char *device_id,
-                                         cups_option_t **values);
 extern cups_encoding_t _ppdGetEncoding(const char *name);
 extern cups_array_t    *_ppdGetLanguages(ppd_file_t *ppd);
 extern unsigned                _ppdHashName(const char *name);
index 6a781bb710453f1aead83687613437971d7a0d00..1503b4f7da9d1a7bbd23fddfdeb9d4bef46c4b29 100644 (file)
@@ -118,8 +118,8 @@ cupsTempFd(char *filename,          /* I - Pointer to buffer */
     * Format a string using the hex time values...
     */
 
-    snprintf(filename, len - 1, "%s/%05x%08lx", tmpdir, (unsigned)getpid(),
-             (unsigned long)(curtime.tv_sec + curtime.tv_usec + tries));
+    snprintf(filename, len - 1, "%s/%05x%08x", tmpdir, (unsigned)getpid(),
+             (unsigned)(curtime.tv_sec + curtime.tv_usec + tries));
 #endif /* WIN32 */
 
    /*
diff --git a/data/HPGLprolog b/data/HPGLprolog
deleted file mode 100644 (file)
index 2ebf985..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-%%BeginResource: procset hpgltops 1.1 0
-%
-% "$Id: HPGLprolog 6649 2007-07-11 21:46:42Z mike $"
-%
-%   HP-GL/2 filter procset for the Common UNIX Printing System (CUPS).
-%
-%   This procset contains the basic drawing commands that are used to
-%   reduce output size.  Note the 'MP' (make newpath) definition - this
-%   should be called 'NP' (newpath), but GhostScript uses the 'NP' name
-%   for 'noaccess put' in some of its font files...
-%
-%   Copyright 2007 by Apple Inc.
-%   Copyright 1993-2005 by Easy Software Products
-%
-%   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 is included with the CUPS source distribution.
-%
-/MO { moveto } bind def
-/LI { lineto } bind def
-/FI { fill } bind def
-/ST { stroke } bind def
-/CP { closepath } bind def
-/MP { newpath } bind def
-/SP { setlinewidth setrgbcolor } bind def
-%%EndResource
index e518c8f015f0c24048fe328b5408612fc75617a3..504d2e5fdbf40fbe5c06cd3bc2a5087a8fdc3109 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Datafile makefile for the Common UNIX Printing System (CUPS).
 #
-#   Copyright 2007-2008 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1993-2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -71,7 +71,6 @@ CHARSETS =    \
                utf-8
 
 DATAFILES =    \
-               HPGLprolog \
                psglyphs \
                testprint
 
index 6b3384bbc22e363962beb40d3f78af57e233c88f..4f1089a1726b7c139b21ad93eb4fbc2958216f6b 100644 (file)
@@ -945,25 +945,6 @@ of authentication to use for IPP operations that require a
 username. The default is <CODE>Basic</CODE>.</P>
 
 
-<H2 CLASS="title"><A NAME="DefaultCharset">DefaultCharset</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-DefaultCharset utf-8
-DefaultCharset iso-8859-1
-DefaultCharset windows-1251
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>DefaultCharset</CODE> directive sets the default
-character set to use for client connections. The default
-character set is <CODE>utf-8</CODE> but is overridden by the
-character set for the language specified by the client or the
-<CODE>DefaultLanguage</CODE> directive.</P>
-
-
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="DefaultEncryption">DefaultEncryption</A></H2>
 
 <H3>Examples</H3>
index a0ec7a0e2ec4f429d2ac5fbe11ccbc6a917c2196..076cc4b9c69e7ba608514d64eeb7ed4edc8bc442 100644 (file)
@@ -45,10 +45,10 @@ the page started printing. The format of this field is identical
 to the <I>data-time</I> field in the <VAR>access_log</VAR>
 file.</P>
 
-<P>The <I>page-number</I> and <I>num-pages</I> fields contain the
+<P>The <I>page-number</I> and <I>num-copies</I> fields contain the
 page number and number of copies being printed of that page. For
 printers that cannot produce copies on their own, the
-<I>num-pages</I> field will always be 1.</P>
+<I>num-copies</I> field will always be 1.</P>
 
 <P>The <I>job-billing</I> field contains a copy of the
 <CODE>job-billing</CODE> attribute provided with the IPP
index 23e22940722b04addebcbb0d532876f50061e13b..ab9a1329c168f6f859df81a457f2fd2d7f499859 100644 (file)
@@ -103,13 +103,11 @@ diff -urN olddirectory directory >filename.patch
 in their entirety, however that may delay the adoption of your
 changes.</P>
 
-<BLOCKQUOTE>Patches and files must conform to the standards
-outlined in the "<A HREF="#CODING">Coding Guidelines</A>" and "<A
-HREF="#MAKEFILES">Makefile Guidelines</A>" sections in this
-document. In addition, since Apple Inc. provides CUPS
-under multiple licenses, we require that you assign the copyright
-for your changes and files to us for inclusion in
-CUPS.</BLOCKQUOTE>
+<BLOCKQUOTE>Patches and files must conform to the standards outlined in the
+"<A HREF="#CODING">Coding Guidelines</A>" and "<A HREF="#MAKEFILES">Makefile
+Guidelines</A>" sections in this document. In addition, since Apple Inc.
+provides CUPS under multiple licenses, we require that you assign the copyright
+for your changes and files to us for inclusion in CUPS.</BLOCKQUOTE>
 
 
 <H2 CLASS="title"><A NAME="PRACTICES">Software Development Practices</A></H2>
@@ -151,51 +149,45 @@ MAJOR.MINOR.PATCH
 2.0.0
 </PRE>
 
-<P>The first production release in a MAJOR.MINOR series
-(MAJOR.MINOR.0) is called a feature release. Feature releases are
-the only releases that may contain new features. Subsequent
-production releases in a MAJOR.MINOR series may only contain bug
-fixes.</P>
+<P>The first production release in a MAJOR.MINOR series (MAJOR.MINOR.0) is
+called a feature release. Feature releases are the only releases that may
+contain new features. Subsequent production releases in a MAJOR.MINOR series may
+only contain bug fixes.</P>
 
-<BLOCKQUOTE>We did not hold to this limitation in the CUPS 1.1
-series for a variety of reasons. Starting with CUPS 1.2, the "no
-new features in a patch release" policy will be strictly
-enforced. This should yield more frequent minor releases with
-fewer new features (and interactions!) to
-validate/test.</BLOCKQUOTE>
+<BLOCKQUOTE>We did not hold to this limitation in the CUPS 1.1 series for a
+variety of reasons. Starting with CUPS 1.2, the "no new features in a patch
+release" policy has been strictly enforced. The policy has also resulted in
+fewer new features (and interactions!) to validate/test in the subsequence
+feature releases.</BLOCKQUOTE>
 
-<P>Beta-test releases are identified by appending the letter B
-to the major and minor version numbers followed by the beta
-release number:</P>
+<P>Beta-test releases are identified by appending the letter B to the major and
+minor version numbers followed by the beta release number:</P>
 
 <PRE CLASS="command">
 MAJOR.MINORbNUMBER
 1.2b1
 </PRE>
 
-<P>Release candidates are identified by appending the letters RC
-to the major and minor version numbers followed by the release
-candidate number:</P>
+<P>Release candidates are identified by appending the letters RC to the major
+and minor version numbers followed by the release candidate number:</P>
 
 <PRE CLASS="command">
 MAJOR.MINORrcNUMBER
 1.2rc1
 </PRE>
 
-<P>Developer snapshots are identified by appending the letters
-SVN-R to the major and minor version numbers followed by the
-revision number:</P>
+<P>Developer snapshots are identified by appending the letters SVN-R to the
+major and minor version numbers followed by the revision number:</P>
 
 <PRE CLASS="command">
 MAJOR.MINORsvn-rREV
 1.2svn-r1234
 </PRE>
 
-<P>Beta-test releases, release candidates, and developer
-snapshots are only created for new minor releases. Once a
-production release has been made (MAJOR.MINOR.0), subsequent
-patch releases are issues without preliminary beta or release
-testing.</P>
+<P>Beta-test releases, release candidates, and developer snapshots are only
+created for new minor releases. Once a production release has been made
+(MAJOR.MINOR.0), subsequent patch releases are issues without preliminary beta
+or release testing.</P>
 
 <H3>Version Control (Subversion)</H3>
 
@@ -212,16 +204,9 @@ applicable STRs. The following format <em>must</em> be used for
 commit log messages:</P>
 
 <PRE CLASS="command">
-Summary of the change ("fix PostScript printing bug") along
-with corresponding STRs ("STR #1, STR #6")
+Summary of the change on one line followed by bug number (STR #NNNN)
 
-foo.cxx:
-    - function(): Detailed list of changes
-    - function2(): Detailed list of changes
-    - Summary of design changes ("added new foo struct")
-
-bar.h:
-    - More detailed changes
+Detailed list of changes.
 </PRE>
 
 <P>Primary development occurs on the <var>trunk</var> branch,
@@ -625,7 +610,7 @@ the Subversion "&#36;Id$" tag:</P>
  *
  *   Description of file contents.
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2010 by Apple Inc.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Apple Inc. and are protected by Federal copyright
@@ -703,13 +688,15 @@ special text in the function description comment:</P>
 
 <UL>
 
-       <LI><CODE>@since CUPS <I>version</I>@</CODE> - Marks the
-       function as new in the specified version of CUPS.</LI>
-
        <LI><CODE>@deprecated@</CODE> - Marks the function as
        deprecated (not recommended for new development and
        scheduled for removal)</LI>
 
+       <LI><CODE>@since CUPS <I>version</I>@</CODE> - Marks the
+       function as new in the specified version of CUPS.</LI>
+
+       <LI><CODE>@private@</CODE> - Marks the function as private.</LI>
+
 </UL>
 
 <H3>Variables</H3>
index 2111f79f0e0e3fb80bb6d9e28a0391df2b6afc1b..ed31ab6c7573090b94be3b4bb21d20f0d0847cd8 100644 (file)
@@ -44,7 +44,7 @@ cmyk.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 cmyk.o: ../cups/language.h ../cups/raster.h ../cups/string.h ../config.h
 dither.o: driver.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 dither.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-dither.o: ../cups/language.h ../cups/raster.h
+dither.o: ../cups/language.h ../cups/raster.h ../config.h
 lut.o: driver.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 lut.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 lut.o: ../cups/language.h ../cups/raster.h
index dcfef5556ff0d2c851f401057d12e4a48e9afa27..8f017ace1d45922829fdf492982c39c1f9a017b1 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Makefile for the CUPS base drivers.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 2002-2005 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -51,12 +51,14 @@ UNITTARGETS =       \
                testcmyk \
                testdither \
                testrgb
-TARGETS =      \
-               $(LIBTARGETS) \
+FILTERS =      \
                commandtoescpx \
                commandtopclx \
                rastertoescpx \
                rastertopclx
+TARGETS =      \
+               $(LIBTARGETS) \
+               $(FILTERS)
 
 
 #
@@ -120,12 +122,12 @@ install-data:
 
 install-exec:
        $(INSTALL_DIR) $(SERVERBIN)/filter
-       for file in commandtoescpx commandtopclx rastertoescpx rastertopclx; do \
+       for file in $(FILTERS); do \
                $(INSTALL_BIN) $$file $(SERVERBIN)/filter; \
        done
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               for file in commandtoescpx commandtopclx rastertoescpx rastertopclx; do \
+               for file in $(FILTERS); do \
                        cp $$file $(SYMROOT); \
                done \
        fi
index a50962a1a17aa6097b88affbdfdafcb00297e4b2..59fc5065dd11193c42b251fc473ab0ea86b8e28b 100644 (file)
@@ -1,37 +1,5 @@
 # DO NOT DELETE
 
-hpgl-attr.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-attr.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-attr.o: ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-attr.o: ../cups/string.h ../config.h
-hpgl-config.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-config.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-config.o: ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-config.o: ../cups/language.h ../cups/string.h ../config.h
-hpgl-main.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-main.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-main.o: ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-main.o: ../cups/string.h ../config.h ../cups/i18n.h ../cups/transcode.h
-hpgl-prolog.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-prolog.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-prolog.o: ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-prolog.o: ../cups/language.h ../cups/string.h ../config.h
-hpgl-char.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-char.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-char.o: ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-char.o: ../cups/string.h ../config.h
-hpgl-input.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-input.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-input.o: ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-input.o: ../cups/string.h ../config.h ../cups/i18n.h ../cups/transcode.h
-hpgl-polygon.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-polygon.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-polygon.o: ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-polygon.o: ../cups/language.h ../cups/string.h ../config.h
-hpgl-vector.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-vector.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-vector.o: ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-vector.o: ../cups/language.h ../cups/string.h ../config.h
 image-bmp.o: image-private.h image.h ../cups/raster.h ../cups/cups.h
 image-bmp.o: ../cups/ipp.h ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 image-bmp.o: ../cups/array.h ../cups/file.h ../cups/language.h
@@ -99,17 +67,6 @@ raster.o: image-private.h image.h ../cups/raster.h ../cups/cups.h
 raster.o: ../cups/ipp.h ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 raster.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h
 raster.o: ../cups/string.h ../config.h
-form-main.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-main.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-form-main.o: ../cups/file.h ../cups/language.h ../cups/language.h
-form-main.o: ../cups/string.h ../config.h
-form-ps.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-ps.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-form-ps.o: ../cups/language.h ../cups/language.h ../cups/string.h ../config.h
-form-tree.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-tree.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-form-tree.o: ../cups/file.h ../cups/language.h ../cups/language.h
-form-tree.o: ../cups/string.h ../config.h
 bannertops.o: pstext.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 bannertops.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 bannertops.o: ../cups/file.h ../cups/language.h ../cups/language.h
@@ -120,8 +77,7 @@ commandtops.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 commandtops.o: ../cups/file.h ../cups/language.h ../cups/string.h ../config.h
 commandtops.o: ../cups/sidechannel.h
 gziptoany.o: ../cups/file.h ../cups/versioning.h ../cups/string.h ../config.h
-gziptoany.o: ../cups/i18n.h ../cups/transcode.h ../cups/language.h
-gziptoany.o: ../cups/array.h
+gziptoany.o: ../cups/i18n.h ../cups/transcode.h
 imagetops.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 imagetops.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 imagetops.o: ../cups/file.h ../cups/language.h ../cups/language.h
@@ -147,9 +103,9 @@ pstops.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 pstops.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 pstops.o: ../cups/language.h ../cups/language.h ../cups/string.h ../config.h
 pstops.o: ../cups/file.h ../cups/array.h ../cups/i18n.h ../cups/transcode.h
-rasterbench.o: ../cups/raster.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-rasterbench.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-rasterbench.o: ../cups/file.h ../cups/language.h
+rasterbench.o: ../config.h ../cups/raster.h ../cups/cups.h ../cups/ipp.h
+rasterbench.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
+rasterbench.o: ../cups/array.h ../cups/file.h ../cups/language.h
 rastertoepson.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h
 rastertoepson.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 rastertoepson.o: ../cups/file.h ../cups/language.h ../cups/ppd.h
@@ -182,38 +138,6 @@ texttops.o: ../cups/language.h ../cups/language.h ../cups/string.h
 texttops.o: ../config.h ../cups/i18n.h ../cups/transcode.h
 # DO NOT DELETE
 
-hpgl-attr.32.o: hpgl-attr.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-attr.32.o: hpgl-attr.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-attr.32.o: hpgl-attr.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-attr.32.o: hpgl-attr.c  ../cups/string.h ../config.h
-hpgl-config.32.o: hpgl-config.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-config.32.o: hpgl-config.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-config.32.o: hpgl-config.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-config.32.o: hpgl-config.c  ../cups/language.h ../cups/string.h ../config.h
-hpgl-main.32.o: hpgl-main.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-main.32.o: hpgl-main.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-main.32.o: hpgl-main.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-main.32.o: hpgl-main.c  ../cups/string.h ../config.h ../cups/i18n.h ../cups/transcode.h
-hpgl-prolog.32.o: hpgl-prolog.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-prolog.32.o: hpgl-prolog.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-prolog.32.o: hpgl-prolog.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-prolog.32.o: hpgl-prolog.c  ../cups/language.h ../cups/string.h ../config.h
-hpgl-char.32.o: hpgl-char.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-char.32.o: hpgl-char.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-char.32.o: hpgl-char.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-char.32.o: hpgl-char.c  ../cups/string.h ../config.h
-hpgl-input.32.o: hpgl-input.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-input.32.o: hpgl-input.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-input.32.o: hpgl-input.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-input.32.o: hpgl-input.c  ../cups/string.h ../config.h ../cups/i18n.h ../cups/transcode.h
-hpgl-polygon.32.o: hpgl-polygon.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-polygon.32.o: hpgl-polygon.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-polygon.32.o: hpgl-polygon.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-polygon.32.o: hpgl-polygon.c  ../cups/language.h ../cups/string.h ../config.h
-hpgl-vector.32.o: hpgl-vector.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-vector.32.o: hpgl-vector.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-vector.32.o: hpgl-vector.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-vector.32.o: hpgl-vector.c  ../cups/language.h ../cups/string.h ../config.h
 image-bmp.32.o: image-bmp.c  image-private.h image.h ../cups/raster.h ../cups/cups.h
 image-bmp.32.o: image-bmp.c  ../cups/ipp.h ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 image-bmp.32.o: image-bmp.c  ../cups/array.h ../cups/file.h ../cups/language.h
@@ -281,17 +205,6 @@ raster.32.o: raster.c  image-private.h image.h ../cups/raster.h ../cups/cups.h
 raster.32.o: raster.c  ../cups/ipp.h ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 raster.32.o: raster.c  ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h
 raster.32.o: raster.c  ../cups/string.h ../config.h
-form-main.32.o: form-main.c  form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-main.32.o: form-main.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-form-main.32.o: form-main.c  ../cups/file.h ../cups/language.h ../cups/language.h
-form-main.32.o: form-main.c  ../cups/string.h ../config.h
-form-ps.32.o: form-ps.c  form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-ps.32.o: form-ps.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-form-ps.32.o: form-ps.c  ../cups/language.h ../cups/language.h ../cups/string.h ../config.h
-form-tree.32.o: form-tree.c  form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-tree.32.o: form-tree.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-form-tree.32.o: form-tree.c  ../cups/file.h ../cups/language.h ../cups/language.h
-form-tree.32.o: form-tree.c  ../cups/string.h ../config.h
 bannertops.32.o: bannertops.c  pstext.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 bannertops.32.o: bannertops.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 bannertops.32.o: bannertops.c  ../cups/file.h ../cups/language.h ../cups/language.h
@@ -302,8 +215,7 @@ commandtops.32.o: commandtops.c  ../cups/versioning.h ../cups/ppd.h ../cups/arra
 commandtops.32.o: commandtops.c  ../cups/file.h ../cups/language.h ../cups/string.h ../config.h
 commandtops.32.o: commandtops.c  ../cups/sidechannel.h
 gziptoany.32.o: gziptoany.c  ../cups/file.h ../cups/versioning.h ../cups/string.h ../config.h
-gziptoany.32.o: gziptoany.c  ../cups/i18n.h ../cups/transcode.h ../cups/language.h
-gziptoany.32.o: gziptoany.c  ../cups/array.h
+gziptoany.32.o: gziptoany.c  ../cups/i18n.h ../cups/transcode.h
 imagetops.32.o: imagetops.c  common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 imagetops.32.o: imagetops.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 imagetops.32.o: imagetops.c  ../cups/file.h ../cups/language.h ../cups/language.h
@@ -329,9 +241,9 @@ pstops.32.o: pstops.c  common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 pstops.32.o: pstops.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 pstops.32.o: pstops.c  ../cups/language.h ../cups/language.h ../cups/string.h ../config.h
 pstops.32.o: pstops.c  ../cups/file.h ../cups/array.h ../cups/i18n.h ../cups/transcode.h
-rasterbench.32.o: rasterbench.c  ../cups/raster.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-rasterbench.32.o: rasterbench.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-rasterbench.32.o: rasterbench.c  ../cups/file.h ../cups/language.h
+rasterbench.32.o: rasterbench.c  ../config.h ../cups/raster.h ../cups/cups.h ../cups/ipp.h
+rasterbench.32.o: rasterbench.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
+rasterbench.32.o: rasterbench.c  ../cups/array.h ../cups/file.h ../cups/language.h
 rastertoepson.32.o: rastertoepson.c  ../cups/cups.h ../cups/ipp.h ../cups/http.h
 rastertoepson.32.o: rastertoepson.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 rastertoepson.32.o: rastertoepson.c  ../cups/file.h ../cups/language.h ../cups/ppd.h
@@ -364,38 +276,6 @@ texttops.32.o: texttops.c  ../cups/language.h ../cups/language.h ../cups/string.
 texttops.32.o: texttops.c  ../config.h ../cups/i18n.h ../cups/transcode.h
 # DO NOT DELETE
 
-hpgl-attr.64.o: hpgl-attr.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-attr.64.o: hpgl-attr.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-attr.64.o: hpgl-attr.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-attr.64.o: hpgl-attr.c  ../cups/string.h ../config.h
-hpgl-config.64.o: hpgl-config.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-config.64.o: hpgl-config.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-config.64.o: hpgl-config.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-config.64.o: hpgl-config.c  ../cups/language.h ../cups/string.h ../config.h
-hpgl-main.64.o: hpgl-main.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-main.64.o: hpgl-main.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-main.64.o: hpgl-main.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-main.64.o: hpgl-main.c  ../cups/string.h ../config.h ../cups/i18n.h ../cups/transcode.h
-hpgl-prolog.64.o: hpgl-prolog.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-prolog.64.o: hpgl-prolog.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-prolog.64.o: hpgl-prolog.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-prolog.64.o: hpgl-prolog.c  ../cups/language.h ../cups/string.h ../config.h
-hpgl-char.64.o: hpgl-char.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-char.64.o: hpgl-char.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-char.64.o: hpgl-char.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-char.64.o: hpgl-char.c  ../cups/string.h ../config.h
-hpgl-input.64.o: hpgl-input.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-hpgl-input.64.o: hpgl-input.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-hpgl-input.64.o: hpgl-input.c  ../cups/file.h ../cups/language.h ../cups/language.h
-hpgl-input.64.o: hpgl-input.c  ../cups/string.h ../config.h ../cups/i18n.h ../cups/transcode.h
-hpgl-polygon.64.o: hpgl-polygon.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-polygon.64.o: hpgl-polygon.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-polygon.64.o: hpgl-polygon.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-polygon.64.o: hpgl-polygon.c  ../cups/language.h ../cups/string.h ../config.h
-hpgl-vector.64.o: hpgl-vector.c  hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
-hpgl-vector.64.o: hpgl-vector.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-hpgl-vector.64.o: hpgl-vector.c  ../cups/array.h ../cups/file.h ../cups/language.h
-hpgl-vector.64.o: hpgl-vector.c  ../cups/language.h ../cups/string.h ../config.h
 image-bmp.64.o: image-bmp.c  image-private.h image.h ../cups/raster.h ../cups/cups.h
 image-bmp.64.o: image-bmp.c  ../cups/ipp.h ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 image-bmp.64.o: image-bmp.c  ../cups/array.h ../cups/file.h ../cups/language.h
@@ -463,17 +343,6 @@ raster.64.o: raster.c  image-private.h image.h ../cups/raster.h ../cups/cups.h
 raster.64.o: raster.c  ../cups/ipp.h ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 raster.64.o: raster.c  ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h
 raster.64.o: raster.c  ../cups/string.h ../config.h
-form-main.64.o: form-main.c  form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-main.64.o: form-main.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-form-main.64.o: form-main.c  ../cups/file.h ../cups/language.h ../cups/language.h
-form-main.64.o: form-main.c  ../cups/string.h ../config.h
-form-ps.64.o: form-ps.c  form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-ps.64.o: form-ps.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-form-ps.64.o: form-ps.c  ../cups/language.h ../cups/language.h ../cups/string.h ../config.h
-form-tree.64.o: form-tree.c  form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-form-tree.64.o: form-tree.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-form-tree.64.o: form-tree.c  ../cups/file.h ../cups/language.h ../cups/language.h
-form-tree.64.o: form-tree.c  ../cups/string.h ../config.h
 bannertops.64.o: bannertops.c  pstext.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 bannertops.64.o: bannertops.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 bannertops.64.o: bannertops.c  ../cups/file.h ../cups/language.h ../cups/language.h
@@ -484,8 +353,7 @@ commandtops.64.o: commandtops.c  ../cups/versioning.h ../cups/ppd.h ../cups/arra
 commandtops.64.o: commandtops.c  ../cups/file.h ../cups/language.h ../cups/string.h ../config.h
 commandtops.64.o: commandtops.c  ../cups/sidechannel.h
 gziptoany.64.o: gziptoany.c  ../cups/file.h ../cups/versioning.h ../cups/string.h ../config.h
-gziptoany.64.o: gziptoany.c  ../cups/i18n.h ../cups/transcode.h ../cups/language.h
-gziptoany.64.o: gziptoany.c  ../cups/array.h
+gziptoany.64.o: gziptoany.c  ../cups/i18n.h ../cups/transcode.h
 imagetops.64.o: imagetops.c  common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 imagetops.64.o: imagetops.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 imagetops.64.o: imagetops.c  ../cups/file.h ../cups/language.h ../cups/language.h
@@ -511,9 +379,9 @@ pstops.64.o: pstops.c  common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 pstops.64.o: pstops.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
 pstops.64.o: pstops.c  ../cups/language.h ../cups/language.h ../cups/string.h ../config.h
 pstops.64.o: pstops.c  ../cups/file.h ../cups/array.h ../cups/i18n.h ../cups/transcode.h
-rasterbench.64.o: rasterbench.c  ../cups/raster.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-rasterbench.64.o: rasterbench.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-rasterbench.64.o: rasterbench.c  ../cups/file.h ../cups/language.h
+rasterbench.64.o: rasterbench.c  ../config.h ../cups/raster.h ../cups/cups.h ../cups/ipp.h
+rasterbench.64.o: rasterbench.c  ../cups/http.h ../cups/versioning.h ../cups/ppd.h
+rasterbench.64.o: rasterbench.c  ../cups/array.h ../cups/file.h ../cups/language.h
 rastertoepson.64.o: rastertoepson.c  ../cups/cups.h ../cups/ipp.h ../cups/http.h
 rastertoepson.64.o: rastertoepson.c  ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 rastertoepson.64.o: rastertoepson.c  ../cups/file.h ../cups/language.h ../cups/ppd.h
index 6e2e96bd1d0b656e0e14011b189f891f03a2ee93..184b3072dab81bb16900ee7967f8c329618c787e 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Filter makefile for the Common UNIX Printing System (CUPS).
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -22,7 +22,6 @@ FILTERS       =       \
                $(BANNERTOPS) \
                commandtops \
                gziptoany \
-               hpgltops \
                $(TEXTTOPS) \
                pstops \
                $(IMGFILTERS) \
@@ -43,16 +42,13 @@ TARGETS     =       \
                $(LIBTARGETS) \
                $(FILTERS)
 
-HPGLOBJS =     hpgl-attr.o hpgl-config.o hpgl-main.o hpgl-prolog.o \
-               hpgl-char.o hpgl-input.o hpgl-polygon.o hpgl-vector.o
 IMAGEOBJS =    image-bmp.o image-colorspace.o image-gif.o image-jpeg.o \
                image-photocd.o image-pix.o image-png.o image-pnm.o \
                image-sgi.o image-sgilib.o image-sun.o image-tiff.o \
                image-zoom.o image.o error.o interpret.o raster.o
 IMAGE32OBJS =  $(IMAGEOBJS:.o=.32.o)
 IMAGE64OBJS =  $(IMAGEOBJS:.o=.64.o)
-FORMOBJS =     form-attr.o form-main.o form-ps.o form-text.o form-tree.o
-OBJS   =       $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \
+OBJS   =       $(IMAGEOBJS) \
                bannertops.o commandtops.o gziptoany.o imagetops.o \
                imagetoraster.o common.o pdftops.o pstext.o pstops.o \
                rasterbench.o rastertoepson.o rastertohp.o rastertolabel.o \
@@ -131,7 +127,7 @@ install-exec:
        $(LN) rastertolabel $(SERVERBIN)/filter/rastertodymo
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               for file in $(TARGETS); do \
+               for file in $(FILTERS); do \
                        cp $$file $(SYMROOT); \
                done \
        fi
@@ -161,6 +157,10 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64)
                $(RM) $(LIBDIR)/libcupsimage.dylib; \
                $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/libcupsimage.dylib; \
        fi
+       if test "x$(SYMROOT)" != "x"; then \
+               $(INSTALL_DIR) $(SYMROOT); \
+               cp $(LIBCUPSIMAGE) $(SYMROOT); \
+       fi
 
 installstatic:
        $(INSTALL_DIR) -m 755 $(LIBDIR)
@@ -292,15 +292,6 @@ commandtops:       commandtops.o ../cups/$(LIBCUPS)
        $(CC) $(LDFLAGS) -o $@ commandtops.o $(LIBS)
 
 
-#
-# formtops
-#
-
-formtops:      $(FORMOBJS) common.o ../cups/$(LIBCUPS)
-       echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ $(FORMOBJS) common.o $(LIBS) -lm
-
-
 #
 # gziptoany
 #
@@ -310,15 +301,6 @@ gziptoany: gziptoany.o ../Makedefs ../cups/$(LIBCUPS)
        $(CC) $(LDFLAGS) -o $@ gziptoany.o $(LIBZ) $(LIBS)
 
 
-#
-# hpgltops
-#
-
-hpgltops:      $(HPGLOBJS) common.o ../cups/$(LIBCUPS)
-       echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ $(HPGLOBJS) common.o $(LIBS) -lm
-
-
 #
 # libcupsimage.so.2, libcupsimage.sl.2
 #
diff --git a/filter/form-main.c b/filter/form-main.c
deleted file mode 100644 (file)
index 0f4ff1b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * "$Id: form-main.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   CUPS form main entry for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1997-2005 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   main() - Load the specified form file and output PostScript.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "form.h"
-
-
-/*
- * Globals...
- */
-
-int            NumOptions;     /* Number of command-line options */
-cups_option_t  *Options;       /* Command-line options */
-ppd_file_t     *PPD;           /* PPD file */
-
-
-/*
- * 'main()' - Load the specified form file and output PostScript.
- */
-
-int                            /* O - Exit status */
-main(int  argc,                        /* I - Number of command-line arguments */
-     char *argv[])             /* I - Command-line arguments */
-{
-
-  return (0);
-}
-
-
-/*
- * End of "$Id: form-main.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/form-ps.c b/filter/form-ps.c
deleted file mode 100644 (file)
index 6a1e1e3..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * "$Id: form-ps.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   CUPS form PostScript routines for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1997-2005 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "form.h"
-
-
-/*
- * 'formWrite()' - Write PostScript output for the given form document.
- */
-
-void
-formWrite(tree_t *t)                   /* I - Document tree to write */
-{
-}
-
-
-/*
- * End of "$Id: form-ps.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/form-tree.c b/filter/form-tree.c
deleted file mode 100644 (file)
index 337924d..0000000
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * "$Id: form-tree.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   CUPS form document tree routines for the Common UNIX Printing
- *   System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1997-2005 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "form.h"
-
-
-/*
- * Local functions...
- */
-
-static int     compare_attr(attr_t *a0, attr_t *a1);
-static int     compare_elements(char **e0, char **e1);
-static int     parse_attr(tree_t *t, FILE *fp);
-static int     parse_element(tree_t *t, FILE *fp);
-
-
-/*
- * Local globals...
- */
-
-static char    *elements[] =
-               {
-                 "",
-                 "!--",
-                 "ARC",
-                 "BOX",
-                 "BR",
-                 "B",
-                 "CUPSFORM",
-                 "DEFVAR",
-                 "FONT",
-                 "H1",
-                 "H2",
-                 "H3",
-                 "H4",
-                 "H5",
-                 "H6",
-                 "HEAD",
-                 "IMG",
-                 "I",
-                 "LINE",
-                 "PAGE",
-                 "PIE",
-                 "POLY",
-                 "PRE",
-                 "P",
-                 "RECT",
-                 "TEXT",
-                 "TT",
-                 "VAR"
-               };
-
-
-/*
- * 'formDelete()' - Delete a node and its children.
- */
-
-void
-formDelete(tree_t *t)                  /* I - Tree node */
-{
-}
-
-
-/*
- * 'formGetAttr()' - Get a node attribute value.
- */
-
-char *                                 /* O - Value or NULL */
-formGetAttr(tree_t     *t,             /* I - Tree node */
-            const char *name)          /* I - Name of attribute */
-{
-}
-
-
-/*
- * 'formNew()' - Create a new form node.
- */
-
-tree_t *                               /* O - New tree node */
-formNew(tree_t    *p)                  /* I - Parent node */
-{
-  tree_t       *t;                     /* New tree node */
-
-
- /*
-  * Allocate the new node...
-  */
-
-  if ((t = (tree_t *)calloc(sizeof(tree_t), 1)) == NULL)
-    return (NULL);
-
- /*
-  * Set/copy attributes...
-  */
-
-  if (p == NULL)
-  {
-    t->bg[0]    = 1.0;
-    t->bg[1]    = 1.0;
-    t->bg[2]    = 1.0;
-    t->halign   = HALIGN_LEFT;
-    t->valign   = VALIGN_MIDDLE;
-    t->typeface = "Courier";
-    t->size     = 12.0;
-  }
-  else
-  {
-    memcpy(t, p, sizeof(tree_t));
-
-    t->prev       = NULL;
-    t->next       = NULL;
-    t->child      = NULL;
-    t->last_child = NULL;
-    t->parent     = NULL;
-    t->num_attrs  = 0;
-    t->attrs      = NULL;
-    t->data       = NULL;
-  }
-
- /*
-  * Return the new node...
-  */
-
-  return (t);
-}
-
-
-/*
- * 'formRead()' - Read a form tree from a file.
- */
-
-tree_t *                               /* O - New form tree */
-formRead(FILE   *fp,                   /* I - File to read from */
-         tree_t *p)                    /* I - Parent node */
-{
-  int          ch,                     /* Character from file */
-               closech,                /* Closing character */
-               have_whitespace;        /* Leading whitespace? */
-  static char  s[10240];               /* String from file */
-  uchar                *ptr,                   /* Pointer in string */
-               glyph[16],              /* Glyph name (&#nnn;) */
-               *glyphptr;              /* Pointer in glyph string */
-  tree_t       *tree,                  /* "top" of this tree */
-               *t,                     /* New tree node */
-               *prev,                  /* Previous tree node */
-               *temp;                  /* Temporary looping var */
-  uchar                *face,                  /* Typeface for FONT tag */
-               *color,                 /* Color for FONT tag */
-               *size;                  /* Size for FONT tag */
-
-
- /*
-  * Start off with no previous tree node...
-  */
-
-  prev = NULL;
-  tree = NULL;
-
- /*
-  * Parse data until we hit end-of-file...
-  */
-
-  while ((ch = getc(fp)) != EOF)
-  {
-   /*
-    * Ignore leading whitespace...
-    */
-
-    have_whitespace = 0;
-    closech         = '/';
-
-    if (p == NULL || !p->preformatted)
-    {
-      while (isspace(ch & 255))
-      {
-        have_whitespace = 1;
-        ch              = getc(fp);
-      }
-
-      if (ch == EOF)
-        break;
-    }
-
-   /*
-    * Allocate a new tree node - use calloc() to get zeroed data...
-    */
-
-    t = formNew(p);
-
-   /*
-    * See what the character was...
-    */
-
-    if (ch == '<')
-    {
-     /*
-      * Markup char; grab the next char to see if this is a /...
-      */
-
-      ch = getc(fp);
-      if (ch == ' ')
-      {
-       /*
-        * Illegal lone "<"!  Ignore it...
-       */
-
-       free(t);
-       continue;
-      }
-      
-      if (ch != '/')
-        ungetc(ch, fp);
-
-      if (parse_element(t, fp) < 0)
-      {
-        free(t);
-        break;
-      }
-
-      if ((closech = getc(fp)) == '/')
-        getc(fp);
-
-     /*
-      * If this is the matching close mark, or if we are starting the same
-      * element, or if we've completed a list, we're done!
-      */
-
-      if (ch == '/')
-      {
-       /*
-        * Close element; find matching element...
-        */
-
-        for (temp = p; temp != NULL; temp = temp->p)
-          if (temp->element == t->element)
-            break;
-
-        free(t);
-
-       if (temp != NULL)
-          break;
-       else
-         continue;
-      }
-    }
-    else if (t->preformatted)
-    {
-     /*
-      * Read a pre-formatted string into the current tree node...
-      */
-
-      ptr = s;
-      while (ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
-      {
-        if (ch == '&')
-        {
-          for (glyphptr = glyph;
-               (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
-               glyphptr ++)
-            if (!isalnum(ch & 255))
-              break;
-            else
-              *glyphptr = ch;
-
-          *glyphptr = '\0';
-         if (atoi(glyph) > 0)
-           ch = atoi(glyph);
-         else if (strcmp(glyph, "lt") == 0)
-           ch = '<';
-         else if (strcmp(glyph, "gt") == 0)
-           ch = '>';
-         else if (strcmp(glyph, "quot") == 0)
-           ch = '\'';
-         else if (strcmp(glyph, "nbsp") == 0)
-           ch = ' ';
-         else
-           ch = '&';
-        }
-
-        if (ch != 0)
-          *ptr++ = ch;
-
-        if (ch == '\n')
-          break;
-
-        ch = getc(fp);
-      }
-
-      *ptr = '\0';
-
-      if (ch == '<')
-        ungetc(ch, fp);
-
-      t->element = ELEMENT_FRAGMENT;
-      t->data    = strdup(s);
-    }
-    else
-    {
-     /*
-      * Read the next string fragment...
-      */
-
-      ptr = s;
-      if (have_whitespace)
-        *ptr++ = ' ';
-
-      while (!isspace(ch & 255) && ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
-      {
-        if (ch == '&')
-        {
-          for (glyphptr = glyph;
-               (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
-               glyphptr ++)
-            if (!isalnum(ch & 255))
-              break;
-            else
-              *glyphptr = ch;
-
-          *glyphptr = '\0';
-         if (atoi(glyph) > 0)
-           ch = atoi(glyph);
-         else if (strcmp(glyph, "lt") == 0)
-           ch = '<';
-         else if (strcmp(glyph, "gt") == 0)
-           ch = '>';
-         else if (strcmp(glyph, "quot") == 0)
-           ch = '\'';
-         else if (strcmp(glyph, "nbsp") == 0)
-           ch = ' ';
-         else
-           ch = '&';
-        }
-
-        if (ch != 0)
-          *ptr++ = ch;
-
-        ch = getc(fp);
-      }
-
-      if (isspace(ch & 255))
-        *ptr++ = ' ';
-
-      *ptr = '\0';
-
-      if (ch == '<')
-        ungetc(ch, fp);
-
-      t->element = ELEMENT_FRAGMENT;
-      t->data    = strdup(s);
-    }
-
-   /*
-    * If the p tree pointer is not NULL and this is the first
-    * entry we've read, set the child pointer...
-    */
-
-    if (p != NULL && prev == NULL)
-      p->child = t;
-
-    if (p != NULL)
-      p->last_child = t;
-
-   /*
-    * Do the prev/next links...
-    */
-
-    t->parent = p;
-    t->prev   = prev;
-    if (prev != NULL)
-      prev->next = t;
-    else
-      tree = t;
-
-    prev = t;
-
-   /*
-    * Do child stuff as needed...
-    */
-
-    if (closech == '>')
-      t->child = formRead(t, fp);
-  }  
-
-  return (tree);
-}
-
-
-/*
- * 'formSetAttr()' - Set a node attribute.
- */
-
-void
-formSetAttr(tree_t     *t,             /* I - Tree node */
-            const char *name,          /* I - Attribute name */
-           const char *value)          /* I - Attribute value */
-{
-}
-
-
-/*
- * 'compare_attr()' - Compare two attributes.
- */
-
-static int                             /* O - -1 if a0 < a1, etc. */
-compare_attr(attr_t *a0,               /* I - First attribute */
-             attr_t *a1)               /* I - Second attribute */
-{
-  return (strcasecmp(a0->name, a1->name));
-}
-
-
-/*
- * 'compare_elements()' - Compare two elements.
- */
-
-static int                             /* O - -1 if e0 < e1, etc. */
-compare_elements(char **e0,            /* I - First element */
-                 char **e1)            /* I - Second element */
-{
-  return (strcasecmp(*e0, *e1));
-}
-
-
-/*
- * 'parse_attr()' - Parse an element attribute string.
- */
-
-static int                             /* O - -1 on error, 0 on success */
-parse_attr(tree_t *t,                  /* I - Current tree node */
-           FILE   *fp)                 /* I - Input file */
-{
-  char name[1024],                     /* Name of attr */
-       value[10240],                   /* Value of attr */
-       *ptr;                           /* Temporary pointer */
-  int  ch;                             /* Character from file */
-
-
-  ptr = name;
-  while ((ch = getc(fp)) != EOF)
-    if (isalnum(ch & 255))
-    {
-      if (ptr < (name + sizeof(name) - 1))
-        *ptr++ = ch;
-    }
-    else
-      break;
-
-  *ptr = '\0';
-
-  while (isspace(ch & 255) || ch == '\r')
-    ch = getc(fp);
-
-  switch (ch)
-  {
-    default :
-        ungetc(ch, fp);
-        return (formSetAttr(t, name, NULL));
-    case EOF :
-        return (-1);
-    case '=' :
-        ptr = value;
-        ch  = getc(fp);
-
-        while (isspace(ch & 255) || ch == '\r')
-          ch = getc(fp);
-
-        if (ch == EOF)
-          return (-1);
-
-        if (ch == '\'')
-        {
-          while ((ch = getc(fp)) != EOF)
-            if (ch == '\'')
-              break;
-            else if (ptr < (value + sizeof(value) - 1))
-              *ptr++ = ch;
-
-          *ptr = '\0';
-        }
-        else if (ch == '\"')
-        {
-          while ((ch = getc(fp)) != EOF)
-            if (ch == '\"')
-              break;
-            else if (ptr < (value + sizeof(value) - 1))
-              *ptr++ = ch;
-
-          *ptr = '\0';
-        }
-        else
-        {
-          *ptr++ = ch;
-          while ((ch = getc(fp)) != EOF)
-            if (isspace(ch & 255) || ch == '>' || ch == '/' || ch == '\r')
-              break;
-            else if (ptr < (value + sizeof(value) - 1))
-              *ptr++ = ch;
-
-          *ptr = '\0';
-          if (ch == '>' || ch == '/')
-            ungetc(ch, fp);
-        }
-
-        return (formSetAttr(t, name, value));
-  }
-}
-
-
-/*
- * 'parse_element()' - Parse an element.
- */
-
-static int                             /* O - -1 on error or ELEMENT_nnnn */
-parse_element(tree_t *t,               /* I - Current tree node */
-              FILE   *fp)              /* I - Input file */
-{
-  int  ch;                             /* Character from file */
-  char element[255],                   /* Element string... */
-       *eptr,                          /* Current character... */
-       comment[10240],                 /* Comment string */
-       *cptr,                          /* Current char... */
-       **temp;                         /* Element variable entry */
-
-
-  eptr = element;
-
-  while ((ch = getc(fp)) != EOF && eptr < (element + sizeof(element) - 1))
-    if (ch == '>' || ch == '/' || isspace(ch & 255))
-      break;
-    else
-      *eptr++ = ch;
-
-  *eptr = '\0';
-
-  if (ch == EOF)
-    return (ELEMENT_ERROR);
-
-  eptr = element;
-  temp = bsearch(&mptr, elements, sizeof(elements) / sizeof(elements[0]),
-                 sizeof(elements[0]),
-                 (int (*)(const void *, const void *))compare_elements);
-
-  if (temp == NULL)
-  {
-   /*
-    * Unrecognized element stuff...
-    */
-
-    t->element = ELEMENT_COMMENT;
-    strcpy(comment, element);
-    cptr = comment + strlen(comment);
-  }
-  else
-  {
-    t->element = (element_t)((char **)temp - elements);
-    cptr       = comment;
-  }
-
-  if (t->element == ELEMENT_COMMENT)
-  {
-    while (ch != EOF && ch != '>' && cptr < (comment + sizeof(comment) - 1))
-    {
-      *cptr++ = ch;
-      ch = getc(fp);
-    }
-
-    *cptr   = '\0';
-    t->data = strdup(comment);
-  }
-  else
-  {
-    while (ch != EOF && ch != '>' && ch != '/')
-    {
-      if (!isspace(ch & 255))
-      {
-        ungetc(ch, fp);
-        parse_variable(t, fp);
-      }
-
-      ch = getc(fp);
-    }
-
-    if (ch != EOF)
-      ungetc(ch, fp);
-  }
-
-  return (t->element);
-}
-
-
-/*
- * End of "$Id: form-tree.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/form.h b/filter/form.h
deleted file mode 100644 (file)
index 7b4598e..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * "$Id: form.h 6649 2007-07-11 21:46:42Z mike $"
- *
- *   CUPS form header file for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1997-2005 by Easy Software Products.
- *
- *   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.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "common.h"
-
-
-/*
- * Form elements...
- */
-
-typedef enum
-{
-  ELEMENT_FILE = -1,           /* Pseudo element, not in file, but above */
-  ELEMENT_FRAGMENT,    /* Text fragment */
-  ELEMENT_COMMENT,     /* <!-- .... --> */
-  ELEMENT_ARC,
-  ELEMENT_BOX,
-  ELEMENT_BR,
-  ELEMENT_B,
-  ELEMENT_CUPSFORM,
-  ELEMENT_DEFVAR,
-  ELEMENT_FONT,
-  ELEMENT_H1,
-  ELEMENT_H2,
-  ELEMENT_H3,
-  ELEMENT_H4,
-  ELEMENT_H5,
-  ELEMENT_H6,
-  ELEMENT_HEAD,
-  ELEMENT_IMG,
-  ELEMENT_I,
-  ELEMENT_LINE,
-  ELEMENT_PAGE,
-  ELEMENT_PIE,
-  ELEMENT_POLY,
-  ELEMENT_PRE,
-  ELEMENT_P,
-  ELEMENT_RECT,
-  ELEMENT_TEXT,
-  ELEMENT_TT,
-  ELEMENT_VAR
-} element_t;
-
-
-/*
- * Font styles...
- */
-
-typedef enum
-{
-  STYLE_NORMAL,
-  STYLE_BOLD,
-  STYLE_ITALIC,
-  STYLE_BOLD_ITALIC
-} style_t;
-
-
-/*
- * Text alignments...
- */
-
-typedef enum
-{
-  HALIGN_LEFT,
-  HALIGN_CENTER,
-  HALIGN_RIGHT
-} halign_t;
-
-typedef enum
-{
-  VALIGN_BOTTOM,
-  VALIGN_CENTER,
-  VALIGN_TOP
-} valign_t;
-
-
-/*
- * Text directions...
- */
-
-typedef enun
-{
-  DIR_LEFT_TO_RIGHT,
-  DIR_RIGHT_TO_LEFT
-} dir_t;
-
-
-/*
- * Attribute structure...
- */
-
-typedef struct
-{
-  char                 *name,          /* Name of attribute */
-                       *value;         /* Value of attribute */
-} attr_t;
-
-
-/*
- * Form document tree structure...
- */
-
-typedef struct tree_str
-{
-  struct tree_str      *prev,          /* Previous tree node */
-                       *next,          /* Next tree node */
-                       *parent,        /* Parent tree node */
-                       *child,         /* First child node */
-                       *last_child;    /* Last child node */
-  element_t            element;        /* Element type */
-  float                        x, y, w, h;     /* Position and size in points */
-  float                        bg[3], fg[3];   /* Colors of element */
-  float                        thickness;      /* Thickness of lines */
-  int                  preformatted;   /* Preformatted text? */
-  float                        size;           /* Height of text in points */
-  char                 *typeface;      /* Typeface of text */
-  style_t              style;          /* Style of text */
-  halign_t             halign;         /* Horizontal alignment */
-  valign_t             valign;         /* Vertical alignment */
-  dir_t                        dir;            /* Direction of text */
-  int                  num_attrs;      /* Number of attributes */
-  attr_t               *attrs;         /* Attributes */
-  void                 *data;          /* Text fragment data */
-} tree_t;
-
-
-/*
- * Globals...
- */
-
-extern int             NumOptions;     /* Number of command-line options */
-extern cups_option_t   *Options;       /* Command-line options */
-extern ppd_file_t      *PPD;           /* PPD file */
-
-
-/*
- * Prototypes...
- */
-
-extern void    formDelete(tree_t *t);
-extern char    *formGetAttr(tree_t *t, const char *name);
-extern tree_t  *formNew(tree_t *p);
-extern tree_t  *formRead(FILE *fp, tree_t *p);
-extern void    formSetAttr(tree_t *t, const char *name, const char *value);
-extern void    formWrite(tree_t *p);
-
-
-/*
- * End of "$Id: form.h 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-attr.c b/filter/hpgl-attr.c
deleted file mode 100644 (file)
index 7a93ad7..0000000
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * "$Id: hpgl-attr.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 attribute processing for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007-2008 by Apple Inc.
- *   Copyright 1993-2007 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   CR_color_range()     - Set the range for color values.
- *   AC_anchor_corner()   - Set the anchor corner.
- *   FT_fill_type()       - Set the fill type or pattern.
- *   LA_line_attributes() - Set the line drawing attributes.
- *   LT_line_type()       - Set the line type (style)...
- *   NP_number_pens()     - Set the number of pens to be used.
- *   PC_pen_color()       - Set the pen color...
- *   PW_pen_width()       - Set the pen width.
- *   RF_raster_fill()     - Set the raster fill pattern.
- *   SM_symbol_mode()     - Set where symbols are drawn.
- *   SP_select_pen()      - Select a pen for drawing.
- *   UL_user_line_type()  - Set a user-defined line type.
- *   WU_width_units()     - Set the units used for pen widths.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-
-
-/*
- * 'CR_color_range()' - Set the range for color values.
- */
-
-void
-CR_color_range(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameters */
-{
-  if (num_params == 0)
-  {
-   /*
-    * Default to 0 to 255 for all color values.
-    */
-
-    ColorRange[0][0] = 0.0;
-    ColorRange[0][1] = 255.0;
-    ColorRange[1][0] = 0.0;
-    ColorRange[1][1] = 255.0;
-    ColorRange[2][0] = 0.0;
-    ColorRange[2][1] = 255.0;
-  }
-  else if (num_params == 6)
-  {
-   /*
-    * Set the range based on the parameters...
-    */
-
-    ColorRange[0][0] = params[0].value.number;
-    ColorRange[0][1] = params[1].value.number - params[0].value.number;
-    ColorRange[1][0] = params[2].value.number;
-    ColorRange[1][1] = params[3].value.number - params[2].value.number;
-    ColorRange[2][0] = params[4].value.number;
-    ColorRange[2][1] = params[5].value.number - params[4].value.number;
-  }
-  else
-    fprintf(stderr,
-            "DEBUG: HP-GL/2 \'CR\' command with invalid number of "
-           "parameters (%d)!\n", num_params);
-}
-
-
-/*
- * 'AC_anchor_corner()' - Set the anchor corner.
- */
-
-void
-AC_anchor_corner(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'FT_fill_type()' - Set the fill type or pattern.
- *
- * Note:
- *
- *   This needs to be updated to support non-solid fill.
- */
-
-void
-FT_fill_type(int     num_params,       /* I - Number of parameters */
-             param_t *params)          /* I - Parameters */
-{
-  if (num_params == 0 ||
-      params[0].value.number == 1 ||
-      params[0].value.number == 2)
-  {
-    /**** SOLID PATTERN ****/
-  }
-}
-
-
-/*
- * 'LA_line_attributes()' - Set the line drawing attributes.
- */
-
-void
-LA_line_attributes(int     num_params, /* I - Number of parameters */
-                   param_t *params)    /* I - Parameters */
-{
-  int  i;                              /* Looping var */
-
-
-  if (num_params == 0)
-  {
-    MiterLimit = 3.0f;
-    LineCap    = 0;
-    LineJoin   = 0;
-  }
-  else for (i = 0; i < (num_params - 1); i += 2)
-    switch ((int)params[i].value.number)
-    {
-      case 1 :
-          LineCap = params[i + 1].value.number == 1 ? 0 :
-                    params[i + 1].value.number == 4 ? 1 : 2;
-          break;
-      case 2 :
-          switch ((int)params[i + 1].value.number)
-          {
-            case 1 :
-            case 2 :
-            case 3 :
-                LineJoin = 0;
-                break;
-            case 5 :
-                LineJoin = 2;
-                break;
-            default :
-                LineJoin = 1;
-                break;
-          }
-          break;
-      case 3 :
-          MiterLimit = 1.0 + 0.5 * (params[i + 1].value.number - 1.0);
-          break;
-    }
-
-  if (PageDirty)
-  {
-    printf("%.1f setmiterlimit\n", MiterLimit);
-    printf("%d setlinecap\n", LineCap);
-    printf("%d setlinejoin\n", LineJoin);
-  }
-}
-
-
-/*
- * 'LT_line_type()' - Set the line type (style)...
- *
- * Note:
- *
- *   This needs to be updated to support line types.
- */
-
-void
-LT_line_type(int     num_params,       /* I - Number of parameters */
-             param_t *params)          /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'NP_number_pens()' - Set the number of pens to be used.
- */
-
-void
-NP_number_pens(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameters */
-{
-  int  i;                              /* Looping var */
-
-
-  if (num_params == 0)
-    PenCount = 8;
-  else if (num_params == 1)
-  {
-    if (params[0].value.number < 1 || params[0].value.number > MAX_PENS)
-    {
-      fprintf(stderr,
-             "DEBUG: HP-GL/2 \'NP\' command with invalid number of "
-             "pens (%d)!\n", (int)params[0].value.number);
-      PenCount = 8;
-    }
-    else
-      PenCount = (int)params[0].value.number;
-  }
-  else
-    fprintf(stderr,
-            "DEBUG: HP-GL/2 \'NP\' command with invalid number of "
-           "parameters (%d)!\n", num_params);
-
-  for (i = 0; i < PenCount; i ++)
-    Pens[i].width = PenWidth;
-
-  PC_pen_color(0, NULL);
-}
-
-
-/*
- * 'PC_pen_color()' - Set the pen color...
- */
-
-void
-PC_pen_color(int     num_params,       /* I - Number of parameters */
-             param_t *params)          /* I - Parameters */
-{
-  int          i;                      /* Looping var */
-  static float standard_colors[8][3] = /* Standard colors for first 8 pens */
-               {
-                 { 0.0, 0.0, 0.0 },    /* Black */
-                 { 1.0, 0.0, 0.0 },    /* Red */
-                 { 0.0, 1.0, 0.0 },    /* Green */
-                 { 1.0, 1.0, 0.0 },    /* Yellow */
-                 { 0.0, 0.0, 1.0 },    /* Blue */
-                 { 1.0, 0.0, 1.0 },    /* Magenta */
-                 { 0.0, 1.0, 1.0 },    /* Cyan */
-                 { 1.0, 1.0, 1.0 }     /* White */
-               };
-
-
-  if (num_params == 0)
-  {
-    for (i = 0; i < PenCount; i ++)
-      if (i < 8)
-      {
-        Pens[i].rgb[0] = standard_colors[i][0];
-        Pens[i].rgb[1] = standard_colors[i][1];
-        Pens[i].rgb[2] = standard_colors[i][2];
-      }
-      else
-      {
-        Pens[i].rgb[0] = 0.0f;
-        Pens[i].rgb[1] = 0.0f;
-        Pens[i].rgb[2] = 0.0f;
-      }
-
-    if (PageDirty)
-      printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-            Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-            Pens[PenNumber].width * PenScaling);
-  }
-  else if (num_params == 1 || num_params == 4)
-  {
-    i = (int)params[0].value.number - 1;
-
-    if (i < 0 || i >= PenCount)
-    {
-      fprintf(stderr,
-              "DEBUG: HP-GL/2 \'PC\' command with invalid pen (%d)!\n", i + 1);
-      return;
-    }
-
-    if (num_params == 1)
-    {
-      Pens[i].rgb[0] = standard_colors[i & 7][0];
-      Pens[i].rgb[1] = standard_colors[i & 7][1];
-      Pens[i].rgb[2] = standard_colors[i & 7][2];
-    }
-    else
-    {
-      Pens[i].rgb[0] = (params[1].value.number - ColorRange[0][0]) /
-                       (ColorRange[0][1] - ColorRange[0][0]);
-      Pens[i].rgb[1] = (params[2].value.number - ColorRange[1][0]) /
-                       (ColorRange[1][1] - ColorRange[1][0]);
-      Pens[i].rgb[2] = (params[3].value.number - ColorRange[2][0]) /
-                       (ColorRange[2][1] - ColorRange[2][0]);
-
-      fprintf(stderr, "DEBUG: Pen %d %.0f %.0f %.0f = %.3f %.3f %.3f\n",
-             i, params[1].value.number, params[2].value.number,
-             params[3].value.number, Pens[i].rgb[0], Pens[i].rgb[1],
-             Pens[i].rgb[2]);
-    }
-
-    if (PageDirty && i == PenNumber)
-      printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-            Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-            Pens[PenNumber].width * PenScaling);
-  }
-  else
-    fprintf(stderr,
-            "DEBUG: HP-GL/2 \'PC\' command with invalid number of "
-           "parameters (%d)!\n", num_params);
-}
-
-
-/*
- * 'PW_pen_width()' - Set the pen width.
- */
-
-void
-PW_pen_width(int     num_params,       /* I - Number of parameters */
-             param_t *params)          /* I - Parameters */
-{
-  int  pen;                            /* Pen number */
-  float        w;                              /* Width value */
-
-
-  if (WidthUnits == 0)
-  {
-   /*
-    * Metric...
-    */
-
-    if (num_params == 0)
-      w = 0.35f / 25.4f * 72.0f;
-    else
-      w = params[0].value.number / 25.4f * 72.0f;
-  }
-  else
-  {
-   /*
-    * Relative...
-    */
-
-    w = (float)hypot(PlotSize[0], PlotSize[1]) / 1016.0f * 72.0f;
-
-    if (num_params == 0)
-      w *= 0.01f;
-    else
-      w *= params[0].value.number;
-  }
-
-  if (num_params == 2)
-  {
-    pen = (int)params[1].value.number - 1;
-
-    if (pen < 0 || pen >= PenCount)
-    {
-      fprintf(stderr,
-              "DEBUG: HP-GL/2 \'PW\' command with invalid pen (%d)!\n",
-             pen + 1);
-      return;
-    }
-
-    Pens[pen].width = w;
-
-    if (PageDirty && pen == PenNumber)
-      printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-            Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-            Pens[PenNumber].width * PenScaling);
-  }
-  else if (num_params < 2)
-  {
-   /*
-    * Set width for all pens...
-    */
-
-    for (pen = 0; pen < PenCount; pen ++)
-      Pens[pen].width = w;
-
-    if (PageDirty)
-      printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-            Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-            Pens[PenNumber].width * PenScaling);
-  }
-  else
-    fprintf(stderr,
-            "DEBUG: HP-GL/2 \'PW\' command with invalid number of "
-           "parameters (%d)!\n", num_params);
-}
-
-
-/*
- * 'RF_raster_fill()' - Set the raster fill pattern.
- *
- * Note:
- *
- *   This needs to be implemented.
- */
-
-void
-RF_raster_fill(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'SM_symbol_mode()' - Set where symbols are drawn.
- */
-
-void
-SM_symbol_mode(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'SP_select_pen()' - Select a pen for drawing.
- */
-
-void
-SP_select_pen(int     num_params,      /* I - Number of parameters */
-              param_t *params)         /* I - Parameters */
-{
-  if (num_params == 0)
-    PenNumber = 0;
-  else if (num_params > 1)
-    fprintf(stderr,
-            "DEBUG: HP-GL/2 \'SP\' command with invalid number of parameters "
-           "(%d)!\n", num_params);
-  else if (params[0].value.number <= 0 || params[0].value.number >= PenCount)
-    fprintf(stderr, "DEBUG: HP-GL/2 \'SP\' command with invalid pen (%d)!\n",
-           (int)params[0].value.number);
-  else
-    PenNumber = (int)params[0].value.number - 1;
-
-  if (PageDirty)
-    printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-          Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-          Pens[PenNumber].width * PenScaling);
-}
-
-
-/*
- * 'UL_user_line_type()' - Set a user-defined line type.
- */
-
-void
-UL_user_line_type(int     num_params,  /* I - Number of parameters */
-                  param_t *params)     /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'WU_width_units()' - Set the units used for pen widths.
- */
-
-void
-WU_width_units(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameters */
-{
-  if (num_params == 0)
-    WidthUnits = 0;
-  else if (num_params == 1)
-    WidthUnits = (int)params[0].value.number;
-  else
-    fprintf(stderr,
-            "DEBUG: HP-GL/2 \'WU\' command with invalid number of "
-           "parameters (%d)!\n", num_params);
-}
-
-
-/*
- * End of "$Id: hpgl-attr.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-char.c b/filter/hpgl-char.c
deleted file mode 100644 (file)
index 031b938..0000000
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * "$Id: hpgl-char.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 character processing for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1993-2005 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   AD_define_alternate()     - Define the alternate font.
- *   CF_character_fill()       - Set whether or not to fill or outline
- *                               characters.
- *   CP_character_plot()       - Move the current pen position for the given
- *                               number of columns and rows.
- *   DI_absolute_direction()   - Set the direction vector for text.
- *   DR_relative_direction()   - Set the relative direction vector for text.
- *   DT_define_label_term()    - Set the label string terminator.
- *   DV_define_variable_path() - Define a path for text.
- *   ES_extra_space()          - Set extra spacing (kerning) between characters.
- *   LB_label()                - Display a label string.
- *   LO_label_origin()         - Set the label origin.
- *   SA_select_alternate()     - Select the alternate font.
- *   SD_define_standard()      - Define the standard font...
- *   SI_absolute_size()        - Set the absolute size of text.
- *   SL_character_slant()      - Set the slant of text.
- *   SR_relative_size()        - Set the relative size of text.
- *   SS_select_standard()      - Select the standard font for text.
- *   TD_transparent_data()     - Send transparent print data.
- *   
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-
-
-/*
- * 'define_font()' - Define the specified font...
- */
-
-void
-define_font(int f)                     /* I - Font number */
-{
-  font_t       *font;                  /* Font */
-  const char   *fstring;               /* Font string - SA or SS */
-  float                xform[2][2];            /* Transform matrix */
-
-
- /*
-  * Get the correct font data...
-  */
-
-  if (f)
-  {
-    font    = &AlternateFont;
-    fstring = "SA";
-  }
-  else
-  {
-    font    = &StandardFont;
-    fstring = "SS";
-  }
-
- /*
-  * Compute the font matrix, accounting for any rotation...
-  */
-
-  switch (Rotation)
-  {
-    default :
-    case 0 :
-        xform[0][0] = font->xpitch * font->x * font->height;
-       xform[0][1] = font->xpitch * font->y * font->height;
-       xform[1][0] = -font->y * font->height;
-       xform[1][1] = font->x * font->height;
-        break;
-
-    case 90 :
-       xform[0][0] = -font->xpitch * font->y * font->height;
-        xform[0][1] = font->xpitch * font->x * font->height;
-       xform[1][0] = -font->x * font->height;
-       xform[1][1] = -font->y * font->height;
-        break;
-
-    case 180 :
-        xform[0][0] = -font->xpitch * font->x * font->height;
-       xform[0][1] = -font->xpitch * font->y * font->height;
-       xform[1][0] = font->y * font->height;
-       xform[1][1] = -font->x * font->height;
-        break;
-
-    case 270 :
-       xform[0][0] = font->xpitch * font->y * font->height;
-        xform[0][1] = -font->xpitch * font->x * font->height;
-       xform[1][0] = font->x * font->height;
-       xform[1][1] = font->y * font->height;
-        break;
-  }
-
- /*
-  * Send the font definition...
-  */
-
-  printf("/%s {\n"
-         "     /%s%s%s%s findfont\n"
-        "      [ %f %f %f %f 0.0 0.0 ] makefont\n"
-        "      setfont\n"
-        "} bind def\n",
-         fstring, font->spacing ? "Helvetica" : "Courier",
-         (font->weight > 0 || font->posture) ? "-" : "",
-         font->weight > 0 ? "Bold" : "",
-         font->posture ? "Oblique" : "",
-         xform[0][0], xform[0][1], xform[1][0], xform[1][1]);
-
-  if (f == CharFont)
-    printf("%s\n", fstring);
-}
-
-
-/*
- * 'AD_define_alternate()' - Define the alternate font.
- */
-
-void
-AD_define_alternate(int     num_params,        /* I - Number of parameters */
-                    param_t *params)   /* I - Parameters */
-{
-  int  i;                              /* Looping var */
-
-
- /*
-  * Set default font attributes...
-  */
-
-  AlternateFont.symbol_set = 277;
-  AlternateFont.spacing    = 0;
-  AlternateFont.pitch      = 9;
-  AlternateFont.height     = 11.5;
-  AlternateFont.posture    = 0;
-  AlternateFont.weight     = 0;
-  AlternateFont.typeface   = 48;
-  AlternateFont.x          = 1.0;
-  AlternateFont.y          = 0.0;
-
- /*
-  * Loop through parameter value pairs...
-  */
-
-  for (i = 0; i < (num_params - 1); i += 2)
-    switch ((int)params[i].value.number)
-    {
-      case 1 : /* Symbol Set */
-          AlternateFont.symbol_set = (int)params[i + 1].value.number;
-          break;
-      case 2 : /* Font Spacing */
-          AlternateFont.spacing = (int)params[i + 1].value.number;
-          break;
-      case 3 : /* Pitch */
-          AlternateFont.pitch = params[i + 1].value.number;
-          break;
-      case 4 : /* Height */
-          AlternateFont.height = params[i + 1].value.number;
-          break;
-      case 5 : /* Posture */
-          AlternateFont.posture = (int)params[i + 1].value.number;
-          break;
-      case 6 : /* Stroke Weight */
-          AlternateFont.weight = (int)params[i + 1].value.number;
-          break;
-      case 7 : /* Typeface */
-          AlternateFont.typeface = (int)params[i + 1].value.number;
-          break;
-    }
-
-  if (AlternateFont.spacing)
-  {
-   /*
-    * Set proportional spacing font...
-    */
-
-    AlternateFont.xpitch = 1.0f;
-  }
-  else
-  {
-   /*
-    * Set fixed-spaced font...
-    */
-
-    AlternateFont.xpitch = 0.6f * AlternateFont.height / AlternateFont.pitch;
-  }
-
- /*
-  * Define the font...
-  */
-
-  if (PageDirty)
-  {
-    printf("%% AD");
-    for (i = 0; i < num_params; i ++)
-      if (i)
-        printf(",%g", params[i].value.number);
-      else
-        printf("%g", params[i].value.number);
-    puts(";");
-
-    define_font(1);
-  }
-
-  CharHeight[1] = AlternateFont.height;
-}
-
-
-/*
- * 'CF_character_fill()' - Set whether or not to fill or outline characters.
- */
-
-void
-CF_character_fill(int     num_params,  /* I - Number of parameters */
-                  param_t *params)     /* I - Parameters */
-{
-  if (num_params == 0)
-    CharFillMode = 0;
-  else
-    CharFillMode = (int)params[0].value.number;
-
-  if (num_params == 2)
-    CharPen = (int)params[1].value.number;
-}
-
-
-/*
- * 'CP_character_plot()' - Move the current pen position for the given number
- *                         of columns and rows.
- */
-
-void
-CP_character_plot(int     num_params,
-                  param_t *params)
-{
-  if (num_params < 2)
-    return;
-
-  switch (Rotation)
-  {
-    case 0:
-       PenPosition[0] += params[0].value.number * 1.2f / CharHeight[CharFont];
-       PenPosition[1] += params[1].value.number * CharHeight[CharFont];
-       break;
-    case 90:
-       PenPosition[0] -= params[1].value.number * 1.2f / CharHeight[CharFont];
-       PenPosition[1] += params[0].value.number * CharHeight[CharFont];
-       break;
-    case 180:
-       PenPosition[0] -= params[0].value.number * 1.2f / CharHeight[CharFont];
-       PenPosition[1] -= params[1].value.number * CharHeight[CharFont];
-       break;
-    case 270:
-       PenPosition[0] += params[1].value.number * 1.2f / CharHeight[CharFont];
-       PenPosition[1] -= params[0].value.number * CharHeight[CharFont];
-       break;
-  }
-}
-
-
-/*
- * 'DI_absolute_direction()' - Set the direction vector for text.
- */
-
-void
-DI_absolute_direction(int     num_params,      /* I - Number of parameters */
-                      param_t *params)         /* I - Parameters */
-{
-  if (num_params != 2)
-    return;
-
-  if (CharFont)
-  {
-    AlternateFont.x = params[0].value.number;
-    AlternateFont.y = params[1].value.number;
-  }
-  else
-  {
-    StandardFont.x = params[0].value.number;
-    StandardFont.y = params[1].value.number;
-  }
-
-  if (PageDirty)
-  {
-    printf("%% DI%g,%g\n", params[0].value.number, params[1].value.number);
-
-    define_font(CharFont);
-  }
-}
-
-
-/*
- * 'DR_relative_direction()' - Set the relative direction vector for text.
- */
-
-void
-DR_relative_direction(int     num_params,      /* I - Number of parameters */
-                      param_t *params)         /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'DT_define_label_term()' - Set the label string terminator.
- */
-
-void
-DT_define_label_term(int     num_params,       /* I - Number of parameters */
-                     param_t *params)          /* I - Parameters */
-{
-  if (num_params == 0)
-    StringTerminator = '\003';
-  else
-    StringTerminator = params[0].value.string[0];
-}
-
-
-/*
- * 'DV_define_variable_path()' - Define a path for text.
- */
-
-void
-DV_define_variable_path(int     num_params,    /* I - Number of parameters */
-                        param_t *params)       /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'ES_extra_space()' - Set extra spacing (kerning) between characters.
- */
-
-void
-ES_extra_space(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'LB_label()' - Display a label string.
- */
-
-void
-LB_label(int     num_params,           /* I - Number of parameters */
-         param_t *params)              /* I - Parameters */
-{
-  char *s;                             /* Pointer into string */
-
-
-  if (num_params == 0)
-    return;
-
-  Outputf("gsave\n");
-  Outputf("currentmiterlimit 1.0 setmiterlimit\n");
-  Outputf("MP\n");
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-  PenValid = 1;
-
-  Outputf("(");
-  for (s = params[0].value.string; *s != '\0'; s ++)
-    if (strchr("()\\", *s) != NULL)
-      Outputf("\\%c", *s);
-    else
-      Outputf("%c", *s);
-  Outputf(") true charpath\n");
-
-  if (CharFillMode != 1)
-    Outputf("FI\n");
-  if (CharFillMode == 1 || CharFillMode == 3)
-  {
-    Outputf("%.3f %.3f %.3f %.2f SP ST\n", Pens[CharPen].rgb[0],
-           Pens[CharPen].rgb[CharPen], Pens[CharPen].rgb[2],
-           Pens[CharPen].width * PenScaling);
-    Outputf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-           Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-           Pens[PenNumber].width * PenScaling);
-  }
-
-  Outputf("setmiterlimit\n");
-  Outputf("grestore\n");
-}
-
-
-/*
- * 'LO_label_origin()' - Set the label origin.
- */
-
-void
-LO_label_origin(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'SA_select_alternate()' - Select the alternate font.
- */
-
-void
-SA_select_alternate(int     num_params,        /* I - Number of parameters */
-                    param_t *params)   /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  if (PageDirty)
-    puts("SA");
-
-  CharFont = 1;
-}
-
-
-/*
- * 'SD_define_standard()' - Define the standard font...
- */
-void
-SD_define_standard(int     num_params, /* I - Number of parameters */
-                   param_t *params)    /* I - Parameters */
-{
-  int  i;                              /* Looping var */
-
-
- /*
-  * Set default font attributes...
-  */
-
-  StandardFont.symbol_set = 277;
-  StandardFont.spacing    = 0;
-  StandardFont.pitch      = 9;
-  StandardFont.height     = 11.5;
-  StandardFont.posture    = 0;
-  StandardFont.weight     = 0;
-  StandardFont.typeface   = 48;
-  StandardFont.x          = 1.0;
-  StandardFont.y          = 0.0;
-
- /*
-  * Loop through parameter value pairs...
-  */
-
-  for (i = 0; i < (num_params - 1); i += 2)
-    switch ((int)params[i].value.number)
-    {
-      case 1 : /* Symbol Set */
-          StandardFont.symbol_set = (int)params[i + 1].value.number;
-          break;
-      case 2 : /* Font Spacing */
-          StandardFont.spacing = (int)params[i + 1].value.number;
-          break;
-      case 3 : /* Pitch */
-          StandardFont.pitch = params[i + 1].value.number;
-          break;
-      case 4 : /* Height */
-          StandardFont.height = params[i + 1].value.number;
-          break;
-      case 5 : /* Posture */
-          StandardFont.posture = (int)params[i + 1].value.number;
-          break;
-      case 6 : /* Stroke Weight */
-          StandardFont.weight = (int)params[i + 1].value.number;
-          break;
-      case 7 : /* Typeface */
-          StandardFont.typeface = (int)params[i + 1].value.number;
-          break;
-    }
-
-  if (StandardFont.spacing || StandardFont.pitch <= 0.0)
-  {
-   /*
-    * Set proportional spacing font...
-    */
-
-    StandardFont.xpitch = 1.0f;
-  }
-  else
-  {
-   /*
-    * Set fixed-spaced font...
-    */
-
-    StandardFont.xpitch = 0.6f * StandardFont.height / StandardFont.pitch;
-  }
-
- /*
-  * Define the font...
-  */
-
-  if (PageDirty)
-  {
-    printf("%% SD");
-    for (i = 0; i < num_params; i ++)
-      if (i)
-        printf(",%g", params[i].value.number);
-      else
-        printf("%g", params[i].value.number);
-    puts(";");
-
-    define_font(0);
-  }
-
-  CharHeight[0] = StandardFont.height;
-}
-
-
-/*
- * 'SI_absolute_size()' - Set the absolute size of text.
- */
-
-void
-SI_absolute_size(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  float        xsize, ysize;                   /* Font size... */
-
-
-  if (num_params != 2)
-    return;
-
- /*
-  * The "SI" values are supposed to be cm, but they appear to be inches
-  * when tested on real HP devices...
-  */
-
-  xsize = params[0].value.number * 72.0f;
-  ysize = params[1].value.number * 72.0f * 0.6f;
-
-  if (CharFont)
-  {
-    AlternateFont.xpitch = xsize / ysize;
-    AlternateFont.height = ysize;
-  }
-  else
-  {
-    StandardFont.xpitch = xsize / ysize;
-    StandardFont.height = ysize;
-  }
-
-  if (PageDirty)
-  {
-    printf("%% SI%g,%g\n", params[0].value.number, params[1].value.number);
-
-    define_font(CharFont);
-  }
-}
-
-
-/*
- * 'SL_character_slant()' - Set the slant of text.
- */
-
-void
-SL_character_slant(int     num_params, /* I - Number of parameters */
-                   param_t *params)    /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'SR_relative_size()' - Set the relative size of text.
- */
-
-void
-SR_relative_size(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'SS_select_standard()' - Select the standard font for text.
- */
-
-void
-SS_select_standard(int     num_params, /* I - Number of parameters */
-                   param_t *params)    /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  if (PageDirty)
-    puts("SS");
-
-  CharFont = 0;
-}
-
-
-/*
- * 'TD_transparent_data()' - Send transparent print data.
- */
-
-void
-TD_transparent_data(int     num_params,        /* I - Number of parameters */
-                    param_t *params)   /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * End of "$Id: hpgl-char.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-config.c b/filter/hpgl-config.c
deleted file mode 100644 (file)
index 180674d..0000000
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * "$Id: hpgl-config.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 configuration routines for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1993-2005 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   update_transform()  - Update the page transformation matrix as needed.
- *   BP_begin_plot()     - Start a plot...
- *   DF_default_values() - Set all state info to the default values.
- *   IN_initialize()     - Initialize the plotter.
- *   IP_input_absolute() - Set P1 and P2 values for the plot.
- *   IR_input_relative() - Update P1 and P2.
- *   IW_input_window()   - Setup an input window.
- *   PG_advance_page()   - Eject the current page.
- *   PS_plot_size()      - Set the plot size.
- *   RO_rotate()         - Rotate the plot.
- *   RP_replot()         - Replot the current page.
- *   SC_scale()          - Set user-defined scaling.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-
-#define max(a,b) ((a) < (b) ? (b) : (a))
-
-
-/*
- * 'update_transform()' - Update the page transformation matrix as needed.
- */
-
-void
-update_transform(void)
-{
-  float        page_width,     /* Actual page width */
-       page_height;    /* Actual page height */
-  float        scaling;        /* Scaling factor */
-  float        left, right,    /* Scaling window */
-       bottom, top;
-  float        width, height;  /* Scaling width and height */
-  float        iw1[2], iw2[2]; /* Clipping window */
-
-
- /*
-  * Get the page and input window sizes...
-  */
-
-  if (FitPlot)
-  {
-    page_width  = PageRight - PageLeft;
-    page_height = PageTop - PageBottom;
-  }
-  else
-  {
-    page_width  = (P2[0] - P1[0]) * 72.0f / 1016.0f;
-    page_height = (P2[1] - P1[1]) * 72.0f / 1016.0f;
-  }
-
-  fprintf(stderr, "DEBUG: page_width = %.0f, page_height = %.0f\n",
-          page_width, page_height);
-
-  if (page_width == 0 || page_height == 0)
-    return;
-
- /*
-  * Set the scaling window...
-  */
-
-  switch (ScalingType)
-  {
-    default : /* No user scaling */
-        left   = P1[0];
-       bottom = P1[1];
-       right  = P2[0];
-       top    = P2[1];
-        break;
-
-    case 0 : /* Anisotropic (non-uniform) scaling */
-        left   = Scaling1[0];
-       bottom = Scaling1[1];
-       right  = Scaling2[0];
-       top    = Scaling2[1];
-        break;
-
-    case 1 : /* Isotropic (uniform) scaling */
-        left   = Scaling1[0];
-       bottom = Scaling1[1];
-       right  = Scaling2[0];
-       top    = Scaling2[1];
-
-       width  = right - left;
-       height = top - bottom;
-        
-       if (width == 0 || height == 0)
-         return;
-
-        if ((width * page_height) != (height * page_width))
-       {
-         scaling = height * page_width / page_height;
-         if (width < scaling)
-         {
-           width = scaling;
-           left  = 0.5f * (left + right - width);
-           right = left + width;
-         }
-         else
-         {
-           height = width * page_height / page_width;
-           bottom = 0.5f * (bottom + top - height);
-           top    = bottom + height;
-         }
-       }
-        break;
-
-    case 2 :
-        left   = Scaling1[0];
-       bottom = Scaling1[1];
-       right  = left + page_width * Scaling2[0] * 1016.0f / 72.0f;
-       top    = bottom + page_height * Scaling2[1] * 1016.0f / 72.0f;
-        break;
-  }
-
-  width  = right - left;
-  height = top - bottom;
-
-  if (width == 0 || height == 0)
-    return;
-
- /*
-  * Scale the plot as needed...
-  */
-
-  if (Rotation == 0 || Rotation == 180)
-    scaling = page_width / width;
-  else
-    scaling = page_width / height;
-
-  if (FitPlot)
-    scaling *= max(page_width, page_height) / max(PlotSize[1], PlotSize[0]);
-
- /*
-  * Offset for the current P1 location...
-  */
-
-  if (FitPlot)
-  {
-    left   = 0;
-    bottom = 0;
-  }
-  else
-  {
-    left   = P1[0] * 72.0f / 1016.0f;
-    bottom = P1[1] * 72.0f / 1016.0f;
-  }
-
- /*
-  * Generate a new transformation matrix...
-  */
-
-  switch (Rotation)
-  {
-    default :
-    case 0 :
-       Transform[0][0] = scaling;
-       Transform[0][1] = 0.0;
-       Transform[0][2] = -left;
-       Transform[1][0] = 0.0;
-       Transform[1][1] = scaling;
-       Transform[1][2] = -bottom;
-       break;
-
-    case 90 :
-       Transform[0][0] = 0.0;
-       Transform[0][1] = -scaling;
-       Transform[0][2] = PageLength - left;
-       Transform[1][0] = scaling;
-       Transform[1][1] = 0.0;
-       Transform[1][2] = -bottom;
-       break;
-
-    case 180 :
-       Transform[0][0] = -scaling;
-       Transform[0][1] = 0.0;
-       Transform[0][2] = PageLength - left;
-       Transform[1][0] = 0.0;
-       Transform[1][1] = -scaling;
-       Transform[1][2] = PageWidth - bottom;
-       break;
-
-    case 270 :
-       Transform[0][0] = 0.0;
-       Transform[0][1] = scaling;
-       Transform[0][2] = -left;
-       Transform[1][0] = -scaling;
-       Transform[1][1] = 0.0;
-       Transform[1][2] = PageWidth - bottom;
-       break;
-  }
-
-  fprintf(stderr, "DEBUG: Transform = [ %.3f %.3f\n"
-                  "DEBUG:               %.3f %.3f\n"
-                  "DEBUG:               %.3f %.3f ]\n",
-          Transform[0][0], Transform[1][0], Transform[0][1],
-         Transform[1][1], Transform[0][2], Transform[1][2]);
-
-  if (FitPlot)
-  {
-    if (Rotation == 0 || Rotation == 180)
-      PenScaling = page_width / PlotSize[1];
-    else
-      PenScaling = page_width / PlotSize[0];
-  }
-  else
-    PenScaling = 1.0;
-
-  if (PenScaling < 0.0)
-    PenScaling = -PenScaling;
-
-  if (PageDirty)
-  {
-    printf("%.2f setlinewidth\n", Pens[PenNumber].width * PenScaling);
-
-    if (IW1[0] != IW2[0] && IW1[1] != IW2[1])
-    {
-      iw1[0] = IW1[0] * 72.0f / 1016.0f;
-      iw1[1] = IW1[1] * 72.0f / 1016.0f;
-      iw2[0] = IW2[0] * 72.0f / 1016.0f;
-      iw2[1] = IW2[1] * 72.0f / 1016.0f;
-
-      printf("initclip MP %.3f %.3f MO %.3f %.3f LI %.3f %.3f LI %.3f %.3f LI CP clip\n",
-            iw1[0], iw1[1], iw1[0], iw2[1], iw2[0], iw2[1], iw2[0], iw1[1]);
-    }
-  }
-}
-
-
-/*
- * 'BP_begin_plot()' - Start a plot...
- */
-
-void
-BP_begin_plot(int     num_params,      /* I - Number of parameters */
-              param_t *params)         /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'DF_default_values()' - Set all state info to the default values.
- */
-
-void
-DF_default_values(int     num_params,  /* I - Number of parameters */
-                  param_t *params)     /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  NP_number_pens(0, NULL);
-  AC_anchor_corner(0, NULL);
-  AD_define_alternate(0, NULL);
-  SD_define_standard(0, NULL);
-  CF_character_fill(0, NULL);
-  DI_absolute_direction(0, NULL);
-  DT_define_label_term(0, NULL);
-  DV_define_variable_path(0, NULL);
-  ES_extra_space(0, NULL);
-  FT_fill_type(0, NULL);
-  IW_input_window(0, NULL);
-  LA_line_attributes(0, NULL);
-  LO_label_origin(0, NULL);
-  LT_line_type(0, NULL);
-  PA_plot_absolute(0, NULL);
-  PolygonMode = 0;
-  RF_raster_fill(0, NULL);
-  SC_scale(0, NULL);
-  SM_symbol_mode(0, NULL);
-  SS_select_standard(0, NULL);
-  TD_transparent_data(0, NULL);
-  UL_user_line_type(0, NULL);
-}
-
-
-/*
- * 'IN_initialize()' - Initialize the plotter.
- */
-
-void
-IN_initialize(int     num_params,      /* I - Number of parameters */
-              param_t *params)         /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  DF_default_values(0, NULL);
-  PU_pen_up(0, NULL);
-  RO_rotate(0, NULL);
-  PS_plot_size(0, NULL);
-  WU_width_units(0, NULL);
-  PW_pen_width(0, NULL);
-
-  PenWidth = 1;
-
-  PenPosition[0] = PenPosition[1] = 0.0;
-}
-
-
-/*
- * 'IP_input_absolute()' - Set P1 and P2 values for the plot.
- */
-
-void
-IP_input_absolute(int     num_params,  /* I - Number of parameters */
-                  param_t *params)     /* I - Parameters */
-{
-  if (num_params == 0)
-  {
-    P1[0] = PageLeft / 72.0f * 1016.0f;
-    P1[1] = PageBottom / 72.0f * 1016.0f;
-    P2[0] = PageRight / 72.0f * 1016.0f;
-    P2[1] = PageTop / 72.0f * 1016.0f;
-  }
-  else if (num_params == 2)
-  {
-    P2[0] -= P1[0];
-    P2[1] -= P1[1];
-    P1[0] = params[0].value.number;
-    P1[1] = params[1].value.number;
-    P2[0] += P1[0];
-    P2[1] += P1[1];
-  }
-  else if (num_params == 4)
-  {
-    P1[0] = params[0].value.number;
-    P1[1] = params[1].value.number;
-    P2[0] = params[2].value.number;
-    P2[1] = params[3].value.number;
-  }
-
-  IW1[0] = 0.0;
-  IW1[1] = 0.0;
-  IW2[0] = 0.0;
-  IW2[1] = 0.0;
-
-  if (ScalingType < 0)
-  {
-    Scaling1[0] = P1[0];
-    Scaling1[0] = P1[1];
-    Scaling2[0] = P2[0];
-    Scaling2[1] = P2[1];
-  }
-
-  update_transform();
-}
-
-
-/*
- * 'IR_input_relative()' - Update P1 and P2.
- */
-
-void
-IR_input_relative(int     num_params,  /* I - Number of parameters */
-                  param_t *params)     /* I - Parameters */
-{
-  if (num_params == 0)
-  {
-    P1[0] = PageLeft / 72.0f * 1016.0f;
-    P1[1] = PageBottom / 72.0f * 1016.0f;
-    P2[0] = PageRight / 72.0f * 1016.0f;
-    P2[1] = PageTop / 72.0f * 1016.0f;
-  }
-  else if (num_params == 2)
-  {
-    P2[0] -= P1[0];
-    P2[1] -= P1[1];
-    P1[0] = params[0].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f;
-    P1[1] = params[1].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f;
-    P2[0] += P1[0];
-    P2[1] += P1[1];
-  }
-  else if (num_params == 4)
-  {
-    P1[0] = params[0].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f;
-    P1[1] = params[1].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f;
-    P2[0] = params[2].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f;
-    P2[1] = params[3].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f;
-  }
-
-  IW1[0] = 0.0;
-  IW1[1] = 0.0;
-  IW2[0] = 0.0;
-  IW2[1] = 0.0;
-
-  if (ScalingType < 0)
-  {
-    Scaling1[0] = P1[0];
-    Scaling1[0] = P1[1];
-    Scaling2[0] = P2[0];
-    Scaling2[1] = P2[1];
-  }
-
-  update_transform();
-}
-
-
-/*
- * 'IW_input_window()' - Setup an input window.
- */
-
-void
-IW_input_window(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  if (num_params == 0)
-  {
-    IW1[0] = PageLeft / 72.0f * 1016.0f;
-    IW1[1] = PageBottom / 72.0f * 1016.0f;
-    IW2[0] = PageRight / 72.0f * 1016.0f;
-    IW2[1] = PageTop / 72.0f * 1016.0f;
-  }
-  else if (num_params == 4)
-  {
-
-    if (ScalingType < 0)
-    {
-      IW1[0] = params[0].value.number;
-      IW1[1] = params[1].value.number;
-      IW2[0] = params[2].value.number;
-      IW2[1] = params[3].value.number;
-    }
-    else
-    {
-      IW1[0] = (Transform[0][0] * params[0].value.number +
-                Transform[0][1] * params[1].value.number +
-                Transform[0][2]) / 72.0f * 1016.0f;
-      IW1[1] = (Transform[1][0] * params[0].value.number +
-                Transform[1][1] * params[1].value.number +
-                Transform[1][2]) / 72.0f * 1016.0f;
-      IW2[0] = (Transform[0][0] * params[2].value.number +
-                Transform[0][1] * params[3].value.number +
-                Transform[0][2]) / 72.0f * 1016.0f;
-      IW2[1] = (Transform[1][0] * params[2].value.number +
-                Transform[1][1] * params[3].value.number +
-                Transform[1][2]) / 72.0f * 1016.0f;
-    }
-
-    fprintf(stderr, "DEBUG: IW%.0f,%.0f,%.0f,%.0f = [ %.0f %.0f %.0f %.0f ]\n",
-           params[0].value.number, params[1].value.number,
-           params[2].value.number, params[3].value.number,
-           IW1[0], IW1[1], IW2[0], IW2[1]);
-  }
-
-
-  update_transform();
-}
-
-
-/*
- * 'PG_advance_page()' - Eject the current page.
- */
-
-void
-PG_advance_page(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  if (PageDirty)
-  {
-    puts("grestore");
-    puts("showpage");
-
-    PageDirty = 0;
-  }
-}
-
-
-/*
- * 'PS_plot_size()' - Set the plot size.
- */
-
-void
-PS_plot_size(int     num_params,       /* I - Number of parameters */
-             param_t *params)          /* I - Parameters */
-{
-  switch (num_params)
-  {
-    case 0 : /* PS ; */
-        if (Rotation == 0 || Rotation == 180)
-        {
-          PlotSize[0] = PageWidth;
-          PlotSize[1] = PageLength;
-       }
-       else
-       {
-          PlotSize[0] = PageLength;
-          PlotSize[1] = PageWidth;
-       }
-
-       PlotSizeSet = 0;
-        break;
-    case 1 : /* PS length ; */
-        if (Rotation == 0 || Rotation == 180)
-        {
-          PlotSize[1] = 72.0f * params[0].value.number / 1016.0f;
-          PlotSize[0] = 0.75f * PlotSize[1];
-        }
-        else
-        {
-          PlotSize[0] = 72.0f * params[0].value.number / 1016.0f;
-          PlotSize[1] = 0.75f * PlotSize[0];
-        }
-
-       PlotSizeSet = 1;
-        break;
-    case 2 : /* PS length, width ; */
-       /*
-        * Unfortunately, it appears that NO application correctly
-       * sends a two-argument PS command as documented in the
-       * HP-GL/2 Reference Manual from HP.  Instead, applications
-       * send the width before the length, which causes all sorts
-       * of problems when scaling.
-       *
-       * Rather than fight it, we now look for them as width,length
-       * instead of length,width.
-       *
-       * Don't like it?  Send mail to the folks that make Ideas, Pro/E,
-       * AutoCAD, etc.
-       */
-
-        if (Rotation == 0 || Rotation == 180)
-        {
-          PlotSize[0] = 72.0f * params[0].value.number / 1016.0f;
-          PlotSize[1] = 72.0f * params[1].value.number / 1016.0f;
-        }
-        else
-        {
-          PlotSize[0] = 72.0f * params[1].value.number / 1016.0f;
-          PlotSize[1] = 72.0f * params[0].value.number / 1016.0f;
-        }
-
-       PlotSizeSet = 1;
-        break;
-  }
-
- /*
-  * This is required for buggy files that don't set the input window.
-  */
-
-  IP_input_absolute(0, NULL);
-}
-
-
-/*
- * 'RO_rotate()' - Rotate the plot.
- */
-
-void
-RO_rotate(int     num_params,  /* I - Number of parameters */
-          param_t *params)     /* I - Parameters */
-{
-  if (num_params == 0)
-    Rotation = 0;
-  else
-    Rotation = (int)params[0].value.number;
-
-  update_transform();
-}
-
-
-/*
- * 'RP_replot()' - Replot the current page.
- */
-
-void
-RP_replot(int     num_params,  /* I - Number of parameters */
-          param_t *params)     /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-}
-
-
-/*
- * 'SC_scale()' - Set user-defined scaling.
- */
-
-void
-SC_scale(int     num_params,   /* I - Number of parameters */
-         param_t *params)      /* I - Parameters */
-{
-  if (num_params == 0)
-  {
-    ScalingType = -1;
-    Scaling1[0] = P1[0];
-    Scaling1[0] = P1[1];
-    Scaling2[0] = P2[0];
-    Scaling2[1] = P2[1];
-  }
-  else if (num_params > 3)
-  {
-    Scaling1[0] = params[0].value.number;
-    Scaling2[0] = params[1].value.number;
-    Scaling1[1] = params[2].value.number;
-    Scaling2[1] = params[3].value.number;
-
-    if (num_params > 4)
-      ScalingType = (int)params[4].value.number;
-    else
-      ScalingType = 1;
-  }
-
-  update_transform();
-}
-
-
-/*
- * End of "$Id: hpgl-config.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-input.c b/filter/hpgl-input.c
deleted file mode 100644 (file)
index 195094c..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * "$Id: hpgl-input.c 7219 2008-01-14 22:00:02Z mike $"
- *
- *   HP-GL/2 input processing for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007-2009 by Apple Inc.
- *   Copyright 1993-2006 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   ParseCommand()   - Parse an HPGL/2 command.
- *   FreeParameters() - Free all string parameter values.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-#include <ctype.h>
-#include <cups/i18n.h>
-
-#define MAX_PARAMS 16384
-
-
-/*
- * 'ParseCommand()' - Parse an HPGL/2 command.
- *
- * Returns the number of parameters seen or -1 on EOF.
- */
-
-int                            /* O - -1 on EOF, # params otherwise */
-ParseCommand(FILE    *fp,      /* I - File to read from */
-             char    *name,    /* O - Name of command */
-             param_t **params) /* O - Parameter list */
-{
-  int          num_params,     /* Number of parameters seen */
-               ch,             /* Current char */
-               done,           /* Non-zero when the current command is read */
-               i;              /* Looping var */
-  char         buf[262144],    /* String buffer */
-               *bufptr;        /* Pointer into buffer */
-  float                temp;           /* Temporary parameter value */
-  static param_t p[MAX_PARAMS];        /* Parameter buffer */
-
-
-  num_params = 0;
-  done       = 0;
-
-  do
-  {
-    while ((ch = getc(fp)) != EOF)
-      if (strchr(" \t\r\n,;", ch) == NULL)
-        break;
-
-    if (ch == EOF)
-    {
-      return (-1);
-    }
-
-    if (ch == 0x1b)
-      switch (getc(fp))
-      {
-        case '.' : /* HP-GL/2 job control */
-            i = getc(fp);
-
-            if (strchr(")Z", i) != NULL)
-            {
-             /*
-              * 'Printer Off' command - look for next 'Printer On' command...
-              */
-
-              for (;;)
-              {
-                while ((i = getc(fp)) != EOF && i != 0x1b);
-
-                if (i == EOF)
-                  return (-1);
-
-                if (getc(fp) != '.')
-                  continue;
-
-                if ((i = getc(fp)) == '(' ||
-                    i == 'Y')
-                  break;
-              }
-            }
-            else if (strchr("@HIMNTI\003", i) != NULL)
-            {
-              while ((i = getc(fp)) != EOF && i != ':');
-            }
-            break;
-
-        case '%' : /* PJL command? */
-            if ((i = getc(fp)) == '-')
-             if ((i = getc(fp)) == '1')
-               if ((i = getc(fp)) == '2')
-               {
-                /*
-                 * Yes, dump everything up to the "ENTER LANGUAGE" line...
-                 */
-
-                 while (fgets(buf, sizeof(buf), fp) != NULL)
-                   if (strstr(buf, "ENTER") && strstr(buf, "LANGUAGE"))
-                     break;
-                 break;
-               }
-
-            ungetc(i, fp);
-
-        default : /* HP RTL/PCL control */
-            while ((i = getc(fp)) != EOF && !isupper(i & 255));
-
-           if (i == EOF)
-             return (-1);
-            break;
-      }
-  } while (ch < ' ');
-
-  name[0] = ch;
-  name[1] = getc(fp);
-  name[2] = '\0';
-
-  if (name[1] < ' ')
-  {
-   /*
-    * If we get here, then more than likely we are faced with a raw PCL
-    * file which we can't handle - abort!
-    */
-
-    fputs(_("ERROR: Invalid HP-GL/2 command seen, unable to print file\n"),
-          stderr);
-    return (-1);
-  }
-
-  if (!strcasecmp(name, "LB"))
-  {
-    bufptr = buf;
-    while ((ch = getc(fp)) != StringTerminator && ch != EOF)
-      if (bufptr < (buf + sizeof(buf) - 1))
-        *bufptr++ = ch;
-    *bufptr = '\0';
-
-    p[num_params].type         = PARAM_STRING;
-    p[num_params].value.string = strdup(buf);
-    num_params ++;
-  }
-  else if (!strcasecmp(name, "SM"))
-  {
-    buf[0] = getc(fp);
-    buf[1] = '\0';
-    p[num_params].type         = PARAM_STRING;
-    p[num_params].value.string = strdup(buf);
-    num_params ++;
-  }
-  else if (!strcasecmp(name, "DT"))
-  {
-    if ((buf[0] = getc(fp)) != ';')
-    {
-      buf[1] = '\0';
-      p[num_params].type         = PARAM_STRING;
-      p[num_params].value.string = strdup(buf);
-      num_params ++;
-    }
-  }
-  else if (!strcasecmp(name, "PE"))
-  {
-    bufptr = buf;
-    while ((ch = getc(fp)) != ';')
-      if (ch == EOF)
-        break;
-      else if (bufptr < (buf + sizeof(buf) - 1))
-        *bufptr++ = ch;
-    *bufptr = '\0';
-
-    p[num_params].type         = PARAM_STRING;
-    p[num_params].value.string = strdup(buf);
-    num_params ++;
-  }
-
-  while (!done)
-    switch (ch = getc(fp))
-    {
-      case EOF :
-          done = 1;
-          break;
-
-      case ',' :
-      case ' ' :
-      case '\n' :
-      case '\r' :
-      case '\t' :
-          break;
-
-      case '\"' :
-          fscanf(fp, "%262143[^\"]\"", buf);
-          if (num_params < MAX_PARAMS)
-          {
-            p[num_params].type         = PARAM_STRING;
-            p[num_params].value.string = strdup(buf);
-            num_params ++;
-          };
-          break;
-
-      case '-' :
-      case '+' :
-          ungetc(ch, fp);
-          if (fscanf(fp, "%f", &temp) == 1 && num_params < MAX_PARAMS)
-          {
-            p[num_params].type         = PARAM_RELATIVE;
-            p[num_params].value.number = temp;
-            num_params ++;
-          }
-          break;
-      case '0' :
-      case '1' :
-      case '2' :
-      case '3' :
-      case '4' :
-      case '5' :
-      case '6' :
-      case '7' :
-      case '8' :
-      case '9' :
-      case '.' :
-          ungetc(ch, fp);
-          if (fscanf(fp, "%f", &temp) == 1 && num_params < MAX_PARAMS)
-          {
-            p[num_params].type         = PARAM_ABSOLUTE;
-            p[num_params].value.number = temp;
-            num_params ++;
-          }
-          break;
-      default :
-          ungetc(ch, fp);
-          done = 1;
-          break;
-    }
-
-  *params = p;
-  return (num_params);
-}
-
-
-/*
- * 'FreeParameters()' - Free all string parameter values.
- */
-
-void
-FreeParameters(int     num_params,     /* I - Number of parameters */
-               param_t *params)                /* I - Parameter values */
-{
-  int  i;                              /* Looping var */
-
-
-  for (i = 0; i < num_params; i ++)
-    if (params[i].type == PARAM_STRING)
-      free(params[i].value.string);
-}
-
-
-/*
- * End of "$Id: hpgl-input.c 7219 2008-01-14 22:00:02Z mike $".
- */
diff --git a/filter/hpgl-main.c b/filter/hpgl-main.c
deleted file mode 100644 (file)
index 953d447..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * "$Id: hpgl-main.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 filter main entry for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007-2008 by Apple Inc.
- *   Copyright 1993-2007 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   main()          - Main entry for HP-GL/2 filter.
- *   compare_names() - Compare two command names.
- */
-
-/*
- * Include necessary headers...
- */
-
-/*#define DEBUG*/
-#define _HPGL_MAIN_C_
-#include "hpgltops.h"
-#include <cups/i18n.h>
-
-
-/*
- * HP-GL/2 command table...
- */
-
-typedef struct
-{
-  char name[4];                        /* Name of command */
-  void (*func)(int, param_t *);        /* Function to call */
-} name_t;
-
-static name_t commands[] =
-{
-  { "BP", BP_begin_plot },
-  { "DF", DF_default_values },
-  { "IN", IN_initialize },
-  { "IP", IP_input_absolute },
-  { "IR", IR_input_relative },
-  { "IW", IW_input_window },
-  { "PG", PG_advance_page },
-  { "RO", RO_rotate },
-  { "RP", RP_replot },
-  { "SC", SC_scale },
-  { "AA", AA_arc_absolute },
-  { "AR", AR_arc_relative },
-  { "AT", AT_arc_absolute3 },
-  { "CI", CI_circle },
-  { "PA", PA_plot_absolute },
-  { "PD", PD_pen_down },
-  { "PE", PE_polyline_encoded },
-  { "PR", PR_plot_relative },
-  { "PS", PS_plot_size },
-  { "PU", PU_pen_up },
-  { "RT", RT_arc_relative3 },
-  { "EA", EA_edge_rect_absolute },
-  { "EP", EP_edge_polygon },
-  { "ER", ER_edge_rect_relative },
-  { "EW", EW_edge_wedge },
-  { "FP", FP_fill_polygon },
-  { "PM", PM_polygon_mode },
-  { "RA", RA_fill_rect_absolute },
-  { "RR", RR_fill_rect_relative },
-  { "WG", WG_fill_wedge },
-  { "AD", AD_define_alternate },
-  { "CF", CF_character_fill },
-  { "CP", CP_character_plot },
-  { "DI", DI_absolute_direction },
-  { "DR", DR_relative_direction },
-  { "DT", DT_define_label_term },
-  { "DV", DV_define_variable_path },
-  { "ES", ES_extra_space },
-  { "LB", LB_label },
-  { "LO", LO_label_origin },
-  { "SA", SA_select_alternate },
-  { "SD", SD_define_standard },
-  { "SI", SI_absolute_size },
-  { "SL", SL_character_slant },
-  { "SR", SR_relative_size },
-  { "SS", SS_select_standard },
-  { "TD", TD_transparent_data },
-  { "AC", AC_anchor_corner },
-  { "FT", FT_fill_type },
-  { "LA", LA_line_attributes },
-  { "LT", LT_line_type },
-  { "NP", NP_number_pens },
-  { "PC", PC_pen_color },
-  { "CR", CR_color_range },
-  { "PW", PW_pen_width },
-  { "RF", RF_raster_fill },
-  { "SM", SM_symbol_mode },
-  { "SP", SP_select_pen },
-  { "UL", UL_user_line_type },
-  { "WU", WU_width_units }
-};
-#define NUM_COMMANDS (sizeof(commands) / sizeof(name_t))
-
-
-/*
- * Local functions...
- */
-
-static int     compare_names(const void *p1, const void *p2);
-
-
-/*
- * 'main()' - Main entry for HP-GL/2 filter.
- */
-
-int                    /* O - Exit status */
-main(int  argc,                /* I - Number of command-line arguments */
-     char *argv[])     /* I - Command-line arguments */
-{
-  FILE         *fp;            /* Input file */
-  int          num_params;     /* Number of parameters */
-  param_t      *params;        /* Command parameters */
-  name_t       *command,       /* Command */
-               name;           /* Name of command */
-  int          num_options;    /* Number of print options */
-  cups_option_t        *options;       /* Print options */
-  const char   *val;           /* Option value */
-  int          shading;        /* -1 = black, 0 = grey, 1 = color */
-
-
- /*
-  * Make sure status messages are not buffered...
-  */
-
-  setbuf(stdout, NULL);
-  setbuf(stderr, NULL);
-
- /*
-  * Check command-line...
-  */
-
-  if (argc < 6 || argc > 7)
-  {
-    fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
-            argv[0]);
-    return (1);
-  }
-
- /*
-  * If we have 7 arguments, print the file named on the command-line.
-  * Otherwise, send stdin instead...
-  */
-
-  if (argc == 6)
-    fp = stdin;
-  else
-  {
-   /*
-    * Try to open the print file...
-    */
-
-    if ((fp = fopen(argv[6], "rb")) == NULL)
-    {
-      perror("DEBUG: unable to open print file - ");
-      return (1);
-    }
-  }
-
- /*
-  * Process command-line options and write the prolog...
-  */
-
-  options     = NULL;
-  num_options = cupsParseOptions(argv[5], 0, &options);
-
-  PPD = SetCommonOptions(num_options, options, 1);
-
-  PlotSize[0] = PageWidth;
-  PlotSize[1] = PageLength;
-
-  shading  = 1;
-  PenWidth = 1.0;
-
-  if ((val = cupsGetOption("blackplot", num_options, options)) != NULL &&
-      strcasecmp(val, "no") && strcasecmp(val, "off") &&
-      strcasecmp(val, "false"))
-    shading = 0;
-
-  if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
-      !strcasecmp(val, "true"))
-    FitPlot = 1;
-  else if ((val = cupsGetOption("fit-to-page", num_options, options)) != NULL &&
-      !strcasecmp(val, "true"))
-    FitPlot = 1;
-
-  if ((val = cupsGetOption("penwidth", num_options, options)) != NULL)
-    PenWidth = (float)atoi(val) * 0.001f;
-
- /*
-  * Write the PostScript prolog and initialize the plotting "engine"...
-  */
-
-  OutputProlog(argv[3], argv[2], shading);
-
-  IP_input_absolute(0, NULL);
-
- /*
-  * Sort the command array...
-  */
-
-  qsort(commands, NUM_COMMANDS, sizeof(name_t),
-        (int (*)(const void *, const void *))compare_names);
-
- /*
-  * Read commands until we reach the end of file.
-  */
-
-  while ((num_params = ParseCommand(fp, name.name, &params)) >= 0)
-  {
-    Outputf("%% %s(%d)\n", name.name, num_params);
-
-#ifdef DEBUG
-    {
-      int i;
-      fprintf(stderr, "DEBUG: %s(%d)", name.name, num_params);
-      for (i = 0; i < num_params; i ++)
-       if (params[i].type == PARAM_STRING)
-          fprintf(stderr, " \'%s\'", params[i].value.string);
-       else
-          fprintf(stderr, " %f", params[i].value.number);
-      fputs("\n", stderr);
-    }
-#endif /* DEBUG */
-
-    if ((command = bsearch(&name, commands, NUM_COMMANDS, sizeof(name_t),
-                           (int (*)(const void *, const void *))compare_names)) != NULL)
-      (*command->func)(num_params, params);
-
-    FreeParameters(num_params, params);
-  }
-
-  OutputTrailer();
-
-  if (fp != stdin)
-    fclose(fp);
-
-  return (0);
-}
-
-
-/*
- * 'compare_names()' - Compare two command names.
- */
-
-static int                     /* O - Result of strcasecmp() on names */
-compare_names(const void *p1,  /* I - First name */
-              const void *p2)  /* I - Second name */
-{
-  return (strcasecmp(((name_t *)p1)->name, ((name_t *)p2)->name));
-}
-
-
-/*
- * End of "$Id: hpgl-main.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-polygon.c b/filter/hpgl-polygon.c
deleted file mode 100644 (file)
index 6f8df01..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * "$Id: hpgl-polygon.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 polygon routines for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1993-2005 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   EA_edge_rect_absolute() - Draw a rectangle.
- *   EP_edge_polygon()       - Stroke the edges of a polygon.
- *   ER_edge_rect_relative() - Draw a rectangle relative to the current
- *   EW_edge_wedge()         - Draw a pie wedge.
- *   FP_fill_polygon()       - Fill a polygon.
- *   PM_polygon_mode()       - Set the polygon drawing mode.
- *   RA_fill_rect_absolute() - Fill a rectangle.
- *   RR_fill_rect_relative() - Fill a rectangle relative to the current
- *   WG_fill_wedge()         - Fill a pie wedge.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-
-
-/*
- * 'EA_edge_rect_absolute()' - Draw a rectangle.
- */
-
-void
-EA_edge_rect_absolute(int     num_params,      /* I - Number of parameters */
-                      param_t *params)         /* I - Parameters */
-{
-  float        x, y;           /* Transformed coordinates */
-
-
-  if (num_params < 2)
-    return;
-
-  x = Transform[0][0] * params[0].value.number +
-      Transform[0][1] * params[1].value.number +
-      Transform[0][2];
-  y = Transform[1][0] * params[0].value.number +
-      Transform[1][1] * params[1].value.number +
-      Transform[1][2];
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-  Outputf("%.3f %.3f LI\n", PenPosition[0], y);
-  Outputf("%.3f %.3f LI\n", x, y);
-  Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("ST\n");
-}
-
-
-/*
- * 'EP_edge_polygon()' - Stroke the edges of a polygon.
- */
-
-void
-EP_edge_polygon(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  Outputf("ST\n");
-}
-
-
-/*
- * 'ER_edge_rect_relative()' - Draw a rectangle relative to the current
- *                             pen position.
- */
-
-void
-ER_edge_rect_relative(int     num_params,      /* I - Number of parameters */
-                      param_t *params)         /* I - Parameters */
-{
-  float x, y;          /* Transformed coordinates */
-
-
-  if (num_params < 2)
-    return;
-
-  x = Transform[0][0] * params[0].value.number +
-      Transform[0][1] * params[1].value.number +
-      PenPosition[0];
-  y = Transform[1][0] * params[0].value.number +
-      Transform[1][1] * params[1].value.number +
-      PenPosition[1];
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-  Outputf("%.3f %.3f LI\n", PenPosition[0], y);
-  Outputf("%.3f %.3f LI\n", x, y);
-  Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("ST\n");
-}
-
-
-/*
- * 'EW_edge_wedge()' - Draw a pie wedge.
- */
-
-void
-EW_edge_wedge(int     num_params,      /* I - Number of parameters */
-              param_t *params)         /* I - Parameters */
-{
-  float x, y;                          /* Transformed coordinates */
-  float start, end,                    /* Start and end of arc */
-       theta,                          /* Current angle */
-       dt,                             /* Step between points */
-       radius;                         /* Radius of arc */
-
-
-  if (num_params < 3)
-    return;
-
-  radius = params[0].value.number;
-  start  = params[1].value.number;
-  end    = start + params[2].value.number;
-
-  if (num_params > 3)
-    dt = (float)fabs(params[3].value.number);
-  else
-    dt = 5.0f;
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-  if (start < end)
-    for (theta = start + dt; theta < end; theta += dt)
-    {
-      x = (float)(PenPosition[0] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
-      y = (float)(PenPosition[1] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
-
-      Outputf("%.3f %.3f LI\n", x, y);
-    }
-  else
-    for (theta = start - dt; theta > end; theta -= dt)
-    {
-      x = (float)(PenPosition[0] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
-      y = (float)(PenPosition[1] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
-
-      Outputf("%.3f %.3f LI\n", x, y);
-    }
-
-  x = (float)(PenPosition[0] +
-              radius * cos(M_PI * end / 180.0) * Transform[0][0] +
-              radius * sin(M_PI * end / 180.0) * Transform[0][1]);
-  y = (float)(PenPosition[1] +
-              radius * cos(M_PI * end / 180.0) * Transform[1][0] +
-              radius * sin(M_PI * end / 180.0) * Transform[1][1]);
-  Outputf("%.3f %.3f LI\n", x, y);
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("ST\n");
-}
-
-
-/*
- * 'FP_fill_polygon()' - Fill a polygon.
- */
-
-void
-FP_fill_polygon(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  (void)num_params;
-  (void)params;
-
-  Outputf("FI\n");
-}
-
-
-/*
- * 'PM_polygon_mode()' - Set the polygon drawing mode.
- */
-
-void
-PM_polygon_mode(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  if (num_params == 0 ||
-      params[0].value.number == 0)
-  {
-    Outputf("MP\n");
-    PenValid    = 0;
-    PolygonMode = 1;
-  }
-  else if (params[0].value.number == 2)
-    PolygonMode = 0;
-}
-
-
-/*
- * 'RA_fill_rect_absolute()' - Fill a rectangle.
- */
-
-void
-RA_fill_rect_absolute(int     num_params,      /* I - Number of parameters */
-                      param_t *params)         /* I - Parameters */
-{
-  float x, y;                  /* Transformed coordinates */
-
-
-  if (num_params < 2)
-    return;
-
-  x = Transform[0][0] * params[0].value.number +
-      Transform[0][1] * params[1].value.number +
-      Transform[0][2];
-  y = Transform[1][0] * params[0].value.number +
-      Transform[1][1] * params[1].value.number +
-      Transform[1][2];
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-  Outputf("%.3f %.3f LI\n", PenPosition[0], y);
-  Outputf("%.3f %.3f LI\n", x, y);
-  Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("FI\n");
-}
-
-
-/*
- * 'RR_fill_rect_relative()' - Fill a rectangle relative to the current
- *                             pen position.
- */
-
-void
-RR_fill_rect_relative(int     num_params,      /* I - Number of parameters */
-                      param_t *params)         /* I - Parameters */
-{
-  float x, y;                  /* Transformed coordinates */
-
-
-  if (num_params < 2)
-    return;
-
-  x = Transform[0][0] * params[0].value.number +
-      Transform[0][1] * params[1].value.number +
-      PenPosition[0];
-  y = Transform[1][0] * params[0].value.number +
-      Transform[1][1] * params[1].value.number +
-      PenPosition[1];
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-  Outputf("%.3f %.3f LI\n", PenPosition[0], y);
-  Outputf("%.3f %.3f LI\n", x, y);
-  Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("FI\n");
-}
-
-
-/*
- * 'WG_fill_wedge()' - Fill a pie wedge.
- */
-
-void
-WG_fill_wedge(int     num_params,      /* I - Number of parameters */
-              param_t *params)         /* I - Parameters */
-{
-  float x, y;                          /* Transformed coordinates */
-  float start, end,                    /* Start and end angles */
-       theta,                          /* Current angle */
-       dt,                             /* Step between points */
-       radius;                         /* Radius of arc */
-
-
-  if (num_params < 3)
-    return;
-
-  radius = params[0].value.number;
-  start  = params[1].value.number;
-  end    = start + params[2].value.number;
-
-  if (num_params > 3)
-    dt = (float)fabs(params[3].value.number);
-  else
-    dt = 5.0;
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-  if (start < end)
-    for (theta = start + dt; theta < end; theta += dt)
-    {
-      x = (float)(PenPosition[0] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
-      y = (float)(PenPosition[1] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
-
-      Outputf("%.3f %.3f LI\n", x, y);
-    }
-  else
-    for (theta = start - dt; theta > end; theta -= dt)
-    {
-      x = (float)(PenPosition[0] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
-      y = (float)(PenPosition[1] +
-                  radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
-                  radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
-
-      Outputf("%.3f %.3f LI\n", x, y);
-    }
-
-  x = (float)(PenPosition[0] +
-              radius * cos(M_PI * end / 180.0) * Transform[0][0] +
-              radius * sin(M_PI * end / 180.0) * Transform[0][1]);
-  y = (float)(PenPosition[1] +
-              radius * cos(M_PI * end / 180.0) * Transform[1][0] +
-              radius * sin(M_PI * end / 180.0) * Transform[1][1]);
-  Outputf("%.3f %.3f LI\n", x, y);
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("FI\n");
-}
-
-
-/*
- * End of "$Id: hpgl-polygon.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-prolog.c b/filter/hpgl-prolog.c
deleted file mode 100644 (file)
index 00e512b..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * "$Id: hpgl-prolog.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 prolog routines for for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1993-2007 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *  OutputProlog()  - Output the PostScript prolog...
- *  OutputTrailer() - Output the PostScript trailer...
- *  Outputf()       - Write a formatted string to the output file, creating the
- *                    page header as needed...
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-#include <stdarg.h>
-
-
-/*
- * 'OutputProlog()' - Output the PostScript prolog...
- */
-
-void
-OutputProlog(char  *title,     /* I - Job title */
-             char  *user,      /* I - Username */
-             int   shading)    /* I - Type of shading */
-{
-  FILE         *prolog;        /* Prolog file */
-  char         line[255];      /* Line from prolog file */
-  const char   *datadir;       /* CUPS_DATADIR environment variable */
-  char         filename[1024]; /* Name of prolog file */
-  time_t       curtime;        /* Current time */
-  struct tm    *curtm;         /* Current date */
-
-
-  curtime = time(NULL);
-  curtm   = localtime(&curtime);
-
-  puts("%!PS-Adobe-3.0");
-  printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
-         PageLeft, PageBottom, PageRight, PageTop);
-  puts("%%Pages: (atend)");
-  printf("%%%%LanguageLevel: %d\n", LanguageLevel);
-  puts("%%DocumentData: Clean7Bit");
-  puts("%%DocumentSuppliedResources: procset hpgltops 1.1 0");
-  puts("%%DocumentNeededResources: font Courier Helvetica");
-  puts("%%Creator: hpgltops/" CUPS_SVERSION);
-  strftime(line, sizeof(line), "%c", curtm);
-  printf("%%%%CreationDate: %s\n", line);
-  WriteTextComment("Title", title);
-  WriteTextComment("For", user);
-  printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
-  puts("%%EndComments");
-  puts("%%BeginProlog");
-  printf("/DefaultPenWidth %.2f def\n", PenWidth * 72.0 / 25.4);
-  if (!shading)                        /* Black only */
-    puts("/setrgbcolor { pop pop pop } bind def");
-  else if (!ColorDevice)       /* Greyscale */
-    puts("/setrgbcolor { 0.08 mul exch 0.61 mul add exch 0.31 mul add setgray } bind def\n");
-
-  if ((datadir = getenv("CUPS_DATADIR")) == NULL)
-    datadir = CUPS_DATADIR;
-
-  snprintf(filename, sizeof(filename), "%s/data/HPGLprolog", datadir);
-
-  if ((prolog = fopen(filename, "r")) == NULL)
-  {
-    fprintf(stderr,
-            "DEBUG: Unable to open HPGL prolog \"%s\" for reading - %s\n",
-            filename, strerror(errno));
-    exit(1);
-  }
-
-  while (fgets(line, sizeof(line), prolog) != NULL)
-    fputs(line, stdout);
-
-  fclose(prolog);
-
-  puts("%%EndProlog");
-
-  IN_initialize(0, NULL);
-}
-
-
-/*
- * 'OutputTrailer()' - Output the PostScript trailer...
- */
-
-void
-OutputTrailer(void)
-{
-  if (PageDirty)
-    PG_advance_page(0, NULL);
-
-  puts("%%Trailer");
-  printf("%%%%Pages: %d\n", PageCount);
-  puts("%%EOF");
-}
-
-
-/*
- * 'Outputf()' - Write a formatted string to the output file, creating the
- *               page header as needed...
- */
-
-int                            /* O - Number of bytes written */
-Outputf(const char *format,    /* I - Printf-style string */
-        ...)                   /* I - Additional args as needed */
-{
-  va_list      ap;             /* Argument pointer */
-  int          bytes;          /* Number of bytes written */
-  float                iw1[2], iw2[2]; /* Clipping window */
-  int          i;              /* Looping var */
-  ppd_size_t   *size;          /* Page size */
-  ppd_option_t *option;        /* Page size option */
-  ppd_choice_t *choice;        /* Page size choice */
-  float                width, length;  /* Page dimensions */
-  int          landscape;      /* Rotate for landscape orientation? */
-
-
- /*
-  * Write the page header as needed...
-  */
-
-  if (!PageDirty)
-  {
-    PageDirty = 1;
-    PageCount ++;
-
-    printf("%%%%Page: %d %d\n", PageCount, PageCount);
-
-    landscape = 0;
-
-    if (!FitPlot && PlotSizeSet)
-    {
-     /*
-      * Set the page size for this page...
-      */
-
-      if (PageRotation == 0 || PageRotation == 180)
-      {
-       width  = PlotSize[0];
-       length = PlotSize[1];
-      }
-      else
-      {
-       width  = PlotSize[1];
-       length = PlotSize[0];
-      }
-
-      fprintf(stderr, "DEBUG: hpgltops setting page size (%.0f x %.0f)\n",
-              width, length);
-
-      if (PPD != NULL)
-      {
-        fputs("DEBUG: hpgltops has a PPD file!\n", stderr);
-
-       /*
-       * Lookup the closest PageSize and set it...
-       */
-
-       for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++)
-         if ((fabs(length - size->length) < 36.0 && size->width >= width) ||
-              (fabs(length - size->width) < 36.0 && size->length >= width))
-           break;
-
-       if (i == 0 && PPD->variable_sizes)
-       {
-          for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++)
-           if (strcasecmp(size->name, "custom") == 0)
-             break;
-       } 
-
-       if (i > 0)
-       {
-        /*
-         * Found a matching size...
-         */
-
-         option = ppdFindOption(PPD, "PageSize");
-         choice = ppdFindChoice(option, size->name);
-
-          puts("%%BeginPageSetup");
-          printf("%%%%BeginFeature: PageSize %s\n", size->name);
-
-          if (strcasecmp(size->name, "custom") == 0)
-         {
-           PageLeft   = PPD->custom_margins[0];
-           PageRight  = width - PPD->custom_margins[2];
-           PageWidth  = width;
-           PageBottom = PPD->custom_margins[1];
-           PageTop    = length - PPD->custom_margins[3];
-           PageLength = length;
-
-            printf("%.0f %.0f 0 0 0\n", width, length);
-
-           if (choice->code == NULL)
-           {
-            /*
-             * This can happen with certain buggy PPD files that don't include
-             * a CustomPageSize command sequence...  We just use a generic
-             * Level 2 command sequence...
-             */
-
-             puts("pop pop pop");
-             puts("<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n");
-           }
-            else
-           {
-            /*
-             * Use the vendor-supplied command...
-             */
-
-             printf("%s\n", choice->code);
-           }
-         }
-         else
-         {
-           if (choice->code)
-              printf("%s\n", choice->code);
-
-           if (fabs(length - size->width) < 36.0)
-           {
-            /*
-              * Do landscape orientation...
-             */
-
-             PageLeft   = size->bottom;
-             PageRight  = size->top;
-             PageWidth  = size->length;
-             PageBottom = size->left;
-             PageTop    = size->right;
-             PageLength = size->width;
-
-              landscape = 1;
-           }
-           else
-           {
-            /*
-              * Do portrait orientation...
-             */
-
-             PageLeft   = size->left;
-             PageRight  = size->right;
-             PageWidth  = size->width;
-             PageBottom = size->bottom;
-             PageTop    = size->top;
-             PageLength = size->length;
-           }
-         }
-
-         puts("%%EndFeature");
-         puts("%%EndPageSetup");
-       }
-      }
-      else
-      {
-        fputs("DEBUG: hpgltops does not have a PPD file!\n", stderr);
-
-        puts("%%BeginPageSetup");
-        printf("%%%%BeginFeature: PageSize w%.0fh%.0f\n", width, length);
-       printf("<</PageSize[%.0f %.0f]/ImageBBox null>>setpagedevice\n",
-              width, length);
-       puts("%%EndFeature");
-       puts("%%EndPageSetup");
-
-       PageLeft   = 0.0;
-       PageRight  = width;
-       PageWidth  = width;
-       PageBottom = 0.0;
-       PageTop    = length;
-       PageLength = length;
-      }
-    }
-
-    define_font(0);
-    define_font(1);
-
-    printf("%.1f setmiterlimit\n", MiterLimit);
-    printf("%d setlinecap\n", LineCap);
-    printf("%d setlinejoin\n", LineJoin);
-
-    printf("%.3f %.3f %.3f %.2f SP\n", Pens[1].rgb[0], Pens[1].rgb[1],
-           Pens[1].rgb[2], Pens[1].width * PenScaling);
-
-    puts("gsave");
-
-    if (Duplex && (PageCount & 1) == 0)
-      switch ((PageRotation / 90 + landscape) & 3)
-      {
-       case 0 :
-            printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
-           break;
-       case 1 :
-            printf("%.0f 0 translate 90 rotate\n", PageLength);
-            printf("%.1f %.1f translate\n", PageLength - PageTop,
-                  PageWidth - PageRight);
-           break;
-       case 2 :
-            printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
-            printf("%.1f %.1f translate\n", PageLeft, PageLength - PageTop);
-           break;
-       case 3 :
-            printf("0 %.0f translate -90 rotate\n", PageWidth);
-            printf("%.1f %.1f translate\n", PageBottom, PageLeft);
-           break;
-      }
-    else
-      switch ((PageRotation / 90 + landscape) & 3)
-      {
-       case 0 :
-            printf("%.1f %.1f translate\n", PageLeft, PageBottom);
-           break;
-       case 1 :
-            printf("%.0f 0 translate 90 rotate\n", PageLength);
-            printf("%.1f %.1f translate\n", PageBottom, PageWidth - PageRight);
-           break;
-       case 2 :
-            printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
-            printf("%.1f %.1f translate\n", PageWidth - PageRight,
-                   PageLength - PageTop);
-           break;
-       case 3 :
-            printf("0 %.0f translate -90 rotate\n", PageWidth);
-            printf("%.1f %.1f translate\n", PageLength - PageTop, PageLeft);
-           break;
-      }
-
-    if (IW1[0] != IW2[0] && IW1[1] != IW2[1])
-    {
-      iw1[0] = IW1[0] * 72.0f / 1016.0f;
-      iw1[1] = IW1[1] * 72.0f / 1016.0f;
-      iw2[0] = IW2[0] * 72.0f / 1016.0f;
-      iw2[1] = IW2[1] * 72.0f / 1016.0f;
-
-      printf("initclip MP %.3f %.3f MO %.3f %.3f LI %.3f %.3f LI %.3f %.3f LI CP clip\n",
-            iw1[0], iw1[1], iw1[0], iw2[1], iw2[0], iw2[1], iw2[0], iw1[1]);
-    }
-  }
-
- /*
-  * Write the string to the output file...
-  */
-
-  va_start(ap, format);
-  bytes = vprintf(format, ap);
-  va_end(ap);
-
-  return (bytes);
-}
-
-
-/*
- * End of "$Id: hpgl-prolog.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgl-vector.c b/filter/hpgl-vector.c
deleted file mode 100644 (file)
index fdf8664..0000000
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * "$Id: hpgl-vector.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 vector routines for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007-2008 by Apple Inc.
- *   Copyright 1993-2007 by Easy Software Products.
- *
- *   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.
- *
- * Contents:
- *
- *   AA_arc_absolute()    - Draw an arc.
- *   AR_arc_relative()    - Draw an arc relative to the current pen
- *   AT_arc_absolute3()   - Draw an arc using 3 points.
- *   CI_circle()          - Draw a circle.
- *   PA_plot_absolute()   - Plot a line using absolute coordinates.
- *   PD_pen_down()        - Start drawing.
- *   PE_polygon_encoded() - Draw an encoded polyline.
- *   PR_plot_relative()   - Plot a line using relative coordinates.
- *   PU_pen_up()          - Stop drawing.
- *   RT_arc_relative3()   - Draw an arc through 3 points relative to the
- *   decode_number()      - Decode an encoded number.
- *   plot_points()        - Plot the specified points.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "hpgltops.h"
-
-
-/*
- * Local functions...
- */
-
-static double  decode_number(unsigned char **, int, double);
-static void    plot_points(int, param_t *);
-
-
-/*
- * 'AA_arc_absolute()' - Draw an arc.
- */
-
-void
-AA_arc_absolute(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  float x, y,                          /* Transformed coordinates */
-       dx, dy;                         /* Distance from current pen */
-  float start, end,                    /* Start and end angles */
-       theta,                          /* Current angle */
-       dt,                             /* Step between points */
-       radius;                         /* Radius of arc */
-
-
-  if (num_params < 3)
-    return;
-
-  x = Transform[0][0] * params[0].value.number +
-      Transform[0][1] * params[1].value.number +
-      Transform[0][2];
-  y = Transform[1][0] * params[0].value.number +
-      Transform[1][1] * params[1].value.number +
-      Transform[1][2];
-
-  dx = PenPosition[0] - x;
-  dy = PenPosition[1] - y;
-
-  start = (float)(180.0 * atan2(dy, dx) / M_PI);
-  if (start < 0.0)
-    start += 360.0f;
-
-  end    = start + params[2].value.number;
-  radius = (float)hypot(dx, dy);
-
-  if (PenDown)
-  {
-    if (num_params > 3 && params[3].value.number > 0.0)
-      dt = (float)fabs(params[3].value.number);
-    else
-      dt = 5.0;
-
-    if (!PolygonMode)
-      Outputf("MP\n");
-
-    PenValid = 1;
-
-    Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-    if (start < end)
-      for (theta = start + dt; theta < end; theta += dt)
-      {
-       PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
-       PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
-
-       Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-      }
-    else
-      for (theta = start - dt; theta > end; theta -= dt)
-      {
-       PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
-       PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
-
-       Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-      }
-  }
-
-  PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
-  PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
-
-  if (PenDown)
-  {
-    Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-
-    if (!PolygonMode)
-      Outputf("ST\n");
-  }
-}
-
-
-/*
- * 'AR_arc_relative()' - Draw an arc relative to the current pen
- *                       position.
- */
-
-void
-AR_arc_relative(int     num_params,    /* I - Number of parameters */
-                param_t *params)       /* I - Parameters */
-{
-  float x, y,                          /* Transformed coordinates */
-       dx, dy;                         /* Distance from current pen */
-  float start, end,                    /* Start and end angles */
-       theta,                          /* Current angle */
-       dt,                             /* Step between points */
-       radius;                         /* Radius of arc */
-
-
-  if (num_params < 3)
-    return;
-
-  x = Transform[0][0] * params[0].value.number +
-      Transform[0][1] * params[1].value.number +
-      PenPosition[0];
-  y = Transform[1][0] * params[0].value.number +
-      Transform[1][1] * params[1].value.number +
-      PenPosition[1];
-
-  dx = PenPosition[0] - x;
-  dy = PenPosition[1] - y;
-
-  start = (float)(180.0 * atan2(dy, dx) / M_PI);
-  if (start < 0.0)
-    start += 360.0f;
-
-  end    = start + params[2].value.number;
-  radius = (float)hypot(dx, dy);
-
-  if (PenDown)
-  {
-    if (num_params > 3 && params[3].value.number > 0.0)
-      dt = (float)fabs(params[3].value.number);
-    else
-      dt = 5.0;
-
-    if (!PolygonMode)
-      Outputf("MP\n");
-
-    PenValid = 1;
-
-    Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-    if (start < end)
-      for (theta = start + dt; theta < end; theta += dt)
-      {
-       PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
-       PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
-
-       Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-      }
-    else
-      for (theta = start - dt; theta > end; theta -= dt)
-      {
-       PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
-       PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
-
-       Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-      }
-  }
-
-  PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
-  PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
-
-  if (PenDown)
-  {
-    Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-
-    if (!PolygonMode)
-      Outputf("ST\n");
-  }
-}
-
-
-/*
- * 'AT_arc_absolute3()' - Draw an arc using 3 points.
- *
- * Note:
- *
- *   Currently this only draws two line segments through the
- *   specified points.
- */
-
-void
-AT_arc_absolute3(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  if (num_params < 4)
-    return;
-
-  if (PenDown)
-  {
-    if (!PolygonMode)
-      Outputf("MP\n");
-
-    PenValid = 1;
-
-    Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-    PenPosition[0] = Transform[0][0] * params[0].value.number +
-                     Transform[0][1] * params[1].value.number +
-                     Transform[0][2];
-    PenPosition[1] = Transform[1][0] * params[0].value.number +
-                     Transform[1][1] * params[1].value.number +
-                     Transform[1][2];
-
-    Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-  }
-
-  PenPosition[0] = Transform[0][0] * params[2].value.number +
-                   Transform[0][1] * params[3].value.number +
-                   Transform[0][2];
-  PenPosition[1] = Transform[1][0] * params[2].value.number +
-                   Transform[1][1] * params[3].value.number +
-                   Transform[1][2];
-
-  if (PenDown)
-  {
-    Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-
-    if (!PolygonMode)
-      Outputf("ST\n");
-  }
-}
-
-
-/*
- * 'CI_circle()' - Draw a circle.
- */
-
-void
-CI_circle(int     num_params,  /* I - Number of parameters */
-          param_t *params)     /* I - Parameters */
-{
-  float x, y;                  /* Transformed coordinates */
-  float theta,                 /* Current angle */
-       dt,                     /* Step between points */
-       radius;                 /* Radius of circle */
-
-
-  if (num_params < 1)
-    return;
-
-  if (!PenDown)
-    return;
-
-  radius = params[0].value.number;
-
-  if (num_params > 1)
-    dt = (float)fabs(params[1].value.number);
-  else
-    dt = 5.0;
-
-  if (!PolygonMode)
-    Outputf("MP\n");
-
-  PenValid = 1;
-
-  for (theta = 0.0; theta < 360.0; theta += dt)
-  {
-    x = (float)(PenPosition[0] +
-                radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
-                radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
-    y = (float)(PenPosition[1] +
-                radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
-                radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
-
-    Outputf("%.3f %.3f %s\n", x, y, theta == 0.0 ? "MO" : "LI");
-  }
-
-  Outputf("CP\n");
-  if (!PolygonMode)
-    Outputf("ST\n");
-}
-
-
-/*
- * 'PA_plot_absolute()' - Plot a line using absolute coordinates.
- */
-
-void
-PA_plot_absolute(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  PenMotion = 0;
-
-  if (num_params > 1)
-    plot_points(num_params, params);
-}
-
-
-/*
- * 'PD_pen_down()' - Start drawing.
- */
-
-void
-PD_pen_down(int     num_params,                /* I - Number of parameters */
-            param_t *params)           /* I - Parameters */
-{
-  PenDown = 1;
-
-  if (num_params > 1)
-    plot_points(num_params, params);
-}
-
-
-/*
- * 'PE_polygon_encoded()' - Draw an encoded polyline.
- */
-
-void
-PE_polyline_encoded(int     num_params,        /* I - Number of parameters */
-                    param_t *params)   /* I - Parameters */
-{
-  unsigned char        *s;                     /* Pointer into string */
-  int          temp,                   /* Temporary value */
-               base_bits,              /* Data bits per byte */
-               draw,                   /* Draw or move */
-               abscoords;              /* Use absolute coordinates */
-  double       tx, ty,                 /* Transformed coordinates */
-               x, y,                   /* Raw coordinates */
-               frac_bits;              /* Multiplier for encoded number */
-
-
-  base_bits = 6;
-  frac_bits = 1.0;
-  draw      = PenDown;
-  abscoords = 0;
-
-  if (num_params == 0)
-    return;
-
-  if (!PolygonMode)
-  {
-    Outputf("MP\n");
-    PenValid = 0;
-  }
-
-  if (!PenValid)
-  {
-    Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-    PenValid = 1;
-  }
-
-  for (s = (unsigned char *)params[0].value.string; *s != '\0';)
-    switch (*s)
-    {
-      case '7' :
-          s ++;
-          base_bits = 5;
-
-#ifdef DEBUG
-          fputs("DEBUG:     7-bit\n", stderr);
-#endif /* DEBUG */
-
-          Outputf("%% PE: 7-bit\n");
-          break;
-      case ':' :       /* Select pen */
-          s ++;
-          temp = (int)decode_number(&s, base_bits, 1.0) - 1;
-         if (temp < 0 || temp >= PenCount)
-         {
-           fprintf(stderr, "DEBUG: Bad pen number %d in PE\n", temp + 1);
-           return;
-         }
-
-          PenNumber = temp;
-
-#ifdef DEBUG
-          fprintf(stderr, "DEBUG:     set pen #%d\n", PenNumber + 1);
-#endif /* DEBUG */
-
-          Outputf("%% PE: set pen #%d\n", PenNumber + 1);
-
-         if (PageDirty)
-           printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
-                  Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
-                  Pens[PenNumber].width * PenScaling);
-          break;
-      case '<' :       /* Next coords are a move-to */
-          draw = 0;
-          s ++;
-
-#ifdef DEBUG
-          fputs("DEBUG:     moveto\n", stderr);
-#endif /* DEBUG */
-
-         Outputf("%% PE: moveto\n");
-          break;
-      case '>' :       /* Set fractional bits */
-          s ++;
-          temp      = (int)decode_number(&s, base_bits, 1.0);
-          frac_bits = 1.0 / (1 << temp);
-
-#ifdef DEBUG
-          fprintf(stderr, "DEBUG:     set fractional bits %d\n", temp);
-#endif /* DEBUG */
-
-          Outputf("%% PE: set fractional bits %d\n", temp);
-          break;
-      case '=' :       /* Next coords are absolute */
-          s ++;
-          abscoords = 1;
-
-#ifdef DEBUG
-          fputs("DEBUG:     absolute\n", stderr);
-#endif /* DEBUG */
-
-          Outputf("%% PE: absolute\n");
-          break;
-      default :
-          if (*s >= 63)
-          {
-           /*
-            * Coordinate...
-            */
-
-            x = decode_number(&s, base_bits, frac_bits);
-            y = decode_number(&s, base_bits, frac_bits);
-
-#ifdef DEBUG
-            fprintf(stderr, "DEBUG:     coords %.3f %.3f\n", x, y);
-#endif /* DEBUG */
-
-            Outputf("%% PE: coords %.3f %.3f\n", x, y);
-
-            if (abscoords)
-            {
-             tx = Transform[0][0] * x + Transform[0][1] * y +
-                  Transform[0][2];
-             ty = Transform[1][0] * x + Transform[1][1] * y +
-                  Transform[1][2];
-           }
-           else if (x == 0.0 && y == 0.0)
-           {
-             draw = 1;
-             continue;
-           }
-           else
-           {
-             tx = Transform[0][0] * x + Transform[0][1] * y +
-                  PenPosition[0];
-             ty = Transform[1][0] * x + Transform[1][1] * y +
-                  PenPosition[1];
-           }
-
-            if (draw)
-           {
-             if (fabs(PenPosition[0] - tx) > 0.001 ||
-                 fabs(PenPosition[1] - ty) > 0.001)
-               Outputf("%.3f %.3f LI\n", tx, ty);
-            }
-           else
-              Outputf("%.3f %.3f MO\n", tx, ty);
-
-           PenPosition[0] = (float)tx;
-           PenPosition[1] = (float)ty;
-
-           draw           = 1;
-           abscoords      = 0;
-          }
-          else
-          {
-           /*
-            * Junk - ignore...
-            */
-
-            if (*s != '\n' && *s != '\r')
-              fprintf(stderr, "WARNING: ignoring illegal PE char \'%c\'...\n", *s);
-            s ++;
-          }
-          break;
-    }
-
-  if (!PolygonMode)
-    Outputf("ST\n");
-}
-
-
-/*
- * 'PR_plot_relative()' - Plot a line using relative coordinates.
- */
-
-void
-PR_plot_relative(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  PenMotion = 1;
-
-  if (num_params > 1)
-    plot_points(num_params, params);
-}
-
-
-/*
- * 'PU_pen_up()' - Stop drawing.
- */
-
-void
-PU_pen_up(int     num_params,  /* I - Number of parameters */
-          param_t *params)     /* I - Parameters */
-{
-  PenDown = 0;
-
-  if (num_params > 1)
-    plot_points(num_params, params);
-}
-
-
-/*
- * 'RT_arc_relative3()' - Draw an arc through 3 points relative to the
- *                        current pen position.
- *
- * Note:
- *
- *   This currently only draws two line segments through the specified
- *   points.
- */
-
-void
-RT_arc_relative3(int     num_params,   /* I - Number of parameters */
-                 param_t *params)      /* I - Parameters */
-{
-  if (num_params < 4)
-    return;
-
-  if (PenDown)
-  {
-    if (!PolygonMode)
-      Outputf("MP\n");
-
-    PenValid = 1;
-
-    Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-    PenPosition[0] = Transform[0][0] * params[0].value.number +
-                     Transform[0][1] * params[1].value.number +
-                     PenPosition[0];
-    PenPosition[1] = Transform[1][0] * params[0].value.number +
-                     Transform[1][1] * params[1].value.number +
-                     PenPosition[1];
-
-    Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-  }
-
-  PenPosition[0] = Transform[0][0] * params[2].value.number +
-                   Transform[0][1] * params[3].value.number +
-                   PenPosition[0];
-  PenPosition[1] = Transform[1][0] * params[2].value.number +
-                   Transform[1][1] * params[3].value.number +
-                   PenPosition[1];
-
-  if (PenDown)
-  {
-    Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
-
-    if (!PolygonMode)
-      Outputf("ST\n");
-  }
-}
-
-
-/*
- * 'decode_number()' - Decode an encoded number.
- */
-
-static double                          /* O - Value */
-decode_number(unsigned char **s,       /* IO - String to decode */
-              int           base_bits, /* I - Number of data bits per byte */
-             double        frac_bits)  /* I - Multiplier for fractional data */
-{
-  double       temp,           /* Current value */
-               shift;          /* Multiplier */
-  int          sign;           /* Sign of result */
-
-
-  sign = 0;
-
-  if (base_bits == 5)
-  {
-    for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
-      if (**s >= 95 && **s < 127)
-      {
-        if (sign == 0)
-        {
-          if ((**s - 95) & 1)
-            sign = -1;
-          else
-            sign = 1;
-
-          temp += ((**s - 95) & ~1) * shift;
-        }
-        else
-          temp += (**s - 95) * shift;
-        break;
-      }
-      else if (**s < 63)
-      {
-        if (**s != '\r' && **s != '\n')
-          fprintf(stderr, "DEBUG: Bad PE character 0x%02X!\n", **s);
-
-        continue;
-      }
-      else
-      {
-        if (sign == 0)
-        {
-          if ((**s - 63) & 1)
-            sign = -1;
-          else
-            sign = 1;
-
-          temp += ((**s - 63) & ~1) * shift;
-        }
-        else
-          temp += (**s - 63) * shift;
-
-       shift *= 32.0;
-      }
-  }
-  else
-  {
-    for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
-      if (**s >= 191 && **s < 255)
-      {
-        if (sign == 0)
-        {
-          if ((**s - 191) & 1)
-            sign = -1;
-          else
-            sign = 1;
-
-          temp += ((**s - 191) & ~1) * shift;
-        }
-        else
-          temp += (**s - 191) * shift;
-        break;
-      }
-      else if (**s < 63)
-      {
-        if (**s != '\r' && **s != '\n')
-          fprintf(stderr, "DEBUG: Bad PE character 0x%02X!\n", **s);
-
-        continue;
-      }
-      else
-      {
-        if (sign == 0)
-        {
-          if ((**s - 63) & 1)
-            sign = -1;
-          else
-            sign = 1;
-
-          temp += ((**s - 63) & ~1) * shift;
-        }
-        else
-          temp += (**s - 63) * shift;
-
-        shift *= 64.0;
-      }
-  }
-
-  (*s) ++;
-
-  return (temp * sign);
-}
-
-
-/*
- * 'plot_points()' - Plot the specified points.
- */
-
-static void
-plot_points(int     num_params,        /* I - Number of parameters */
-            param_t *params)   /* I - Parameters */
-{
-  int  i;                      /* Looping var */
-  float        x, y;                   /* Transformed coordinates */
-
-
-  if (PenDown)
-  {
-    if (!PolygonMode)
-    {
-      Outputf("MP\n");
-      Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
-
-      PenValid = 1;
-    }
-  }
-
-  for (i = 0; i < num_params; i += 2)
-  {
-    if (PenMotion == 0)
-    {
-      x = Transform[0][0] * params[i + 0].value.number +
-          Transform[0][1] * params[i + 1].value.number +
-          Transform[0][2];
-      y = Transform[1][0] * params[i + 0].value.number +
-          Transform[1][1] * params[i + 1].value.number +
-          Transform[1][2];
-    }
-    else
-    {
-      x = Transform[0][0] * params[i + 0].value.number +
-          Transform[0][1] * params[i + 1].value.number +
-          PenPosition[0];
-      y = Transform[1][0] * params[i + 0].value.number +
-          Transform[1][1] * params[i + 1].value.number +
-          PenPosition[1];
-    }
-
-    if (PenDown)
-    {
-      if (PolygonMode && i == 0)
-        Outputf("%.3f %.3f MO\n", x, y);
-      else if (fabs(PenPosition[0] - x) > 0.001 ||
-               fabs(PenPosition[1] - y) > 0.001)
-        Outputf("%.3f %.3f LI\n", x, y);
-    }
-
-    PenPosition[0] = x;
-    PenPosition[1] = y;
-  }
-
-  if (PenDown)
-  {
-    if (!PolygonMode)
-      Outputf("ST\n");
-  }
-}
-
-
-/*
- * End of "$Id: hpgl-vector.c 6649 2007-07-11 21:46:42Z mike $".
- */
diff --git a/filter/hpgltops.h b/filter/hpgltops.h
deleted file mode 100644 (file)
index 4fe45d2..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * "$Id: hpgltops.h 6649 2007-07-11 21:46:42Z mike $"
- *
- *   HP-GL/2 to PostScript filter for the Common UNIX Printing System (CUPS).
- *
- *   Copyright 2007 by Apple Inc.
- *   Copyright 1993-2005 by Easy Software Products.
- *
- *   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.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "common.h"
-#include <math.h>
-
-#ifndef M_PI
-#  define M_PI 3.14159265358979323846
-#endif /* M_PI */
-
-
-/*
- * Maximum number of pens we emulate...
- */
-
-#define MAX_PENS       1024
-
-
-/*
- * Parameter value structure...
- */
-
-typedef struct
-{
-  int  type;
-  union
-  {
-    float      number;
-    char       *string;
-  }    value;
-} param_t;
-
-#define PARAM_ABSOLUTE 0
-#define PARAM_RELATIVE 1
-#define PARAM_STRING   2
-
-
-/*
- * Font information...
- */
-
-typedef struct
-{
-  int  symbol_set,     /* Symbol set */
-       spacing,        /* Spacing (0 = fixed, 1 = proportional) */
-       posture,        /* Posture number */
-       weight,         /* Weight number */
-       typeface;       /* Typeface number */
-  float        pitch,          /* Characters per inch */
-       height,         /* Height/size of font */
-       xpitch;         /* X pitch scaling value */
-  float        x, y;           /* X and Y direction/scaling */
-} font_t;
-
-
-/*
- * Pen information...
- */
-
-typedef struct
-{
-  float        rgb[3];         /* Pen color */
-  float        width;          /* Pen width */
-} pen_t;
-
-
-/*
- * Globals...
- */
-
-#ifdef _HPGL_MAIN_C_
-#  define VAR
-#  define VALUE(x) =x
-#  define VALUE2(x,y) ={x,y}
-#else
-#  define VAR extern
-#  define VALUE(x)
-#  define VALUE2(x,y)
-#endif /* _HPGL_MAIN_C_ */
-
-VAR ppd_file_t *PPD VALUE(NULL);               /* PPD file */
-
-VAR float      P1[2],                          /* Lower-lefthand physical limit */
-               P2[2],                          /* Upper-righthand physical limit */
-               IW1[2],                         /* Window lower-lefthand limit */
-               IW2[2];                         /* Window upper-righthand limit */
-VAR int                Rotation        VALUE(0);       /* Page rotation */
-VAR int                ScalingType     VALUE(-1);      /* Type of scaling (-1 for none) */
-VAR float      Scaling1[2],                    /* Lower-lefthand user limit */
-               Scaling2[2];                    /* Upper-righthand user limit */
-VAR float      Transform[2][3];                /* Transform matrix */
-VAR int                PageRotation    VALUE(0);       /* Page/plot rotation */
-
-VAR char       StringTerminator VALUE('\003'); /* Terminator for labels */
-VAR font_t     StandardFont,                   /* Standard font */
-               AlternateFont;                  /* Alternate font */
-VAR float      PenPosition[2]  VALUE2(0.0f, 0.0f),
-                                               /* Current pen position */
-               PenScaling      VALUE(1.0f),    /* Pen width scaling factor */
-               PenWidth        VALUE(1.0f);    /* Default pen width */
-VAR pen_t      Pens[MAX_PENS];                 /* State of each pen */
-VAR int                PenMotion       VALUE(0),       /* 0 = absolute, 1 = relative */
-               PenValid        VALUE(0),       /* 1 = valid position, 0 = undefined */
-               PenNumber       VALUE(0),       /* Current pen number */
-               PenCount        VALUE(8),       /* Number of pens */
-               PenDown         VALUE(0),       /* 0 = pen up, 1 = pen down */
-               PolygonMode     VALUE(0),       /* Drawing polygons? */
-               PageCount       VALUE(0),       /* Number of pages in plot */
-               PageDirty       VALUE(0),       /* Current page written on? */
-               WidthUnits      VALUE(0);       /* 0 = mm, 1 = proportionate */
-VAR float      PlotSize[2]     VALUE2(2592.0f, 3456.0f);
-                                               /* Plot size */
-VAR int                PlotSizeSet     VALUE(0);       /* Plot size set? */
-VAR int                CharFillMode    VALUE(0),       /* Where to draw labels */
-               CharPen         VALUE(0),       /* Pen to use for labels */
-               CharFont        VALUE(0);       /* Font to use for labels */
-VAR float      CharHeight[2]   VALUE2(11.5f,11.5f);
-                                               /* Size of font for labels */
-VAR int                FitPlot         VALUE(0);       /* 1 = fit to page */
-VAR float      ColorRange[3][2]                /* Range of color values */
-#ifdef _HPGL_MAIN_C_
-               = {
-                 { 0.0, 255.0 },
-                 { 0.0, 255.0 },
-                 { 0.0, 255.0 }
-               }
-#endif /* _HPGL_MAIN_C_ */
-;
-
-VAR int                LineCap         VALUE(0);       /* Line capping */
-VAR int                LineJoin        VALUE(0);       /* Line joining */
-VAR float      MiterLimit      VALUE(3.0f);    /* Miter limit at joints */
-
-
-/*
- * Prototypes...
- */
-
-/* hpgl-input.c */
-extern int     ParseCommand(FILE *fp, char *name, param_t **params);
-extern void    FreeParameters(int num_params, param_t *params);
-
-/* hpgl-config.c */
-extern void    update_transform(void);
-extern void    BP_begin_plot(int num_params, param_t *params);
-extern void    DF_default_values(int num_params, param_t *params);
-extern void    IN_initialize(int num_params, param_t *params);
-extern void    IP_input_absolute(int num_params, param_t *params);
-extern void    IR_input_relative(int num_params, param_t *params);
-extern void    IW_input_window(int num_params, param_t *params);
-extern void    PG_advance_page(int num_params, param_t *params);
-extern void    PS_plot_size(int num_params, param_t *params);
-extern void    RO_rotate(int num_params, param_t *params);
-extern void    RP_replot(int num_params, param_t *params);
-extern void    SC_scale(int num_params, param_t *params);
-
-/* hpgl-vector.c */
-extern void    AA_arc_absolute(int num_params, param_t *params);
-extern void    AR_arc_relative(int num_params, param_t *params);
-extern void    AT_arc_absolute3(int num_params, param_t *params);
-extern void    CI_circle(int num_params, param_t *params);
-extern void    PA_plot_absolute(int num_params, param_t *params);
-extern void    PD_pen_down(int num_params, param_t *params);
-extern void    PE_polyline_encoded(int num_params, param_t *params);
-extern void    PR_plot_relative(int num_params, param_t *params);
-extern void    PU_pen_up(int num_params, param_t *params);
-extern void    RT_arc_relative3(int num_params, param_t *params);
-
-/* hpgl-polygon.c */
-extern void    EA_edge_rect_absolute(int num_params, param_t *params);
-extern void    EP_edge_polygon(int num_params, param_t *params);
-extern void    ER_edge_rect_relative(int num_params, param_t *params);
-extern void    EW_edge_wedge(int num_params, param_t *params);
-extern void    FP_fill_polygon(int num_params, param_t *params);
-extern void    PM_polygon_mode(int num_params, param_t *params);
-extern void    RA_fill_rect_absolute(int num_params, param_t *params);
-extern void    RR_fill_rect_relative(int num_params, param_t *params);
-extern void    WG_fill_wedge(int num_params, param_t *params);
-
-/* hpgl-char.c */
-extern void    define_font(int f);
-extern void    AD_define_alternate(int num_params, param_t *params);
-extern void    CF_character_fill(int num_params, param_t *params);
-extern void    CP_character_plot(int num_params, param_t *params);
-extern void    DI_absolute_direction(int num_params, param_t *params);
-extern void    DR_relative_direction(int num_params, param_t *params);
-extern void    DT_define_label_term(int num_params, param_t *params);
-extern void    DV_define_variable_path(int num_params, param_t *params);
-extern void    ES_extra_space(int num_params, param_t *params);
-extern void    LB_label(int num_params, param_t *params);
-extern void    LO_label_origin(int num_params, param_t *params);
-extern void    SA_select_alternate(int num_params, param_t *params);
-extern void    SD_define_standard(int num_params, param_t *params);
-extern void    SI_absolute_size(int num_params, param_t *params);
-extern void    SL_character_slant(int num_params, param_t *params);
-extern void    SR_relative_size(int num_params, param_t *params);
-extern void    SS_select_standard(int num_params, param_t *params);
-extern void    TD_transparent_data(int num_params, param_t *params);
-
-/* hpgl-attr.c */
-extern void    AC_anchor_corner(int num_params, param_t *params);
-extern void    CR_color_range(int num_params, param_t *params);
-extern void    FT_fill_type(int num_params, param_t *params);
-extern void    LA_line_attributes(int num_params, param_t *params);
-extern void    LT_line_type(int num_params, param_t *params);
-extern void    NP_number_pens(int num_params, param_t *params);
-extern void    PC_pen_color(int num_params, param_t *params);
-extern void    PW_pen_width(int num_params, param_t *params);
-extern void    RF_raster_fill(int num_params, param_t *params);
-extern void    SM_symbol_mode(int num_params, param_t *params);
-extern void    SP_select_pen(int num_params, param_t *params);
-extern void    UL_user_line_type(int num_params, param_t *params);
-extern void    WU_width_units(int num_params, param_t *params);
-
-/* hpgl-prolog.c */
-extern void    OutputProlog(char *title, char *user, int shading);
-extern void    OutputTrailer(void);
-extern int     Outputf(const char *format, ...);
-
-/*
- * End of "$Id: hpgltops.h 6649 2007-07-11 21:46:42Z mike $".
- */
index b12c39a659ac37bbdae0963e7fd3e6718321489e..9e489b3a2422c0798afd5b9b35ac9a11c35ec9f0 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Man page makefile for the Common UNIX Printing System (CUPS).
 #
-#   Copyright 2007-2008 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1993-2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -24,6 +24,7 @@ MAN1  =       cancel.$(MAN1EXT) \
                cups-config.$(MAN1EXT) \
                cupstestdsc.$(MAN1EXT) \
                cupstestppd.$(MAN1EXT) \
+               ipptest.$(MAN1EXT) \
                lp.$(MAN1EXT) \
                lpoptions.$(MAN1EXT) \
                lppasswd.$(MAN1EXT) \
@@ -40,6 +41,7 @@ MAN5  =       classes.conf.$(MAN5EXT) \
                client.conf.$(MAN5EXT) \
                cups-snmp.conf.$(MAN5EXT) \
                cupsd.conf.$(MAN5EXT) \
+               ipp.test.$(MAN5EXT) \
                mailto.conf.$(MAN5EXT) \
                mime.convs.$(MAN5EXT) \
                mime.types.$(MAN5EXT) \
index fc36f5db83a94b6ca0076cedfbf6ba0878974189..ad4d082b3d173de37524f93a5a9cbd8ac45f872a 100644 (file)
@@ -3,7 +3,7 @@
 .\"
 .\"   cupsd.conf man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007-2009 by Apple Inc.
+.\"   Copyright 2007-2010 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -12,7 +12,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 cupsd.conf 5 "CUPS" "14 July 2009" "Apple Inc."
+.TH cupsd.conf 5 "CUPS" "28 January 2010" "Apple Inc."
 .SH NAME
 cupsd.conf \- server configuration file for cups
 .SH DESCRIPTION
@@ -252,10 +252,6 @@ DefaultAuthType Negotiate
 .br
 Specifies the default type of authentication to use.
 .TP 5
-DefaultCharset charset
-.br
-Specifies the default character set to use for text.
-.TP 5
 DefaultEncryption Never
 .TP 5
 DefaultEncryption IfRequested
diff --git a/man/ipp.test.man b/man/ipp.test.man
new file mode 100644 (file)
index 0000000..2487199
--- /dev/null
@@ -0,0 +1,450 @@
+.\"
+.\" "$Id$"
+.\"
+.\"   ipp.test man page for CUPS.
+.\"
+.\"   Copyright 2010 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/".
+.\"
+.TH ipp.test 5 "CUPS" "23 February 2010" "Apple Inc."
+.SH NAME
+ipp.test \- ipptest test file format
+
+.SH DESCRIPTION
+The \fIipptest(1)\fR program accepts free-form plain text files that describe
+one or more IPP operation tests. Comments start with the "#" character and
+continue to the end of the line. Each test is enclosed by curley braces, for
+example:
+.nf
+
+    # This is a comment
+    {
+      # The name of the test
+      NAME "Print PostScript Job"
+
+      # The request to send
+      OPERATION Print-Job
+      GROUP operation
+      ATTR charset attributes-charset utf-8
+      ATTR language attributes-natural-language en
+      ATTR uri printer-uri $uri
+      ATTR name requesting-user-name $user
+      FILE testfile.ps
+
+      # The response to expect
+      STATUS successful-ok
+      EXPECT attributes-charset OF-TYPE charset
+      EXPECT attributes-natural-language OF-TYPE naturalLanguage
+      EXPECT job-id OF-TYPE integer
+      EXPECT job-uri OF-TYPE uri
+    }
+    {
+      # The name of the test
+      NAME "Get Attributes of PostScript Job"
+
+      # The request to send
+      OPERATION Get-Job-Attributes
+      GROUP operation
+      ATTR charset attributes-charset utf-8
+      ATTR language attributes-natural-language en
+      ATTR uri printer-uri $uri
+      ATTR integer job-id $job-id
+      ATTR name requesting-user-name $user
+
+      # The response to expect
+      STATUS successful-ok
+      EXPECT attributes-charset OF-TYPE charset
+      EXPECT attributes-natural-language OF-TYPE naturalLanguage
+      EXPECT job-id OF-TYPE integer
+      EXPECT job-uri OF-TYPE uri
+      EXPECT job-state OF-TYPE enum
+      EXPECT job-originating-user-name OF-TYPE name WITH-VALUE "$user"
+    }
+.fi
+
+.SH TOP-LEVEL DIRECTIVES
+The following directives can be used outside of a test:
+.TP 5
+{ test }
+Defines a test.
+.TP 5
+DEFINE variable-name value
+Defines the named variable to the given value. This is equivalent to specifying
+"-d variable-name=value" on the \fIipptest\fR command-line.
+.TP 5
+INCLUDE "filename"
+.TP 5
+INCLUDE <filename>
+Includes another test file. The first form includes a file relative to the
+current test file, while the second form includes a file from the \fIipptest\fR
+include directory.
+.TP 5
+TRANSFER auto
+Specifies that tests will, by default, use "Transfer-Encoding: chunked" for
+requests with attached files and "Content-Length:" for requests without attached
+files.
+.TP 5
+TRANSFER chunked
+Specifies that tests will, by default, use the HTTP/1.1 "Transfer-Encoding:
+chunked" header. This is the default and is equivalent to specifying "-c" on the
+\fIipptest\fR command-line. Support for chunked requests is required for
+conformance with all versions of IPP.
+.TP 5
+TRANSFER length
+Specifies that tests will, by default, use the HTTP/1.0 "Content-Length:"
+header. This is equivalent to specifying "-l" on the \fIipptest\fR command-line.
+Support for content length requests is required for conformance with all
+versions of IPP.
+.TP 5
+VERSION 1.0
+.TP 5
+VERSION 1.1
+.TP 5
+VERSION 2.0
+.TP 5
+VERSION 2.1
+.TP 5
+VERSION 2.2
+Specifies the default IPP version number to use for the tests that follow.
+
+.SH TEST DIRECTIVES
+The following directives are understood in a test:
+.TP 5
+ATTR tag attribute-name value(s)
+Adds an attribute to the test request. Values are separated by the comma (",")
+character - escape commas using the "\" character.
+.TP 5
+ATTR collection attribute-name { MEMBER tag member-name value(s) ... } [ ... { ... } ]
+Adds a collection attribute to the test request. Member attributes follow the
+same syntax as regular attributes and can themselves be nested collections.
+Multiple collection values can be supplied as needed.
+.TP 5
+DELAY seconds
+Specifies a delay before this test will be run.
+.TP 5
+DISPLAY attribute-name
+Specifies that value of the named attribute should be output as part of the
+test report.
+.TP 5
+EXPECT attribute-name [ predicate(s) ]
+.TP 5
+EXPECT ?attribute-name predicate(s)
+.TP 5
+EXPECT !attribute-name
+Specifies that the response must/may/must not include the named attribute.
+Additional requirements can be added as predicates - see the "EXPECT PREDICATES"
+section for more information on predicates.
+.TP 5
+FILE filename
+Specifies a file to include at the end of the request. This is typically used
+when sending a test print file.
+.TP 5
+GROUP tag
+Specifies the group tag for subsequent attributes in the request.
+.TP 5
+NAME "literal string"
+Specifies the human-readable name of the test.
+.TP 5
+OPERATION operation-code
+Specifies the operation to be performed.
+.TP 5
+REQUEST-ID number
+.TP 5
+REQUEST-ID random
+Specifies the request-id value to use in the request, either an integer or the
+word "random" to use a randomly generated value (the default).
+.TP 5
+RESOURCE path
+Specifies an alternate resource path that is used for the HTTP POST request.
+The default is the resource from the URI provided to the \fIipptest\fR program.
+.TP 5
+STATUS status-code [ predicate ]
+Specifies an expected response status-code value. Additional requirements can be
+added as predicates - see the "STATUS PREDICATES" section for more information
+on predicates.
+.TP 5
+TRANSFER auto
+Specifies that this test will use "Transfer-Encoding: chunked" if it has an
+attached file or "Content-Length:" otherwise.
+.TP 5
+TRANSFER chunked
+Specifies that this test will use the HTTP/1.1 "Transfer-Encoding: chunked"
+header.
+.TP 5
+TRANSFER length
+Specifies that this test will use the HTTP/1.0 "Content-Length:" header.
+.TP 5
+VERSION 1.0
+.TP 5
+VERSION 1.1
+.TP 5
+VERSION 2.0
+.TP 5
+VERSION 2.1
+.TP 5
+VERSION 2.2
+Specifies the IPP version number to use for this test.
+
+.SH EXPECT PREDICATES
+The following predicates are understood following the EXPECT test directive:
+.TP 5
+COUNT number
+Requires the EXPECT attribute to have the specified number of values.
+.TP 5
+IF-DEFINED variable-name
+Makes the EXPECT conditions apply only if the specified variable is defined.
+.TP 5
+IF-UNDEFINED variable-name
+Makes the EXPECT conditions apply only if the specified variable is not
+defined.
+.TP 5
+IN-GROUP tag
+Requires the EXPECT attribute to be in the specified group tag.
+.TP 5
+OF-TYPE tag[,tag,...]
+Requires the EXPECT attribute to use the specified value tag(s).
+.TP 5
+SAME-COUNT-AS attribute-name
+Requires the EXPECT attribute to have the same number of values as the specified
+parallel attribute.
+.TP 5
+WITH-VALUE "literal string"
+Requires at least one value of the EXPECT attribute to match the literal string.
+Comparisons are case-sensitive.
+.TP 5
+WITH-VALUE "/regular expression/"
+Requires that all values of the EXPECT attribute match the regular expression,
+which must conform to the POSIX regular expression syntax.
+Comparisons are case-sensitive.
+
+.SH STATUS PREDICATES
+The following predicates are understood following the STATUS test directive:
+.TP 5
+IF-DEFINED variable-name
+Makes the STATUS apply only if the specified variable is defined.
+.TP 5
+IF-UNDEFINED variable-name
+Makes the STATUS apply only if the specified variable is not defined.
+
+.SH OPERATION CODES
+Operation codes correspond to the names from RFC 2911 and other IPP extension
+specifications. Here is a complete list:
+.nf
+    Activate-Printer
+    CUPS-Accept-Jobs
+    CUPS-Add-Modify-Class
+    CUPS-Add-Modify-Printer
+    CUPS-Authenticate-Job
+    CUPS-Delete-Class
+    CUPS-Delete-Printer
+    CUPS-Get-Classes
+    CUPS-Get-Default
+    CUPS-Get-Devices
+    CUPS-Get-Document
+    CUPS-Get-PPD
+    CUPS-Get-PPDs
+    CUPS-Get-Printers
+    CUPS-Move-Job
+    CUPS-Reject-Jobs
+    CUPS-Set-Default
+    Cancel-Current-Job
+    Cancel-Job
+    Cancel-Subscription
+    Create-Job
+    Create-Job-Subscription
+    Create-Printer-Subscription
+    Deactivate-Printer
+    Disable-Printer
+    Enable-Printer
+    Get-Job-Attributes
+    Get-Jobs
+    Get-Notifications
+    Get-Printer-Attributes
+    Get-Printer-Support-Files
+    Get-Printer-Supported-Values
+    Get-Subscription-Attributes
+    Get-Subscriptions
+    Hold-Job
+    Hold-New-Jobs
+    Pause-Printer
+    Pause-Printer-After-Current-Job
+    Print-Job
+    Print-URI
+    Promote-Job
+    Purge-Jobs
+    Release-Held-New-Jobs
+    Release-Job
+    Renew-Subscription
+    Reprocess-Job
+    Restart-Job
+    Restart-Printer
+    Resume-Job
+    Resume-Printer
+    Schedule-Job-After
+    Send-Document
+    Send-Notifications
+    Send-URI
+    Set-Job-Attributes
+    Set-Printer-Attributes
+    Shutdown-Printer
+    Startup-Printer
+    Suspend-Current-Job
+    Validate-Job
+.fi
+
+.SH STATUS CODES
+Status codes correspond to the names from RFC 2911 and other IPP extension
+specifications. Here is a complete list:
+.nf
+    client-error-attributes-not-settable
+    client-error-attributes-or-values-not-supported
+    client-error-bad-request
+    client-error-charset-not-supported
+    client-error-compression-error
+    client-error-compression-not-supported
+    client-error-conflicting-attributes
+    client-error-document-access-error
+    client-error-document-format-error
+    client-error-document-format-not-supported
+    client-error-forbidden
+    client-error-gone
+    client-error-ignored-all-notifications
+    client-error-ignored-all-subscriptions
+    client-error-not-authenticated
+    client-error-not-authorized
+    client-error-not-found
+    client-error-not-possible
+    client-error-print-support-file-not-found
+    client-error-request-entity-too-large
+    client-error-request-value-too-long
+    client-error-timeout
+    client-error-too-many-subscriptions
+    client-error-uri-scheme-not-supported
+    cups-see-other
+    redirection-other-site
+    server-error-busy
+    server-error-device-error
+    server-error-internal-error
+    server-error-job-canceled
+    server-error-multiple-document-jobs-not-supported
+    server-error-not-accepting-jobs
+    server-error-operation-not-supported
+    server-error-printer-is-deactivated
+    server-error-service-unavailable
+    server-error-temporary-error
+    server-error-version-not-supported
+    successful-ok
+    successful-ok-but-cancel-subscription
+    successful-ok-conflicting-attributes
+    successful-ok-events-complete
+    successful-ok-ignored-notifications
+    successful-ok-ignored-or-substituted-attributes
+    successful-ok-ignored-subscriptions
+    successful-ok-too-many-events
+.fi
+
+.SH TAGS
+Value and group tags correspond to the names from RFC 2911 and other IPP
+extension specifications. Here are the group tags:
+.nf
+    event-notification-attributes-tag
+    job-attributes-tag
+    operation-attributes-tag
+    printer-attributes-tag
+    subscription-attributes-tag
+    unsupported-attributes-tag
+.fi
+.LP
+Here are the value tags:
+.nf
+    admin-define
+    boolean
+    charset
+    collection
+    dateTime
+    default
+    delete-attribute
+    enum
+    integer
+    keyword
+    mimeMediaType
+    nameWithLanguage
+    nameWithoutLanguage
+    naturalLanguage
+    no-value
+    not-settable
+    octetString
+    rangeOfInteger
+    resolution
+    textWithLanguage
+    textWithoutLanguage
+    unknown
+    unsupported
+    uri
+    uriScheme
+.fi
+
+.SH VARIABLES
+The \fIipptest\fR program maintains a list of variables that can be used in any
+literal string or attribute value by specifying "$variable-name". Aside from
+variables defined using the "-d" option or "DEFINE" directive, the following
+pre-defined variables are available:
+.TP 5
+$$
+Inserts a single "$" character.
+.TP 5
+$ENV[name]
+Inserts the value of the named environment variable, or an empty string if the
+environment variable is not defined.
+.TP 5
+$filename
+Inserts the filename provided to \fIipptest\fR with the "-f" option.
+.TP 5
+$hostname
+Inserts the hostname from the URI provided to \fIipptest\fR.
+.TP 5
+$job-id
+Inserts the last job-id value returned in a test response or 0 if no job-id has
+been seen.
+.TP 5
+$job-uri
+Inserts the last job-uri value returned in a test response or an empty string if
+no job-uri has been seen.
+.TP 5
+$scheme
+Inserts the scheme from the URI provided to \fIipptest\fR.
+.TP 5
+$notify-subscription-id
+Inserts the last notify-subscription-id value returnd in a test response or 0 if
+no notify-subscription-id has been seen.
+.TP 5
+$port
+Inserts the port number from the URI provided to \fIipptest\fR.
+.TP 5
+$resource
+Inserts the resource path from the URI provided to \fIipptest\fR.
+.TP 5
+$uri
+Inserts the URI provided to \fIipptest\fR.
+.TP 5
+$user
+Inserts the current user's login name.
+.TP 5
+$username
+Inserts the username from the URI provided to \fIipptest\fR, if any.
+
+.SH SEE ALSO
+\fIipptest(1)\fR,
+.br
+http://localhost:631/help
+
+.SH COPYRIGHT
+Copyright 2007-2010 by Apple Inc.
+.\"
+.\" End of "$Id$".
+.\"
diff --git a/man/ipptest.man b/man/ipptest.man
new file mode 100644 (file)
index 0000000..2d14676
--- /dev/null
@@ -0,0 +1,89 @@
+.\"
+.\" "$Id$"
+.\"
+.\"   ipptest man page for CUPS.
+.\"
+.\"   Copyright 2010 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/".
+.\"
+.TH ipptest 1 "CUPS" "15 February 2010" "Apple Inc."
+.SH NAME
+ipptest - perform internet printing protocol tests
+.SH SYNOPSIS
+.B ipptest
+[ -E ] [ -V
+.I version
+] [ -X ] [ -c ] [ -d
+.I name=value
+] [ -f
+.I filename
+] [ -i
+.I seconds
+] [ -l ] [ -v ] 
+.I URI
+.I filename.test
+[
+.I ... filenameN.test
+]
+.SH DESCRIPTION
+\fIipptest\fR sends IPP requests to the specified URI and tests the results.
+Each test file contains one or more test requests, including the expected
+response status, attributes, and values.  Output is either a plain text or XML
+report on the standard output, with a non-zero exit status indicating that one
+or more tests have failed. The test file format is described in
+\fIipp.test(5)\fR.
+.SH OPTIONS
+The following options are recognized by \fIipptest\fR:
+.TP 5
+-E
+Forces encryption when connecting to the server.
+.TP 5
+-V version
+Specifies the default IPP version to use: 1.0, 1.1, 2.0, 2.1, or 2.2. If not
+specified, version 1.1 is used.
+.TP 5
+-X
+Specifies that XML (Apple plist) output is desired instead of the plain text
+report. This option is incompatible with the \fI-i\fR (interval) option.
+.TP 5
+-c
+Specifies that requests should be sent using the HTTP/1.1 "Transfer-Encoding:
+chunked" header, which is required for conformance by all versions of IPP. The
+default is to use "Transfer-Encoding: chunked" for requests with attached files
+and "Content-Length:" for requests without attached files.
+.TP 5
+-d name=value
+Defines the named variable.
+.TP 5
+-f filename
+Defines the default request filename for tests.
+.TP 5
+-i seconds
+Specifies that the (last) test should be repeated at the specified interval.
+This option is incompatible with the \fI-X\fR (XML output) option.
+.TP 5
+-l
+Specifies that requests should be sent using the HTTP/1.0 "Content-Length:"
+header, which is required for conformance by all versions of IPP. The
+default is to use "Transfer-Encoding: chunked" for requests with attached files
+and "Content-Length:" for requests without attached files.
+.TP 5
+-v
+Specifies that all request and response attributes should be output. This is the
+default for XML output.
+.SH COMPATIBILITY
+The \fIipptest\fR program is unique to CUPS.
+.SH SEE ALSO
+\fIipp.test(5)\fR,
+.br
+http://localhost:631/help
+.SH COPYRIGHT
+Copyright 2007-2010 by Apple Inc.
+.\"
+.\" End of "$Id$".
+.\"
index b6eb952b05f0dd4fde67276f1bd869a9a59766ce..adad41785aab52a5a2df7f15d9da01abccbbf447 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   ESP Package Manager (EPM) file list for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -15,7 +15,7 @@
 
 # Product information
 %product CUPS
-%copyright 2007-2009 by Apple Inc.
+%copyright 2007-2010 by Apple Inc.
 %vendor Apple Inc.
 #%license LICENSE.txt
 %readme LICENSE.txt
@@ -273,7 +273,6 @@ l 0700 root sys $SERVERBIN/backend/mdns dnssd
 %endif
 %system !darwin
 f 0555 root sys $SERVERBIN/backend/parallel backend/parallel
-f 0555 root sys $SERVERBIN/backend/scsi backend/scsi
 %system all
 f 0555 root sys $SERVERBIN/backend/serial backend/serial
 f 0555 root sys $SERVERBIN/backend/snmp backend/snmp
@@ -296,7 +295,6 @@ f 0555 root sys $SERVERBIN/filter/commandtoespcx driver/commandtoescpx
 f 0555 root sys $SERVERBIN/filter/commandtopclx driver/commandtopclx
 f 0555 root sys $SERVERBIN/filter/commandtops filter/commandtops
 f 0555 root sys $SERVERBIN/filter/gziptoany filter/gziptoany
-f 0555 root sys $SERVERBIN/filter/hpgltops filter/hpgltops
 %if IMGFILTERS
 f 0555 root sys $SERVERBIN/filter/imagetops filter/imagetops
 f 0555 root sys $SERVERBIN/filter/imagetoraster filter/imagetoraster
@@ -351,6 +349,7 @@ d 0755 root sys $BINDIR -
 f 0555 root sys $BINDIR/cancel systemv/cancel
 f 0555 root sys $BINDIR/cupstestdsc systemv/cupstestdsc
 f 0555 root sys $BINDIR/cupstestppd systemv/cupstestppd
+f 0555 root sys $BINDIR/ipptest test/ipptest
 f 0555 root sys $BINDIR/lp systemv/lp
 f 0555 root sys $BINDIR/lpoptions systemv/lpoptions
 f 0555 root sys $BINDIR/lppasswd systemv/lppasswd
@@ -465,26 +464,27 @@ d 0755 root $CUPS_GROUP $STATEDIR -
 d 0511 root $CUPS_PRIMARY_SYSTEM_GROUP $STATEDIR/certs -
 
 # Data files
-#f 0444 root sys $LOCALEDIR/da/cups_da.po locale/cups_da.po
-#f 0444 root sys $LOCALEDIR/de/cups_de.po locale/cups_de.po
+f 0444 root sys $LOCALEDIR/da/cups_da.po locale/cups_da.po
+f 0444 root sys $LOCALEDIR/de/cups_de.po locale/cups_de.po
 f 0444 root sys $LOCALEDIR/es/cups_es.po locale/cups_es.po
 #f 0444 root sys $LOCALEDIR/et/cups_et.po locale/cups_et.po
 f 0444 root sys $LOCALEDIR/eu/cups_eu.po locale/cups_eu.po
-#f 0444 root sys $LOCALEDIR/fi/cups_fi.po locale/cups_fi.po
-#f 0444 root sys $LOCALEDIR/fr/cups_fr.po locale/cups_fr.po
+f 0444 root sys $LOCALEDIR/fi/cups_fi.po locale/cups_fi.po
+f 0444 root sys $LOCALEDIR/fr/cups_fr.po locale/cups_fr.po
 #f 0444 root sys $LOCALEDIR/he/cups_he.po locale/cups_he.po
-#f 0444 root sys $LOCALEDIR/it/cups_it.po locale/cups_it.po
-#f 0444 root sys $LOCALEDIR/ja/cups_ja.po locale/cups_ja.po
-#f 0444 root sys $LOCALEDIR/ko/cups_ko.po locale/cups_ko.po
-#f 0444 root sys $LOCALEDIR/nl/cups_nl.po locale/cups_nl.po
-#f 0444 root sys $LOCALEDIR/no/cups_no.po locale/cups_no.po
-#f 0444 root sys $LOCALEDIR/pl/cups_pl.po locale/cups_pl.po
-#f 0444 root sys $LOCALEDIR/pt/cups_pt.po locale/cups_pt.po
-#f 0444 root sys $LOCALEDIR/pt_BR/cups_pt_BR.po locale/cups_pt_BR.po
-#f 0444 root sys $LOCALEDIR/ru/cups_ru.po locale/cups_ru.po
-#f 0444 root sys $LOCALEDIR/sv/cups_sv.po locale/cups_sv.po
-#f 0444 root sys $LOCALEDIR/zh/cups_zh.po locale/cups_zh.po
-#f 0444 root sys $LOCALEDIR/zh_TW/cups_zh_TW.po locale/cups_zh_TW.po
+f 0444 root sys $LOCALEDIR/id/cups_id.po locale/cups_id.po
+f 0444 root sys $LOCALEDIR/it/cups_it.po locale/cups_it.po
+f 0444 root sys $LOCALEDIR/ja/cups_ja.po locale/cups_ja.po
+f 0444 root sys $LOCALEDIR/ko/cups_ko.po locale/cups_ko.po
+f 0444 root sys $LOCALEDIR/nl/cups_nl.po locale/cups_nl.po
+f 0444 root sys $LOCALEDIR/no/cups_no.po locale/cups_no.po
+f 0444 root sys $LOCALEDIR/pl/cups_pl.po locale/cups_pl.po
+f 0444 root sys $LOCALEDIR/pt/cups_pt.po locale/cups_pt.po
+f 0444 root sys $LOCALEDIR/pt_BR/cups_pt_BR.po locale/cups_pt_BR.po
+f 0444 root sys $LOCALEDIR/ru/cups_ru.po locale/cups_ru.po
+f 0444 root sys $LOCALEDIR/sv/cups_sv.po locale/cups_sv.po
+f 0444 root sys $LOCALEDIR/zh/cups_zh.po locale/cups_zh.po
+f 0444 root sys $LOCALEDIR/zh_TW/cups_zh_TW.po locale/cups_zh_TW.po
 
 d 0755 root sys $DATADIR -
 
@@ -503,7 +503,6 @@ d 0755 root sys $DATADIR/charsets -
 f 0444 root sys $DATADIR/charsets/utf-8 data/utf-8
 
 d 0755 root sys $DATADIR/data -
-f 0444 root sys $DATADIR/data/HPGLprolog data/HPGLprolog
 f 0444 root sys $DATADIR/data/psglyphs data/psglyphs
 f 0444 root sys $DATADIR/data/testprint data/testprint
 
@@ -516,6 +515,10 @@ f 0444 root sys $DATADIR/examples examples/*.drv
 d 0755 root sys $DATADIR/fonts -
 f 0444 root sys $DATADIR/fonts fonts/Monospace*
 
+d 0755 root sys $DATADIR/ipptest -
+f 0444 root sys $DATADIR/ipptest test/ipp-*.test
+f 0444 root sys $DATADIR/ipptest test/testfile.*
+
 d 0755 root sys $DATADIR/mime -
 f 0444 root sys $DATADIR/mime/mime.convs conf/mime.convs
 f 0444 root sys $DATADIR/mime/mime.types conf/mime.types
@@ -530,8 +533,8 @@ d 0755 root sys $DATADIR/templates -
 f 0444 root sys $DATADIR/templates templates/*.tmpl
 
 ## Template files
-#d 0755 root sys $DATADIR/templates/de
-#f 0444 root sys $DATADIR/templates/de templates/de/*.tmpl
+d 0755 root sys $DATADIR/templates/de
+f 0444 root sys $DATADIR/templates/de templates/de/*.tmpl
 
 d 0755 root sys $DATADIR/templates/es
 f 0444 root sys $DATADIR/templates/es templates/es/*.tmpl
@@ -548,8 +551,11 @@ f 0444 root sys $DATADIR/templates/eu templates/eu/*.tmpl
 #d 0755 root sys $DATADIR/templates/he
 #f 0444 root sys $DATADIR/templates/he templates/he/*.tmpl
 
-#d 0755 root sys $DATADIR/templates/it
-#f 0444 root sys $DATADIR/templates/it templates/it/*.tmpl
+d 0755 root sys $DATADIR/templates/id
+f 0444 root sys $DATADIR/templates/id templates/id/*.tmpl
+
+d 0755 root sys $DATADIR/templates/it
+f 0444 root sys $DATADIR/templates/it templates/it/*.tmpl
 
 d 0755 root sys $DATADIR/templates/ja
 f 0444 root sys $DATADIR/templates/ja templates/ja/*.tmpl
@@ -644,8 +650,8 @@ f 0444 root sys $DOCDIR/images doc/images/*.png
 f 0444 root sys $DOCDIR/robots.txt doc/robots.txt
 
 # Localized documentation files
-#d 0755 root sys $DOCDIR/de
-#f 0444 root sys $DOCDIR/de doc/de/*.html
+d 0755 root sys $DOCDIR/de
+f 0444 root sys $DOCDIR/de doc/de/*.html
 
 d 0755 root sys $DOCDIR/es
 f 0444 root sys $DOCDIR/es doc/es/*.html
@@ -663,8 +669,11 @@ f 0444 root sys $DOCDIR/eu doc/eu/*.html
 #f 0444 root sys $DOCDIR/he doc/he/*.html
 #f 0444 root sys $DOCDIR/he/cups.css doc/he/cups.css
 
-#d 0755 root sys $DOCDIR/it
-#f 0444 root sys $DOCDIR/it doc/it/*.html
+d 0755 root sys $DOCDIR/id
+f 0444 root sys $DOCDIR/id doc/id/*.html
+
+d 0755 root sys $DOCDIR/it
+f 0444 root sys $DOCDIR/it doc/it/*.html
 
 d 0755 root sys $DOCDIR/ja
 f 0444 root sys $DOCDIR/ja doc/ja/*.html
@@ -692,6 +701,7 @@ d 0755 root sys $MANDIR/man7 -
 f 0444 root sys $MANDIR/man1/cancel.$MAN1EXT man/cancel.$MAN1EXT
 f 0444 root sys $MANDIR/man1/cupstestdsc.$MAN1EXT man/cupstestdsc.$MAN1EXT
 f 0444 root sys $MANDIR/man1/cupstestppd.$MAN1EXT man/cupstestppd.$MAN1EXT
+f 0444 root sys $MANDIR/man1/ipptest.$MAN1EXT man/ipptest.$MAN1EXT
 f 0444 root sys $MANDIR/man1/lpoptions.$MAN1EXT man/lpoptions.$MAN1EXT
 f 0444 root sys $MANDIR/man1/lppasswd.$MAN1EXT man/lppasswd.$MAN1EXT
 f 0444 root sys $MANDIR/man1/lpq.$MAN1EXT man/lpq.$MAN1EXT
@@ -702,6 +712,7 @@ f 0444 root sys $MANDIR/man1/lp.$MAN1EXT man/lp.$MAN1EXT
 
 f 0444 root sys $MANDIR/man5/classes.conf.$MAN5EXT man/classes.conf.$MAN5EXT
 f 0444 root sys $MANDIR/man5/cupsd.conf.$MAN5EXT man/cupsd.conf.$MAN5EXT
+f 0444 root sys $MANDIR/man5/ipp.test.$MAN5EXT man/ipp.test.$MAN5EXT
 f 0444 root sys $MANDIR/man5/mailto.conf.$MAN5EXT man/mailto.conf.$MAN5EXT
 f 0444 root sys $MANDIR/man5/mime.convs.$MAN5EXT man/mime.convs.$MAN5EXT
 f 0444 root sys $MANDIR/man5/mime.types.$MAN5EXT man/mime.types.$MAN5EXT
index 267cac94a858f4c4f1bf7a6f9afac95eff1ddd42..26d0ac8a19b2ffc55fc7d17c86f8ff0b473edb51 100644 (file)
@@ -5,7 +5,7 @@
 #
 #   Original version by Jason McMullan <jmcc@ontv.com>.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1999-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -185,6 +185,7 @@ rm -rf $RPM_BUILD_ROOT
 /usr/bin/cancel
 /usr/bin/cupstestdsc
 /usr/bin/cupstestppd
+/usr/bin/ipptest
 /usr/bin/lp*
 %dir /usr/lib/cups
 %dir /usr/lib/cups/backend
@@ -225,6 +226,8 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/cups/drv/*
 %dir /usr/share/cups/fonts
 /usr/share/cups/fonts/*
+%dir /usr/share/cups/ipptest
+/usr/share/cups/ipptest/*
 %dir /usr/share/cups/mime
 /usr/share/cups/mime/*
 %dir /usr/share/cups/model
@@ -240,6 +243,8 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/doc/cups/es/*
 %dir /usr/share/doc/cups/eu
 /usr/share/doc/cups/eu/*
+%dir /usr/share/doc/cups/id
+/usr/share/doc/cups/id/*
 %dir /usr/share/doc/cups/ja
 /usr/share/doc/cups/ja/*
 %dir /usr/share/doc/cups/pl
@@ -271,6 +276,7 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/man/man1/cancel.1.gz
 /usr/share/man/man1/cupstestdsc.1.gz
 /usr/share/man/man1/cupstestppd.1.gz
+/usr/share/man/man1/ipptest.1.gz
 /usr/share/man/man1/lp.1.gz
 /usr/share/man/man1/lpoptions.1.gz
 /usr/share/man/man1/lppasswd.1.gz
@@ -280,6 +286,7 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/man/man1/lpstat.1.gz
 %dir /usr/share/man/man5
 /usr/share/man/man5/*.conf.5.gz
+/usr/share/man/man5/ipp.test.5.gz
 /usr/share/man/man5/mime.*.5.gz
 %dir /usr/share/man/man7
 /usr/share/man/man7/drv*
index 524426541fa46127334bf3702d1a594bf2649e21..f58b6f88249e0f0d72c3045eae992995e25f8770 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Makefile for the CUPS PPD Compiler.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 2002-2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -143,7 +143,7 @@ install-exec:
        done
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               for file in $(EXECTARGETS) $(LIBTARGETS); do \
+               for file in $(EXECTARGETS); do \
                        cp $$file $(SYMROOT); \
                done \
        fi
@@ -237,11 +237,11 @@ framedhelp:
 # genstrings - generate GNU gettext strings.
 #
 
-genstrings:            genstrings.o libcupsppdc.a ../cups/libcups.a \
+genstrings:            genstrings.o libcupsppdc.a ../cups/$(LIBCUPSSTATIC) \
                        sample.drv ../data/media.defs
        echo Linking $@...
        $(CXX) $(ARCHFLAGS) $(LDFLAGS) -o genstrings genstrings.o \
-               libcupsppdc.a ../cups/libcups.a $(LIBGSSAPI) $(SSLLIBS) \
+               libcupsppdc.a ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) \
                $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
        echo Generating localization strings...
        ./genstrings >sample.c
@@ -256,10 +256,10 @@ ppdc:                     ppdc.o $(LIBCUPSPPDC) ../cups/$(LIBCUPS)
        $(CXX) $(LDFLAGS) -o $@ ppdc.o -L. -lcupsppdc $(LIBS)
 
 
-ppdc-static:           ppdc.o libcupsppdc.a  ../cups/libcups.a foo.drv foo-fr.po
+ppdc-static:           ppdc.o libcupsppdc.a  ../cups/$(LIBCUPSSTATIC) foo.drv foo-fr.po
        echo Linking $@...
        $(CXX) $(ARCHFLAGS) $(LDFLAGS) -o ppdc-static ppdc.o libcupsppdc.a \
-               ../cups/libcups.a $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
                $(COMMONLIBS) $(LIBZ)
        echo Testing PPD compiler...
        ./ppdc-static -l en,fr -I ../data foo.drv
@@ -284,10 +284,10 @@ ppdi:                     ppdi.o $(LIBCUPSPPDC) ../cups/$(LIBCUPS)
        $(CXX) $(LDFLAGS) -o $@ ppdi.o -L. -lcupsppdc $(LIBS)
 
 
-ppdi-static:           ppdc-static ppdi.o libcupsppdc.a  ../cups/libcups.a
+ppdi-static:           ppdc-static ppdi.o libcupsppdc.a  ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CXX) $(ARCHFLAGS) $(LDFLAGS) -o ppdi-static ppdi.o libcupsppdc.a \
-               ../cups/libcups.a $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
                $(COMMONLIBS) $(LIBZ)
        echo Testing PPD importer...
        $(RM) -r ppd ppd2 sample-import.drv
@@ -324,10 +324,10 @@ ppdpo:                    ppdpo.o $(LIBCUPSPPDC) ../cups/$(LIBCUPS)
 # testcatalog, test ppdcCatalog class.
 #
 
-testcatalog:           testcatalog.o libcupsppdc.a ../cups/libcups.a
+testcatalog:           testcatalog.o libcupsppdc.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CXX) $(LDFLAGS) -o $@ testcatalog.o libcupsppdc.a \
-               ../cups/libcups.a $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
                $(COMMONLIBS) $(LIBZ)
 
 
index 8a2a20cc711a63ed0d85be323debf19366082704..1a8e7c325653c30d33e46a3294e1bd72375c3198 100644 (file)
@@ -248,5 +248,4 @@ cups-driverd.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/globals.h
 cups-driverd.o: ../cups/string.h ../cups/cups.h ../cups/i18n.h
 cups-driverd.o: ../cups/transcode.h ../cups/language.h ../cups/array.h
 cups-driverd.o: ../cups/debug.h ../cups/dir.h ../cups/transcode.h
-cups-driverd.o: ../cups/ppd-private.h ../ppdc/ppdc.h ../cups/string.h
-cups-driverd.o: ../cups/file.h
+cups-driverd.o: ../cups/ppd-private.h ../ppdc/ppdc.h ../cups/file.h
index fe8ee6b1dc5ede1a07a10a5dbab57d67af98ff34..15292b9c6636a99667eaac420c49457215c1ed3c 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7875 2008-08-27 22:53:31Z mike $"
 #
-#   Scheduler Makefile for the Common UNIX Printing System (CUPS).
+#   Scheduler Makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -73,14 +73,17 @@ UNITTARGETS =       \
                testspeed \
                testsub
 
-TARGETS        =       \
-               $(LIBTARGETS) \
+DAEMONS =      \
                cupsd \
                cupsfilter \
                cups-deviced \
                cups-driverd \
                cups-lpd \
-               cups-polld \
+               cups-polld
+
+TARGETS        =       \
+               $(LIBTARGETS) \
+               $(DAEMONS)
 
 
 #
@@ -223,7 +226,7 @@ install-exec:
        $(INSTALL_BIN) cups-polld $(SERVERBIN)/daemon
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               for file in $(TARGETS); do \
+               for file in $(DAEMONS); do \
                        cp $$file $(SYMROOT); \
                done \
        fi
@@ -374,11 +377,11 @@ cupsd:    $(CUPSDOBJS) $(LIBCUPSMIME) ../cups/$(LIBCUPS)
                $(LIBPAPER) $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBS) \
                $(LIBGSSAPI) $(LIBWRAP)
 
-cupsd-static:  $(CUPSDOBJS) libcupsmime.a ../cups/libcups.a
+cupsd-static:  $(CUPSDOBJS) libcupsmime.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(LDFLAGS) -o cupsd-static $(CUPSDOBJS) libcupsmime.a \
                $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
-               ../cups/libcups.a $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \
+               ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \
                $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \
                $(LIBWRAP)
 
@@ -503,9 +506,9 @@ testdirsvc: testdirsvc.o
 # Make the test program, "testlpd".
 #
 
-testlpd:       testlpd.o ../cups/libcups.a cups-lpd
+testlpd:       testlpd.o ../cups/$(LIBCUPSSTATIC) cups-lpd
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o testlpd testlpd.o ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o testlpd testlpd.o ../cups/$(LIBCUPSSTATIC) \
                $(COMMONLIBS) $(LIBZ) $(SSLLIBS) $(DNSSDLIBS) $(LIBGSSAPI)
 
 
@@ -513,10 +516,10 @@ testlpd:  testlpd.o ../cups/libcups.a cups-lpd
 # testmime
 #
 
-testmime:      testmime.o libcupsmime.a ../cups/libcups.a
+testmime:      testmime.o libcupsmime.a ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
        $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testmime.o libcupsmime.a \
-               ../cups/libcups.a $(COMMONLIBS) $(LIBZ) $(SSLLIBS) \
+               ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(SSLLIBS) \
                $(DNSSDLIBS) $(LIBGSSAPI)
        echo Running MIME tests...
        ./testmime
@@ -526,9 +529,9 @@ testmime:   testmime.o libcupsmime.a ../cups/libcups.a
 # Make the test program, "testspeed".
 #
 
-testspeed:     testspeed.o ../cups/libcups.a
+testspeed:     testspeed.o ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o testspeed testspeed.o ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o testspeed testspeed.o ../cups/$(LIBCUPSSTATIC) \
                $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) $(LIBGSSAPI)
 
 
@@ -536,9 +539,9 @@ testspeed:  testspeed.o ../cups/libcups.a
 # Make the test program, "testsub".
 #
 
-testsub:       testsub.o ../cups/libcups.a
+testsub:       testsub.o ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o testsub testsub.o ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o testsub testsub.o ../cups/$(LIBCUPSSTATIC) \
                $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) $(LIBGSSAPI)
 
 
index 94449eb46f4808131c47d7b6f53dcccb23ec4115..c34efac0c925059c8fe460043ff96db28d2bc575 100644 (file)
@@ -1,10 +1,9 @@
 /*
  * "$Id: cert.c 7673 2008-06-18 22:31:26Z mike $"
  *
- *   Authentication certificate routines for the Common UNIX
- *   Printing System (CUPS).
+ *   Authentication certificate routines for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -390,9 +389,8 @@ cupsdFindCert(const char *certificate)      /* I - Certificate */
 void
 cupsdInitCerts(void)
 {
+#ifndef HAVE_ARC4RANDOM
   cups_file_t  *fp;                    /* /dev/random file */
-  unsigned     seed;                   /* Seed for random number generator */
-  struct timeval tod;                  /* Time of day */
 
 
  /*
@@ -402,16 +400,20 @@ cupsdInitCerts(void)
 
   if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL)
   {
+    struct timeval tod;                        /* Time of day */
+
    /*
     * Get the time in usecs and use it as the initial seed...
     */
 
     gettimeofday(&tod, NULL);
 
-    seed = (unsigned)(tod.tv_sec + tod.tv_usec);
+    CUPS_SRAND((unsigned)(tod.tv_sec + tod.tv_usec));
   }
   else
   {
+    unsigned   seed;                   /* Seed for random number generator */
+
    /*
     * Read 4 random characters from the random device and use
     * them as the seed...
@@ -420,12 +422,11 @@ cupsdInitCerts(void)
     seed = cupsFileGetChar(fp);
     seed = (seed << 8) | cupsFileGetChar(fp);
     seed = (seed << 8) | cupsFileGetChar(fp);
-    seed = (seed << 8) | cupsFileGetChar(fp);
+    CUPS_SRAND((seed << 8) | cupsFileGetChar(fp));
 
     cupsFileClose(fp);
   }
-
-  CUPS_SRAND(seed);
+#endif /* !HAVE_ARC4RANDOM */
 
  /*
   * Create a root certificate and return...
index 77214aba6fab26cce88f7c776b579583f76805fe..fca0d18b179eb2870328478c400f5b5a465be5d1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printer class routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -117,7 +117,7 @@ cupsdAddPrinterToClass(
  * 'cupsdDeletePrinterFromClass()' - Delete a printer from a class.
  */
 
-void
+int                                    /* O - 1 if class changed, 0 otherwise */
 cupsdDeletePrinterFromClass(
     cupsd_printer_t *c,                        /* I - Class to delete from */
     cupsd_printer_t *p)                        /* I - Printer to delete */
@@ -149,13 +149,15 @@ cupsdDeletePrinterFromClass(
               (c->num_printers - i) * sizeof(cupsd_printer_t *));
   }
   else
-    return;
+    return (0);
 
  /*
   * Update the IPP attributes (have to do this for member-names)...
   */
 
   cupsdSetPrinterAttrs(c);
+
+  return (1);
 }
 
 
@@ -163,10 +165,11 @@ cupsdDeletePrinterFromClass(
  * 'cupsdDeletePrinterFromClasses()' - Delete a printer from all classes.
  */
 
-void
+int                                    /* O - 1 if class changed, 0 otherwise */
 cupsdDeletePrinterFromClasses(
     cupsd_printer_t *p)                        /* I - Printer to delete */
 {
+  int                  changed = 0;    /* Any class changed? */
   cupsd_printer_t      *c;             /* Pointer to current class */
 
 
@@ -179,7 +182,7 @@ cupsdDeletePrinterFromClasses(
        c;
        c = (cupsd_printer_t *)cupsArrayNext(Printers))
     if (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
-      cupsdDeletePrinterFromClass(c, p);
+      changed |= cupsdDeletePrinterFromClass(c, p);
 
  /*
   * Then clean out any empty implicit classes...
@@ -193,7 +196,10 @@ cupsdDeletePrinterFromClasses(
       cupsdLogMessage(CUPSD_LOG_DEBUG, "Deleting implicit class \"%s\"...",
                       c->name);
       cupsdDeletePrinter(c, 0);
+      changed = 1;
     }
+
+  return (changed);
 }
 
 
index 68288f69bd14b2751933d4d07008ab7fec6ab9c8..e9940ce2b8e00df4d57b1bbf3dedb1b7e2304434 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printer class definitions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -21,9 +21,9 @@
 extern cupsd_printer_t *cupsdAddClass(const char *name);
 extern void            cupsdAddPrinterToClass(cupsd_printer_t *c,
                                               cupsd_printer_t *p);
-extern void            cupsdDeletePrinterFromClass(cupsd_printer_t *c,
+extern int             cupsdDeletePrinterFromClass(cupsd_printer_t *c,
                                                    cupsd_printer_t *p);
-extern void            cupsdDeletePrinterFromClasses(cupsd_printer_t *p);
+extern int             cupsdDeletePrinterFromClasses(cupsd_printer_t *p);
 extern cupsd_printer_t *cupsdFindAvailablePrinter(const char *name);
 extern cupsd_printer_t *cupsdFindClass(const char *name);
 extern void            cupsdLoadAllClasses(void);
index 93fbf3419f7b6d2b722fbd2337fd003e2482ba74..2400b57fe5ddf34897dbfceeb48b464b4ec2d681 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Client routines for the Common UNIX Printing System (CUPS) scheduler.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   This file contains Kerberos support code, copyright 2006 by
@@ -1131,8 +1131,8 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
          *ptr = '\0';
       }
       else
-        snprintf(locale, sizeof(locale), "%s.%s",
-                con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], DefaultCharset);
+        snprintf(locale, sizeof(locale), "%s.UTF-8",
+                con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE]);
 
       con->language = cupsLangGet(locale);
     }
@@ -2192,6 +2192,15 @@ cupsdReadClient(cupsd_client_t *con)     /* I - Client to read from */
                return;
              }
            }
+           else if (filestats.st_size == 0)
+           {
+            /*
+             * Don't allow empty file...
+             */
+
+             unlink(con->filename);
+             cupsdClearString(&con->filename);
+           }
 
            if (con->command)
            {
index abcb0f183ab655a2d65dcb3cee71cbfc05ef44d9..bc83cc11c5e426d1a20854001e3a984f011c6074 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Configuration routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -108,7 +108,6 @@ static const cupsd_var_t    variables[] =
   { "ClassifyOverride",                &ClassifyOverride,      CUPSD_VARTYPE_BOOLEAN },
   { "ConfigFilePerm",          &ConfigFilePerm,        CUPSD_VARTYPE_INTEGER },
   { "DataDir",                 &DataDir,               CUPSD_VARTYPE_STRING },
-  { "DefaultCharset",          &DefaultCharset,        CUPSD_VARTYPE_STRING },
   { "DefaultLanguage",         &DefaultLanguage,       CUPSD_VARTYPE_STRING },
   { "DefaultLeaseDuration",    &DefaultLeaseDuration,  CUPSD_VARTYPE_INTEGER },
   { "DefaultPaperSize",                &DefaultPaperSize,      CUPSD_VARTYPE_STRING },
@@ -132,7 +131,6 @@ static const cupsd_var_t    variables[] =
   { "KeepAlive",               &KeepAlive,             CUPSD_VARTYPE_BOOLEAN },
 #ifdef HAVE_LAUNCHD
   { "LaunchdTimeout",          &LaunchdTimeout,        CUPSD_VARTYPE_INTEGER },
-  { "LaunchdConf",             &LaunchdConf,           CUPSD_VARTYPE_STRING },
 #endif /* HAVE_LAUNCHD */
   { "LimitRequestBody",                &MaxRequestSize,        CUPSD_VARTYPE_INTEGER },
   { "ListenBackLog",           &ListenBackLog,         CUPSD_VARTYPE_INTEGER },
@@ -540,8 +538,6 @@ cupsdReadConfiguration(void)
   else
     cupsdSetString(&DefaultLanguage, language->language);
 
-  cupsdSetString(&DefaultCharset, _cupsEncodingName(language->encoding));
-
   cupsdClearString(&DefaultPaperSize);
 
   cupsdSetString(&RIPCache, "8m");
@@ -692,7 +688,6 @@ cupsdReadConfiguration(void)
 
 #ifdef HAVE_LAUNCHD
   LaunchdTimeout = DEFAULT_TIMEOUT + 10;
-  cupsdSetString(&LaunchdConf, CUPS_DEFAULT_LAUNCHD_CONF);
 #endif /* HAVE_LAUNCHD */
 
 #ifdef __APPLE__
@@ -910,7 +905,7 @@ cupsdReadConfiguration(void)
   * Set the default locale using the language and charset...
   */
 
-  cupsdSetStringf(&DefaultLocale, "%s.%s", DefaultLanguage, DefaultCharset);
+  cupsdSetStringf(&DefaultLocale, "%s.UTF-8", DefaultLanguage);
 
  /*
   * Update all relative filenames to include the full path from ServerRoot...
index c30f97a5eac2ce785a82f771fec2f5443a5f1259..1084bc2af8f785dcf8e82a10fc50caff2a875d6a 100644 (file)
@@ -1,8 +1,7 @@
 /*
  * "$Id: conf.h 7935 2008-09-11 01:54:11Z mike $"
  *
- *   Configuration file definitions for the Common UNIX Printing System (CUPS)
- *   scheduler.
+ *   Configuration file definitions for CUPS.
  *
  *   Copyright 2007-2009 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
@@ -136,8 +135,6 @@ VAR char            *AccessLog              VALUE(NULL),
                                        /* Data file directory */
                        *DefaultLanguage        VALUE(NULL),
                                        /* Default language encoding */
-                       *DefaultCharset         VALUE(NULL),
-                                       /* Default charset */
                        *DefaultLocale          VALUE(NULL),
                                        /* Default locale */
                        *DefaultPaperSize       VALUE(NULL),
@@ -253,8 +250,6 @@ VAR int                     SSLOptions              VALUE(CUPSD_SSL_NONE);
 #ifdef HAVE_LAUNCHD
 VAR int                        LaunchdTimeout          VALUE(DEFAULT_KEEPALIVE);
                                        /* Time after which an idle cupsd will exit */
-VAR char               *LaunchdConf            VALUE(NULL);
-                                       /* launchd(8) configuration file */
 #endif /* HAVE_LAUNCHD */
 
 #ifdef __APPLE__
index 0d776a637874877f64b1c9b8cafe14ba888d82dd..b34f6616f4f682d13afb52f4d7b77496dd934c88 100644 (file)
@@ -1991,7 +1991,8 @@ load_drv(const char  *filename,           /* I - Actual filename */
          type = PPD_TYPE_PDF;
     }
 
-    for (product = (ppdcAttr *)d->attrs->first(), products_found = 0;
+    for (product = (ppdcAttr *)d->attrs->first(), products_found = 0,
+             ppd = NULL;
          product;
         product = (ppdcAttr *)d->attrs->next())
       if (!strcmp(product->name->value, "Product"))
index a2595d90ee4cee44d8baeb9d078632835f81cf06..ced835f2937dab82b3db5e8f9c4b6fd86c6e96f3 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   IPP routines for the Common UNIX Printing System (CUPS) scheduler.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   This file contains Kerberos support code, copyright 2006 by
@@ -390,7 +390,7 @@ cupsdProcessIPPRequest(
                     charset->values[0].string.text);
       else
        ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
-                    "attributes-charset", NULL, DefaultCharset);
+                    "attributes-charset", NULL, "utf-8");
 
       if (language)
        ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
@@ -904,6 +904,9 @@ accept_jobs(cupsd_client_t  *con,   /* I - Client connection */
 
   cupsdAddPrinterHistory(printer);
 
+  cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+                "Now accepting jobs.");
+
   if (dtype & CUPS_PRINTER_CLASS)
   {
     cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
@@ -1102,7 +1105,8 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
     cupsdSetString(&pclass->info, attr->values[0].string.text);
 
   if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs",
-                               IPP_TAG_BOOLEAN)) != NULL)
+                               IPP_TAG_BOOLEAN)) != NULL &&
+      attr->values[0].boolean != pclass->accepting)
   {
     cupsdLogMessage(CUPSD_LOG_INFO,
                     "Setting %s printer-is-accepting-jobs to %d (was %d.)",
@@ -1110,6 +1114,9 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
 
     pclass->accepting = attr->values[0].boolean;
     cupsdAddPrinterHistory(pclass);
+
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s accepting jobs.",
+                 pclass->accepting ? "Now" : "No longer");
   }
 
   if ((attr = ippFindAttribute(con->request, "printer-is-shared",
@@ -1154,6 +1161,9 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
     strlcpy(pclass->state_message, attr->values[0].string.text,
             sizeof(pclass->state_message));
     cupsdAddPrinterHistory(pclass);
+
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s",
+                  pclass->state_message);
   }
   if ((attr = ippFindAttribute(con->request, "member-uris",
                                IPP_TAG_URI)) != NULL)
@@ -1232,9 +1242,9 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
 
   if (modify)
   {
-    cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, pclass, NULL,
-                  "Class \"%s\" modified by \"%s\".", pclass->name,
-                 get_username(con));
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED | CUPSD_EVENT_PRINTER_CONFIG,
+                 pclass, NULL, "Class \"%s\" modified by \"%s\".",
+                 pclass->name, get_username(con));
 
     cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" modified by \"%s\".",
                     pclass->name, get_username(con));
@@ -1243,9 +1253,9 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
   {
     cupsdAddPrinterHistory(pclass);
 
-    cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, pclass, NULL,
-                  "New class \"%s\" added by \"%s\".", pclass->name,
-                 get_username(con));
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_CONFIG,
+                 pclass, NULL, "New class \"%s\" added by \"%s\".",
+                 pclass->name, get_username(con));
 
     cupsdLogMessage(CUPSD_LOG_INFO, "New class \"%s\" added by \"%s\".",
                     pclass->name, get_username(con));
@@ -1332,7 +1342,6 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
                *auth_info;             /* auth-info attribute */
   const char   *val;                   /* Default option value */
   int          priority;               /* Job priority */
-  char         *title;                 /* Job name/title */
   cupsd_job_t  *job;                   /* Current job */
   char         job_uri[HTTP_MAX_URI];  /* Job URI */
   int          kbytes;                 /* Size of print file */
@@ -2202,6 +2211,9 @@ add_job_subscriptions(
       ippAddSeparator(con->response);
       ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
                    "notify-subscription-id", sub->id);
+
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "Added subscription %d for job %d",
+                      sub->id, job->id);
     }
 
     if (attr)
@@ -2604,7 +2616,8 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
   }
 
   if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs",
-                               IPP_TAG_BOOLEAN)) != NULL)
+                               IPP_TAG_BOOLEAN)) != NULL &&
+      attr->values[0].boolean != printer->accepting)
   {
     cupsdLogMessage(CUPSD_LOG_INFO,
                     "Setting %s printer-is-accepting-jobs to %d (was %d.)",
@@ -2612,6 +2625,10 @@ add_printer(cupsd_client_t  *con,        /* I - Client connection */
 
     printer->accepting = attr->values[0].boolean;
     cupsdAddPrinterHistory(printer);
+
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+                  "%s accepting jobs.",
+                 printer->accepting ? "Now" : "No longer");
   }
 
   if ((attr = ippFindAttribute(con->request, "printer-is-shared",
@@ -2656,6 +2673,9 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
     strlcpy(printer->state_message, attr->values[0].string.text,
             sizeof(printer->state_message));
     cupsdAddPrinterHistory(printer);
+
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "%s",
+                  printer->state_message);
   }
 
   if ((attr = ippFindAttribute(con->request, "printer-state-reasons",
@@ -2697,6 +2717,9 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
 
     if (PrintcapFormat == PRINTCAP_PLIST)
       cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+                  "Printer \"%s\" state changed.", printer->name);
   }
 
   set_printer_defaults(con, printer);
@@ -2936,9 +2959,9 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
 
   if (modify)
   {
-    cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL,
-                  "Printer \"%s\" modified by \"%s\".", printer->name,
-                 get_username(con));
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED | CUPSD_EVENT_PRINTER_CONFIG,
+                  printer, NULL, "Printer \"%s\" modified by \"%s\".",
+                 printer->name, get_username(con));
 
     cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" modified by \"%s\".",
                     printer->name, get_username(con));
@@ -2947,9 +2970,9 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
   {
     cupsdAddPrinterHistory(printer);
 
-    cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, printer, NULL,
-                  "New printer \"%s\" added by \"%s\".", printer->name,
-                 get_username(con));
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_CONFIG,
+                  printer, NULL, "New printer \"%s\" added by \"%s\".",
+                 printer->name, get_username(con));
 
     cupsdLogMessage(CUPSD_LOG_INFO, "New printer \"%s\" added by \"%s\".",
                     printer->name, get_username(con));
@@ -6431,7 +6454,9 @@ delete_printer(cupsd_client_t  *con,      /* I - Client connection */
     cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" deleted by \"%s\".",
                     printer->name, get_username(con));
 
-    cupsdDeletePrinter(printer, 0);
+    if (cupsdDeletePrinter(printer, 0))
+      cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
+
     cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
   }
 
@@ -9034,6 +9059,9 @@ reject_jobs(cupsd_client_t  *con, /* I - Client connection */
 
   cupsdAddPrinterHistory(printer);
 
+  cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+                "No longer accepting jobs.");
+
   if (dtype & CUPS_PRINTER_CLASS)
   {
     cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
@@ -10186,7 +10214,7 @@ send_ipp_status(cupsd_client_t *con,    /* I - Client connection */
   if (ippFindAttribute(con->response, "attributes-charset",
                        IPP_TAG_ZERO) == NULL)
     ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
-                 "attributes-charset", NULL, DefaultCharset);
+                 "attributes-charset", NULL, "utf-8");
 
   if (ippFindAttribute(con->response, "attributes-natural-language",
                        IPP_TAG_ZERO) == NULL)
index 4442cacc7fdf7c655d3f8f5ce063bd053f548d1e..91a017b75b61741cf288e7eaa4d085c0881d0bf7 100644 (file)
@@ -4291,16 +4291,16 @@ update_job(cupsd_job_t *job)            /* I - Job to check */
       break;
   }
 
-  if (event & CUPSD_EVENT_PRINTER_STATE)
+  if (event & CUPSD_EVENT_JOB_PROGRESS)
+    cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job,
+                  "%s", job->printer->state_message);
+  else if (event & CUPSD_EVENT_PRINTER_STATE)
     cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL,
                  (job->printer->type & CUPS_PRINTER_CLASS) ?
                      "Class \"%s\" state changed." :
                      "Printer \"%s\" state changed.",
                  job->printer->name);
 
-  if (event & CUPSD_EVENT_JOB_PROGRESS)
-    cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job,
-                  "%s", job->printer->state_message);
 
   if (ptr == NULL && !job->status_buffer->bufused)
   {
index 2b4f9e0fdea16c868d29185ad8dd6fdaf064398e..85c8071668000a9c1fecb346dc79dcf4335210ac 100644 (file)
@@ -250,7 +250,8 @@ cupsdStartListening(void)
        unlink(lis->address.un.sun_path);
 
        /*
-       * Save the curent umask and set it to 0...
+       * Save the current umask and set it to 0 so that all users can access
+       * the domain socket...
        */
 
        mask = umask(0);
index 60e97d095a037814bc48d9776fe6faa75b8d7239..9dfb3896641fc6299e0ade0807d625d224a14020 100644 (file)
@@ -1450,7 +1450,7 @@ static void
 launchd_checkin(void)
 {
   size_t               i,              /* Looping var */
-                       count;          /* Numebr of listeners */
+                       count;          /* Number of listeners */
   int                  portnum;        /* Port number */
   launch_data_t                ld_msg,         /* Launch data message */
                        ld_resp,        /* Launch data response */
index 1e615ebe0c15c8d8d53fc4b13676a903f6838d00..876231d45e9001baf9794602063633afa1794d06 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printer routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -430,7 +430,7 @@ cupsdCreateCommonData(void)
 
   /* charset-configured */
   ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET | IPP_TAG_COPY,
-               "charset-configured", NULL, DefaultCharset);
+               "charset-configured", NULL, "utf-8");
 
   /* charset-supported */
   ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET | IPP_TAG_COPY,
@@ -450,8 +450,8 @@ cupsdCreateCommonData(void)
   ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_TEXT | IPP_TAG_COPY,
                "cups-version", NULL, CUPS_SVERSION + 6);
 
-  /* generated-natural-language-supported */
-  ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE | IPP_TAG_COPY,
+  /* generated-natural-language-supported (no IPP_TAG_COPY) */
+  ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
                "generated-natural-language-supported", NULL, DefaultLanguage);
 
   /* ipp-versions-supported */
@@ -534,8 +534,8 @@ cupsdCreateCommonData(void)
   ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                 "multiple-operation-time-out", MultipleOperationTimeout);
 
-  /* natural-language-configured */
-  ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE | IPP_TAG_COPY,
+  /* natural-language-configured (no IPP_TAG_COPY) */
+  ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
                "natural-language-configured", NULL, DefaultLanguage);
 
   /* notify-attributes-supported */
@@ -655,12 +655,13 @@ cupsdDeleteAllPrinters(void)
  * 'cupsdDeletePrinter()' - Delete a printer from the system.
  */
 
-void
+int                                    /* O - 1 if classes affected, 0 otherwise */
 cupsdDeletePrinter(
     cupsd_printer_t *p,                        /* I - Printer to delete */
     int             update)            /* I - Update printers.conf? */
 {
-  int  i;                              /* Looping var */
+  int  i,                              /* Looping var */
+       changed = 0;                    /* Class changed? */
 #ifdef __sgi
   char filename[1024];                 /* Interface script filename */
 #endif /* __sgi */
@@ -771,7 +772,7 @@ cupsdDeletePrinter(
 
   if (!(p->type & CUPS_PRINTER_IMPLICIT))
   {
-    cupsdDeletePrinterFromClasses(p);
+    changed = cupsdDeletePrinterFromClasses(p);
 
    /*
     * Deregister from any browse protocols...
@@ -848,6 +849,8 @@ cupsdDeletePrinter(
   */
 
   cupsArrayRestore(Printers);
+
+  return (changed);
 }
 
 
@@ -2771,6 +2774,12 @@ cupsdSetPrinterState(
     int             update)            /* I - Update printers.conf? */
 {
   ipp_pstate_t old_state;              /* Old printer state */
+  static const char * const printer_states[] =
+  {                                    /* State strings */
+    "idle",
+    "processing",
+    "stopped"
+  };
 
 
  /*
@@ -2794,9 +2803,9 @@ cupsdSetPrinterState(
   {
     cupsdAddEvent(s == IPP_PRINTER_STOPPED ? CUPSD_EVENT_PRINTER_STOPPED :
                       CUPSD_EVENT_PRINTER_STATE, p, NULL,
-                 "%s \"%s\" state changed.",
+                 "%s \"%s\" state changed to %s.",
                  (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer",
-                 p->name);
+                 p->name, printer_states[p->state]);
 
    /*
     * Let the browse code know this needs to be updated...
index 713539941874ea3cd3cdcb4b54085224f2984410..327909240b32c9b6cf4ad5cb5eabd9ff6007a29e 100644 (file)
@@ -140,7 +140,7 @@ extern void         cupsdAddPrinterUser(cupsd_printer_t *p,
                                            const char *username);
 extern void            cupsdCreateCommonData(void);
 extern void            cupsdDeleteAllPrinters(void);
-extern void            cupsdDeletePrinter(cupsd_printer_t *p, int update);
+extern int             cupsdDeletePrinter(cupsd_printer_t *p, int update);
 extern cupsd_printer_t *cupsdFindDest(const char *name);
 extern cupsd_printer_t *cupsdFindPrinter(const char *name);
 extern cupsd_quota_t   *cupsdFindQuota(cupsd_printer_t *p,
index 53b2c1f981017fa3e8a208a964cfda4248bdf883..d6ddb8353bba72a550d2ae9a8175ea77cb246934 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7871 2008-08-27 21:12:43Z mike $"
 #
-#   Standards makefile for the Common UNIX Printing System (CUPS).
+#   Standards makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -153,8 +153,8 @@ uninstall:
 # rfctohtml - make html versions of RFCs...
 #
 
-rfctohtml:     rfctohtml.o ../cups/libcups.a
-       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ rfctohtml.o ../cups/libcups.a \
+rfctohtml:     rfctohtml.o ../cups/$(LIBCUPSSTATIC)
+       $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ rfctohtml.o ../cups/$(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
diff --git a/standards/rfc2046.txt b/standards/rfc2046.txt
new file mode 100644 (file)
index 0000000..84d90c1
--- /dev/null
@@ -0,0 +1,2467 @@
+
+
+
+
+
+
+Network Working Group                                          N. Freed
+Request for Comments: 2046                                     Innosoft
+Obsoletes: 1521, 1522, 1590                               N. Borenstein
+Category: Standards Track                                 First Virtual
+                                                          November 1996
+
+
+                 Multipurpose Internet Mail Extensions
+                            (MIME) Part Two:
+                              Media Types
+
+Status of this Memo
+
+   This document specifies an Internet standards track protocol for the
+   Internet community, and requests discussion and suggestions for
+   improvements.  Please refer to the current edition of the "Internet
+   Official Protocol Standards" (STD 1) for the standardization state
+   and status of this protocol.  Distribution of this memo is unlimited.
+
+Abstract
+
+   STD 11, RFC 822 defines a message representation protocol specifying
+   considerable detail about US-ASCII message headers, but which leaves
+   the message content, or message body, as flat US-ASCII text.  This
+   set of documents, collectively called the Multipurpose Internet Mail
+   Extensions, or MIME, redefines the format of messages to allow for
+
+    (1)   textual message bodies in character sets other than
+          US-ASCII,
+
+    (2)   an extensible set of different formats for non-textual
+          message bodies,
+
+    (3)   multi-part message bodies, and
+
+    (4)   textual header information in character sets other than
+          US-ASCII.
+
+   These documents are based on earlier work documented in RFC 934, STD
+   11, and RFC 1049, but extends and revises them.  Because RFC 822 said
+   so little about message bodies, these documents are largely
+   orthogonal to (rather than a revision of) RFC 822.
+
+   The initial document in this set, RFC 2045, specifies the various
+   headers used to describe the structure of MIME messages. This second
+   document defines the general structure of the MIME media typing
+   system and defines an initial set of media types. The third document,
+   RFC 2047, describes extensions to RFC 822 to allow non-US-ASCII text
+
+
+
+Freed & Borenstein          Standards Track                     [Page 1]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   data in Internet mail header fields. The fourth document, RFC 2048,
+   specifies various IANA registration procedures for MIME-related
+   facilities.  The fifth and final document, RFC 2049, describes MIME
+   conformance criteria as well as providing some illustrative examples
+   of MIME message formats, acknowledgements, and the bibliography.
+
+   These documents are revisions of RFCs 1521 and 1522, which themselves
+   were revisions of RFCs 1341 and 1342.  An appendix in RFC 2049
+   describes differences and changes from previous versions.
+
+Table of Contents
+
+   1. Introduction .........................................    3
+   2. Definition of a Top-Level Media Type .................    4
+   3. Overview Of The Initial Top-Level Media Types ........    4
+   4. Discrete Media Type Values ...........................    6
+   4.1 Text Media Type .....................................    6
+   4.1.1 Representation of Line Breaks .....................    7
+   4.1.2 Charset Parameter .................................    7
+   4.1.3 Plain Subtype .....................................   11
+   4.1.4 Unrecognized Subtypes .............................   11
+   4.2 Image Media Type ....................................   11
+   4.3 Audio Media Type ....................................   11
+   4.4 Video Media Type ....................................   12
+   4.5 Application Media Type ..............................   12
+   4.5.1 Octet-Stream Subtype ..............................   13
+   4.5.2 PostScript Subtype ................................   14
+   4.5.3 Other Application Subtypes ........................   17
+   5. Composite Media Type Values ..........................   17
+   5.1 Multipart Media Type ................................   17
+   5.1.1 Common Syntax .....................................   19
+   5.1.2 Handling Nested Messages and Multiparts ...........   24
+   5.1.3 Mixed Subtype .....................................   24
+   5.1.4 Alternative Subtype ...............................   24
+   5.1.5 Digest Subtype ....................................   26
+   5.1.6 Parallel Subtype ..................................   27
+   5.1.7 Other Multipart Subtypes ..........................   28
+   5.2 Message Media Type ..................................   28
+   5.2.1 RFC822 Subtype ....................................   28
+   5.2.2 Partial Subtype ...................................   29
+   5.2.2.1 Message Fragmentation and Reassembly ............   30
+   5.2.2.2 Fragmentation and Reassembly Example ............   31
+   5.2.3 External-Body Subtype .............................   33
+   5.2.4 Other Message Subtypes ............................   40
+   6. Experimental Media Type Values .......................   40
+   7. Summary ..............................................   41
+   8. Security Considerations ..............................   41
+   9. Authors' Addresses ...................................   42
+
+
+
+Freed & Borenstein          Standards Track                     [Page 2]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   A. Collected Grammar ....................................   43
+
+1.  Introduction
+
+   The first document in this set, RFC 2045, defines a number of header
+   fields, including Content-Type. The Content-Type field is used to
+   specify the nature of the data in the body of a MIME entity, by
+   giving media type and subtype identifiers, and by providing auxiliary
+   information that may be required for certain media types.  After the
+   type and subtype names, the remainder of the header field is simply a
+   set of parameters, specified in an attribute/value notation.  The
+   ordering of parameters is not significant.
+
+   In general, the top-level media type is used to declare the general
+   type of data, while the subtype specifies a specific format for that
+   type of data.  Thus, a media type of "image/xyz" is enough to tell a
+   user agent that the data is an image, even if the user agent has no
+   knowledge of the specific image format "xyz".  Such information can
+   be used, for example, to decide whether or not to show a user the raw
+   data from an unrecognized subtype -- such an action might be
+   reasonable for unrecognized subtypes of "text", but not for
+   unrecognized subtypes of "image" or "audio".  For this reason,
+   registered subtypes of "text", "image", "audio", and "video" should
+   not contain embedded information that is really of a different type.
+   Such compound formats should be represented using the "multipart" or
+   "application" types.
+
+   Parameters are modifiers of the media subtype, and as such do not
+   fundamentally affect the nature of the content.  The set of
+   meaningful parameters depends on the media type and subtype.  Most
+   parameters are associated with a single specific subtype.  However, a
+   given top-level media type may define parameters which are applicable
+   to any subtype of that type.  Parameters may be required by their
+   defining media type or subtype or they may be optional.  MIME
+   implementations must also ignore any parameters whose names they do
+   not recognize.
+
+   MIME's Content-Type header field and media type mechanism has been
+   carefully designed to be extensible, and it is expected that the set
+   of media type/subtype pairs and their associated parameters will grow
+   significantly over time.  Several other MIME facilities, such as
+   transfer encodings and "message/external-body" access types, are
+   likely to have new values defined over time.  In order to ensure that
+   the set of such values is developed in an orderly, well-specified,
+   and public manner, MIME sets up a registration process which uses the
+   Internet Assigned Numbers Authority (IANA) as a central registry for
+   MIME's various areas of extensibility.  The registration process for
+   these areas is described in a companion document, RFC 2048.
+
+
+
+Freed & Borenstein          Standards Track                     [Page 3]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   The initial seven standard top-level media type are defined and
+   described in the remainder of this document.
+
+2.  Definition of a Top-Level Media Type
+
+   The definition of a top-level media type consists of:
+
+    (1)   a name and a description of the type, including
+          criteria for whether a particular type would qualify
+          under that type,
+
+    (2)   the names and definitions of parameters, if any, which
+          are defined for all subtypes of that type (including
+          whether such parameters are required or optional),
+
+    (3)   how a user agent and/or gateway should handle unknown
+          subtypes of this type,
+
+    (4)   general considerations on gatewaying entities of this
+          top-level type, if any, and
+
+    (5)   any restrictions on content-transfer-encodings for
+          entities of this top-level type.
+
+3.  Overview Of The Initial Top-Level Media Types
+
+   The five discrete top-level media types are:
+
+    (1)   text -- textual information.  The subtype "plain" in
+          particular indicates plain text containing no
+          formatting commands or directives of any sort. Plain
+          text is intended to be displayed "as-is". No special
+          software is required to get the full meaning of the
+          text, aside from support for the indicated character
+          set. Other subtypes are to be used for enriched text in
+          forms where application software may enhance the
+          appearance of the text, but such software must not be
+          required in order to get the general idea of the
+          content.  Possible subtypes of "text" thus include any
+          word processor format that can be read without
+          resorting to software that understands the format.  In
+          particular, formats that employ embeddded binary
+          formatting information are not considered directly
+          readable. A very simple and portable subtype,
+          "richtext", was defined in RFC 1341, with a further
+          revision in RFC 1896 under the name "enriched".
+
+
+
+
+
+Freed & Borenstein          Standards Track                     [Page 4]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+    (2)   image -- image data.  "Image" requires a display device
+          (such as a graphical display, a graphics printer, or a
+          FAX machine) to view the information. An initial
+          subtype is defined for the widely-used image format
+          JPEG. .  subtypes are defined for two widely-used image
+          formats, jpeg and gif.
+
+    (3)   audio -- audio data.  "Audio" requires an audio output
+          device (such as a speaker or a telephone) to "display"
+          the contents.  An initial subtype "basic" is defined in
+          this document.
+
+    (4)   video -- video data.  "Video" requires the capability
+          to display moving images, typically including
+          specialized hardware and software.  An initial subtype
+          "mpeg" is defined in this document.
+
+    (5)   application -- some other kind of data, typically
+          either uninterpreted binary data or information to be
+          processed by an application.  The subtype "octet-
+          stream" is to be used in the case of uninterpreted
+          binary data, in which case the simplest recommended
+          action is to offer to write the information into a file
+          for the user.  The "PostScript" subtype is also defined
+          for the transport of PostScript material.  Other
+          expected uses for "application" include spreadsheets,
+          data for mail-based scheduling systems, and languages
+          for "active" (computational) messaging, and word
+          processing formats that are not directly readable.
+          Note that security considerations may exist for some
+          types of application data, most notably
+          "application/PostScript" and any form of active
+          messaging.  These issues are discussed later in this
+          document.
+
+   The two composite top-level media types are:
+
+    (1)   multipart -- data consisting of multiple entities of
+          independent data types.  Four subtypes are initially
+          defined, including the basic "mixed" subtype specifying
+          a generic mixed set of parts, "alternative" for
+          representing the same data in multiple formats,
+          "parallel" for parts intended to be viewed
+          simultaneously, and "digest" for multipart entities in
+          which each part has a default type of "message/rfc822".
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                     [Page 5]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+    (2)   message -- an encapsulated message.  A body of media
+          type "message" is itself all or a portion of some kind
+          of message object.  Such objects may or may not in turn
+          contain other entities.  The "rfc822" subtype is used
+          when the encapsulated content is itself an RFC 822
+          message.  The "partial" subtype is defined for partial
+          RFC 822 messages, to permit the fragmented transmission
+          of bodies that are thought to be too large to be passed
+          through transport facilities in one piece.  Another
+          subtype, "external-body", is defined for specifying
+          large bodies by reference to an external data source.
+
+   It should be noted that the list of media type values given here may
+   be augmented in time, via the mechanisms described above, and that
+   the set of subtypes is expected to grow substantially.
+
+4.  Discrete Media Type Values
+
+   Five of the seven initial media type values refer to discrete bodies.
+   The content of these types must be handled by non-MIME mechanisms;
+   they are opaque to MIME processors.
+
+4.1.  Text Media Type
+
+   The "text" media type is intended for sending material which is
+   principally textual in form.  A "charset" parameter may be used to
+   indicate the character set of the body text for "text" subtypes,
+   notably including the subtype "text/plain", which is a generic
+   subtype for plain text.  Plain text does not provide for or allow
+   formatting commands, font attribute specifications, processing
+   instructions, interpretation directives, or content markup.  Plain
+   text is seen simply as a linear sequence of characters, possibly
+   interrupted by line breaks or page breaks.  Plain text may allow the
+   stacking of several characters in the same position in the text.
+   Plain text in scripts like Arabic and Hebrew may also include
+   facilitites that allow the arbitrary mixing of text segments with
+   opposite writing directions.
+
+   Beyond plain text, there are many formats for representing what might
+   be known as "rich text".  An interesting characteristic of many such
+   representations is that they are to some extent readable even without
+   the software that interprets them.  It is useful, then, to
+   distinguish them, at the highest level, from such unreadable data as
+   images, audio, or text represented in an unreadable form. In the
+   absence of appropriate interpretation software, it is reasonable to
+   show subtypes of "text" to the user, while it is not reasonable to do
+   so with most nontextual data. Such formatted textual data should be
+   represented using subtypes of "text".
+
+
+
+Freed & Borenstein          Standards Track                     [Page 6]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+4.1.1.  Representation of Line Breaks
+
+   The canonical form of any MIME "text" subtype MUST always represent a
+   line break as a CRLF sequence.  Similarly, any occurrence of CRLF in
+   MIME "text" MUST represent a line break.  Use of CR and LF outside of
+   line break sequences is also forbidden.
+
+   This rule applies regardless of format or character set or sets
+   involved.
+
+   NOTE: The proper interpretation of line breaks when a body is
+   displayed depends on the media type. In particular, while it is
+   appropriate to treat a line break as a transition to a new line when
+   displaying a "text/plain" body, this treatment is actually incorrect
+   for other subtypes of "text" like "text/enriched" [RFC-1896].
+   Similarly, whether or not line breaks should be added during display
+   operations is also a function of the media type. It should not be
+   necessary to add any line breaks to display "text/plain" correctly,
+   whereas proper display of "text/enriched" requires the appropriate
+   addition of line breaks.
+
+   NOTE: Some protocols defines a maximum line length.  E.g. SMTP [RFC-
+   821] allows a maximum of 998 octets before the next CRLF sequence.
+   To be transported by such protocols, data which includes too long
+   segments without CRLF sequences must be encoded with a suitable
+   content-transfer-encoding.
+
+4.1.2.  Charset Parameter
+
+   A critical parameter that may be specified in the Content-Type field
+   for "text/plain" data is the character set.  This is specified with a
+   "charset" parameter, as in:
+
+     Content-type: text/plain; charset=iso-8859-1
+
+   Unlike some other parameter values, the values of the charset
+   parameter are NOT case sensitive.  The default character set, which
+   must be assumed in the absence of a charset parameter, is US-ASCII.
+
+   The specification for any future subtypes of "text" must specify
+   whether or not they will also utilize a "charset" parameter, and may
+   possibly restrict its values as well.  For other subtypes of "text"
+   than "text/plain", the semantics of the "charset" parameter should be
+   defined to be identical to those specified here for "text/plain",
+   i.e., the body consists entirely of characters in the given charset.
+   In particular, definers of future "text" subtypes should pay close
+   attention to the implications of multioctet character sets for their
+   subtype definitions.
+
+
+
+Freed & Borenstein          Standards Track                     [Page 7]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   The charset parameter for subtypes of "text" gives a name of a
+   character set, as "character set" is defined in RFC 2045.  The rules
+   regarding line breaks detailed in the previous section must also be
+   observed -- a character set whose definition does not conform to
+   these rules cannot be used in a MIME "text" subtype.
+
+   An initial list of predefined character set names can be found at the
+   end of this section.  Additional character sets may be registered
+   with IANA.
+
+   Other media types than subtypes of "text" might choose to employ the
+   charset parameter as defined here, but with the CRLF/line break
+   restriction removed.  Therefore, all character sets that conform to
+   the general definition of "character set" in RFC 2045 can be
+   registered for MIME use.
+
+   Note that if the specified character set includes 8-bit characters
+   and such characters are used in the body, a Content-Transfer-Encoding
+   header field and a corresponding encoding on the data are required in
+   order to transmit the body via some mail transfer protocols, such as
+   SMTP [RFC-821].
+
+   The default character set, US-ASCII, has been the subject of some
+   confusion and ambiguity in the past.  Not only were there some
+   ambiguities in the definition, there have been wide variations in
+   practice.  In order to eliminate such ambiguity and variations in the
+   future, it is strongly recommended that new user agents explicitly
+   specify a character set as a media type parameter in the Content-Type
+   header field. "US-ASCII" does not indicate an arbitrary 7-bit
+   character set, but specifies that all octets in the body must be
+   interpreted as characters according to the US-ASCII character set.
+   National and application-oriented versions of ISO 646 [ISO-646] are
+   usually NOT identical to US-ASCII, and in that case their use in
+   Internet mail is explicitly discouraged.  The omission of the ISO 646
+   character set from this document is deliberate in this regard.  The
+   character set name of "US-ASCII" explicitly refers to the character
+   set defined in ANSI X3.4-1986 [US- ASCII].  The new international
+   reference version (IRV) of the 1991 edition of ISO 646 is identical
+   to US-ASCII.  The character set name "ASCII" is reserved and must not
+   be used for any purpose.
+
+   NOTE: RFC 821 explicitly specifies "ASCII", and references an earlier
+   version of the American Standard.  Insofar as one of the purposes of
+   specifying a media type and character set is to permit the receiver
+   to unambiguously determine how the sender intended the coded message
+   to be interpreted, assuming anything other than "strict ASCII" as the
+   default would risk unintentional and incompatible changes to the
+   semantics of messages now being transmitted.  This also implies that
+
+
+
+Freed & Borenstein          Standards Track                     [Page 8]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   messages containing characters coded according to other versions of
+   ISO 646 than US-ASCII and the 1991 IRV, or using code-switching
+   procedures (e.g., those of ISO 2022), as well as 8bit or multiple
+   octet character encodings MUST use an appropriate character set
+   specification to be consistent with MIME.
+
+   The complete US-ASCII character set is listed in ANSI X3.4- 1986.
+   Note that the control characters including DEL (0-31, 127) have no
+   defined meaning in apart from the combination CRLF (US-ASCII values
+   13 and 10) indicating a new line.  Two of the characters have de
+   facto meanings in wide use: FF (12) often means "start subsequent
+   text on the beginning of a new page"; and TAB or HT (9) often (though
+   not always) means "move the cursor to the next available column after
+   the current position where the column number is a multiple of 8
+   (counting the first column as column 0)."  Aside from these
+   conventions, any use of the control characters or DEL in a body must
+   either occur
+
+    (1)   because a subtype of text other than "plain"
+          specifically assigns some additional meaning, or
+
+    (2)   within the context of a private agreement between the
+          sender and recipient. Such private agreements are
+          discouraged and should be replaced by the other
+          capabilities of this document.
+
+   NOTE: An enormous proliferation of character sets exist beyond US-
+   ASCII.  A large number of partially or totally overlapping character
+   sets is NOT a good thing.  A SINGLE character set that can be used
+   universally for representing all of the world's languages in Internet
+   mail would be preferrable.  Unfortunately, existing practice in
+   several communities seems to point to the continued use of multiple
+   character sets in the near future.  A small number of standard
+   character sets are, therefore, defined for Internet use in this
+   document.
+
+   The defined charset values are:
+
+    (1)   US-ASCII -- as defined in ANSI X3.4-1986 [US-ASCII].
+
+    (2)   ISO-8859-X -- where "X" is to be replaced, as
+          necessary, for the parts of ISO-8859 [ISO-8859].  Note
+          that the ISO 646 character sets have deliberately been
+          omitted in favor of their 8859 replacements, which are
+          the designated character sets for Internet mail.  As of
+          the publication of this document, the legitimate values
+          for "X" are the digits 1 through 10.
+
+
+
+
+Freed & Borenstein          Standards Track                     [Page 9]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   Characters in the range 128-159 has no assigned meaning in ISO-8859-
+   X.  Characters with values below 128 in ISO-8859-X have the same
+   assigned meaning as they do in US-ASCII.
+
+   Part 6 of ISO 8859 (Latin/Arabic alphabet) and part 8 (Latin/Hebrew
+   alphabet) includes both characters for which the normal writing
+   direction is right to left and characters for which it is left to
+   right, but do not define a canonical ordering method for representing
+   bi-directional text.  The charset values "ISO-8859-6" and "ISO-8859-
+   8", however, specify that the visual method is used [RFC-1556].
+
+   All of these character sets are used as pure 7bit or 8bit sets
+   without any shift or escape functions.  The meaning of shift and
+   escape sequences in these character sets is not defined.
+
+   The character sets specified above are the ones that were relatively
+   uncontroversial during the drafting of MIME.  This document does not
+   endorse the use of any particular character set other than US-ASCII,
+   and recognizes that the future evolution of world character sets
+   remains unclear.
+
+   Note that the character set used, if anything other than US- ASCII,
+   must always be explicitly specified in the Content-Type field.
+
+   No character set name other than those defined above may be used in
+   Internet mail without the publication of a formal specification and
+   its registration with IANA, or by private agreement, in which case
+   the character set name must begin with "X-".
+
+   Implementors are discouraged from defining new character sets unless
+   absolutely necessary.
+
+   The "charset" parameter has been defined primarily for the purpose of
+   textual data, and is described in this section for that reason.
+   However, it is conceivable that non-textual data might also wish to
+   specify a charset value for some purpose, in which case the same
+   syntax and values should be used.
+
+   In general, composition software should always use the "lowest common
+   denominator" character set possible.  For example, if a body contains
+   only US-ASCII characters, it SHOULD be marked as being in the US-
+   ASCII character set, not ISO-8859-1, which, like all the ISO-8859
+   family of character sets, is a superset of US-ASCII.  More generally,
+   if a widely-used character set is a subset of another character set,
+   and a body contains only characters in the widely-used subset, it
+   should be labelled as being in that subset.  This will increase the
+   chances that the recipient will be able to view the resulting entity
+   correctly.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 10]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+4.1.3.  Plain Subtype
+
+   The simplest and most important subtype of "text" is "plain".  This
+   indicates plain text that does not contain any formatting commands or
+   directives. Plain text is intended to be displayed "as-is", that is,
+   no interpretation of embedded formatting commands, font attribute
+   specifications, processing instructions, interpretation directives,
+   or content markup should be necessary for proper display.  The
+   default media type of "text/plain; charset=us-ascii" for Internet
+   mail describes existing Internet practice.  That is, it is the type
+   of body defined by RFC 822.
+
+   No other "text" subtype is defined by this document.
+
+4.1.4.  Unrecognized Subtypes
+
+   Unrecognized subtypes of "text" should be treated as subtype "plain"
+   as long as the MIME implementation knows how to handle the charset.
+   Unrecognized subtypes which also specify an unrecognized charset
+   should be treated as "application/octet- stream".
+
+4.2.  Image Media Type
+
+   A media type of "image" indicates that the body contains an image.
+   The subtype names the specific image format.  These names are not
+   case sensitive. An initial subtype is "jpeg" for the JPEG format
+   using JFIF encoding [JPEG].
+
+   The list of "image" subtypes given here is neither exclusive nor
+   exhaustive, and is expected to grow as more types are registered with
+   IANA, as described in RFC 2048.
+
+   Unrecognized subtypes of "image" should at a miniumum be treated as
+   "application/octet-stream".  Implementations may optionally elect to
+   pass subtypes of "image" that they do not specifically recognize to a
+   secure and robust general-purpose image viewing application, if such
+   an application is available.
+
+   NOTE: Using of a generic-purpose image viewing application this way
+   inherits the security problems of the most dangerous type supported
+   by the application.
+
+4.3.  Audio Media Type
+
+   A media type of "audio" indicates that the body contains audio data.
+   Although there is not yet a consensus on an "ideal" audio format for
+   use with computers, there is a pressing need for a format capable of
+   providing interoperable behavior.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 11]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   The initial subtype of "basic" is specified to meet this requirement
+   by providing an absolutely minimal lowest common denominator audio
+   format.  It is expected that richer formats for higher quality and/or
+   lower bandwidth audio will be defined by a later document.
+
+   The content of the "audio/basic" subtype is single channel audio
+   encoded using 8bit ISDN mu-law [PCM] at a sample rate of 8000 Hz.
+
+   Unrecognized subtypes of "audio" should at a miniumum be treated as
+   "application/octet-stream".  Implementations may optionally elect to
+   pass subtypes of "audio" that they do not specifically recognize to a
+   robust general-purpose audio playing application, if such an
+   application is available.
+
+4.4.  Video Media Type
+
+   A media type of "video" indicates that the body contains a time-
+   varying-picture image, possibly with color and coordinated sound.
+   The term 'video' is used in its most generic sense, rather than with
+   reference to any particular technology or format, and is not meant to
+   preclude subtypes such as animated drawings encoded compactly.  The
+   subtype "mpeg" refers to video coded according to the MPEG standard
+   [MPEG].
+
+   Note that although in general this document strongly discourages the
+   mixing of multiple media in a single body, it is recognized that many
+   so-called video formats include a representation for synchronized
+   audio, and this is explicitly permitted for subtypes of "video".
+
+   Unrecognized subtypes of "video" should at a minumum be treated as
+   "application/octet-stream".  Implementations may optionally elect to
+   pass subtypes of "video" that they do not specifically recognize to a
+   robust general-purpose video display application, if such an
+   application is available.
+
+4.5.  Application Media Type
+
+   The "application" media type is to be used for discrete data which do
+   not fit in any of the other categories, and particularly for data to
+   be processed by some type of application program.  This is
+   information which must be processed by an application before it is
+   viewable or usable by a user.  Expected uses for the "application"
+   media type include file transfer, spreadsheets, data for mail-based
+   scheduling systems, and languages for "active" (computational)
+   material.  (The latter, in particular, can pose security problems
+   which must be understood by implementors, and are considered in
+   detail in the discussion of the "application/PostScript" media type.)
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 12]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   For example, a meeting scheduler might define a standard
+   representation for information about proposed meeting dates.  An
+   intelligent user agent would use this information to conduct a dialog
+   with the user, and might then send additional material based on that
+   dialog.  More generally, there have been several "active" messaging
+   languages developed in which programs in a suitably specialized
+   language are transported to a remote location and automatically run
+   in the recipient's environment.
+
+   Such applications may be defined as subtypes of the "application"
+   media type. This document defines two subtypes:
+
+   octet-stream, and PostScript.
+
+   The subtype of "application" will often be either the name or include
+   part of the name of the application for which the data are intended.
+   This does not mean, however, that any application program name may be
+   used freely as a subtype of "application".
+
+4.5.1.  Octet-Stream Subtype
+
+   The "octet-stream" subtype is used to indicate that a body contains
+   arbitrary binary data.  The set of currently defined parameters is:
+
+    (1)   TYPE -- the general type or category of binary data.
+          This is intended as information for the human recipient
+          rather than for any automatic processing.
+
+    (2)   PADDING -- the number of bits of padding that were
+          appended to the bit-stream comprising the actual
+          contents to produce the enclosed 8bit byte-oriented
+          data.  This is useful for enclosing a bit-stream in a
+          body when the total number of bits is not a multiple of
+          8.
+
+   Both of these parameters are optional.
+
+   An additional parameter, "CONVERSIONS", was defined in RFC 1341 but
+   has since been removed.  RFC 1341 also defined the use of a "NAME"
+   parameter which gave a suggested file name to be used if the data
+   were to be written to a file.  This has been deprecated in
+   anticipation of a separate Content-Disposition header field, to be
+   defined in a subsequent RFC.
+
+   The recommended action for an implementation that receives an
+   "application/octet-stream" entity is to simply offer to put the data
+   in a file, with any Content-Transfer-Encoding undone, or perhaps to
+   use it as input to a user-specified process.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 13]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   To reduce the danger of transmitting rogue programs, it is strongly
+   recommended that implementations NOT implement a path-search
+   mechanism whereby an arbitrary program named in the Content-Type
+   parameter (e.g., an "interpreter=" parameter) is found and executed
+   using the message body as input.
+
+4.5.2.  PostScript Subtype
+
+   A media type of "application/postscript" indicates a PostScript
+   program.  Currently two variants of the PostScript language are
+   allowed; the original level 1 variant is described in [POSTSCRIPT]
+   and the more recent level 2 variant is described in [POSTSCRIPT2].
+
+   PostScript is a registered trademark of Adobe Systems, Inc.  Use of
+   the MIME media type "application/postscript" implies recognition of
+   that trademark and all the rights it entails.
+
+   The PostScript language definition provides facilities for internal
+   labelling of the specific language features a given program uses.
+   This labelling, called the PostScript document structuring
+   conventions, or DSC, is very general and provides substantially more
+   information than just the language level.  The use of document
+   structuring conventions, while not required, is strongly recommended
+   as an aid to interoperability.  Documents which lack proper
+   structuring conventions cannot be tested to see whether or not they
+   will work in a given environment.  As such, some systems may assume
+   the worst and refuse to process unstructured documents.
+
+   The execution of general-purpose PostScript interpreters entails
+   serious security risks, and implementors are discouraged from simply
+   sending PostScript bodies to "off- the-shelf" interpreters.  While it
+   is usually safe to send PostScript to a printer, where the potential
+   for harm is greatly constrained by typical printer environments,
+   implementors should consider all of the following before they add
+   interactive display of PostScript bodies to their MIME readers.
+
+   The remainder of this section outlines some, though probably not all,
+   of the possible problems with the transport of PostScript entities.
+
+    (1)   Dangerous operations in the PostScript language
+          include, but may not be limited to, the PostScript
+          operators "deletefile", "renamefile", "filenameforall",
+          and "file".  "File" is only dangerous when applied to
+          something other than standard input or output.
+          Implementations may also define additional nonstandard
+          file operators; these may also pose a threat to
+          security. "Filenameforall", the wildcard file search
+          operator, may appear at first glance to be harmless.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 14]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+          Note, however, that this operator has the potential to
+          reveal information about what files the recipient has
+          access to, and this information may itself be
+          sensitive.  Message senders should avoid the use of
+          potentially dangerous file operators, since these
+          operators are quite likely to be unavailable in secure
+          PostScript implementations.  Message receiving and
+          displaying software should either completely disable
+          all potentially dangerous file operators or take
+          special care not to delegate any special authority to
+          their operation.  These operators should be viewed as
+          being done by an outside agency when interpreting
+          PostScript documents.  Such disabling and/or checking
+          should be done completely outside of the reach of the
+          PostScript language itself; care should be taken to
+          insure that no method exists for re-enabling full-
+          function versions of these operators.
+
+    (2)   The PostScript language provides facilities for exiting
+          the normal interpreter, or server, loop.  Changes made
+          in this "outer" environment are customarily retained
+          across documents, and may in some cases be retained
+          semipermanently in nonvolatile memory.  The operators
+          associated with exiting the interpreter loop have the
+          potential to interfere with subsequent document
+          processing.  As such, their unrestrained use
+          constitutes a threat of service denial.  PostScript
+          operators that exit the interpreter loop include, but
+          may not be limited to, the exitserver and startjob
+          operators.  Message sending software should not
+          generate PostScript that depends on exiting the
+          interpreter loop to operate, since the ability to exit
+          will probably be unavailable in secure PostScript
+          implementations.  Message receiving and displaying
+          software should completely disable the ability to make
+          retained changes to the PostScript environment by
+          eliminating or disabling the "startjob" and
+          "exitserver" operations.  If these operations cannot be
+          eliminated or completely disabled the password
+          associated with them should at least be set to a hard-
+          to-guess value.
+
+    (3)   PostScript provides operators for setting system-wide
+          and device-specific parameters.  These parameter
+          settings may be retained across jobs and may
+          potentially pose a threat to the correct operation of
+          the interpreter.  The PostScript operators that set
+          system and device parameters include, but may not be
+
+
+
+Freed & Borenstein          Standards Track                    [Page 15]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+          limited to, the "setsystemparams" and "setdevparams"
+          operators.  Message sending software should not
+          generate PostScript that depends on the setting of
+          system or device parameters to operate correctly.  The
+          ability to set these parameters will probably be
+          unavailable in secure PostScript implementations.
+          Message receiving and displaying software should
+          disable the ability to change system and device
+          parameters.  If these operators cannot be completely
+          disabled the password associated with them should at
+          least be set to a hard-to-guess value.
+
+    (4)   Some PostScript implementations provide nonstandard
+          facilities for the direct loading and execution of
+          machine code.  Such facilities are quite obviously open
+          to substantial abuse.  Message sending software should
+          not make use of such features.  Besides being totally
+          hardware-specific, they are also likely to be
+          unavailable in secure implementations of PostScript.
+          Message receiving and displaying software should not
+          allow such operators to be used if they exist.
+
+    (5)   PostScript is an extensible language, and many, if not
+          most, implementations of it provide a number of their
+          own extensions.  This document does not deal with such
+          extensions explicitly since they constitute an unknown
+          factor.  Message sending software should not make use
+          of nonstandard extensions; they are likely to be
+          missing from some implementations.  Message receiving
+          and displaying software should make sure that any
+          nonstandard PostScript operators are secure and don't
+          present any kind of threat.
+
+    (6)   It is possible to write PostScript that consumes huge
+          amounts of various system resources.  It is also
+          possible to write PostScript programs that loop
+          indefinitely.  Both types of programs have the
+          potential to cause damage if sent to unsuspecting
+          recipients.  Message-sending software should avoid the
+          construction and dissemination of such programs, which
+          is antisocial.  Message receiving and displaying
+          software should provide appropriate mechanisms to abort
+          processing after a reasonable amount of time has
+          elapsed. In addition, PostScript interpreters should be
+          limited to the consumption of only a reasonable amount
+          of any given system resource.
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 16]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+    (7)   It is possible to include raw binary information inside
+          PostScript in various forms.  This is not recommended
+          for use in Internet mail, both because it is not
+          supported by all PostScript interpreters and because it
+          significantly complicates the use of a MIME Content-
+          Transfer-Encoding.  (Without such binary, PostScript
+          may typically be viewed as line-oriented data.  The
+          treatment of CRLF sequences becomes extremely
+          problematic if binary and line-oriented data are mixed
+          in a single Postscript data stream.)
+
+    (8)   Finally, bugs may exist in some PostScript interpreters
+          which could possibly be exploited to gain unauthorized
+          access to a recipient's system.  Apart from noting this
+          possibility, there is no specific action to take to
+          prevent this, apart from the timely correction of such
+          bugs if any are found.
+
+4.5.3.  Other Application Subtypes
+
+   It is expected that many other subtypes of "application" will be
+   defined in the future.  MIME implementations must at a minimum treat
+   any unrecognized subtypes as being equivalent to "application/octet-
+   stream".
+
+5.  Composite Media Type Values
+
+   The remaining two of the seven initial Content-Type values refer to
+   composite entities.  Composite entities are handled using MIME
+   mechanisms -- a MIME processor typically handles the body directly.
+
+5.1.  Multipart Media Type
+
+   In the case of multipart entities, in which one or more different
+   sets of data are combined in a single body, a "multipart" media type
+   field must appear in the entity's header.  The body must then contain
+   one or more body parts, each preceded by a boundary delimiter line,
+   and the last one followed by a closing boundary delimiter line.
+   After its boundary delimiter line, each body part then consists of a
+   header area, a blank line, and a body area.  Thus a body part is
+   similar to an RFC 822 message in syntax, but different in meaning.
+
+   A body part is an entity and hence is NOT to be interpreted as
+   actually being an RFC 822 message.  To begin with, NO header fields
+   are actually required in body parts.  A body part that starts with a
+   blank line, therefore, is allowed and is a body part for which all
+   default values are to be assumed.  In such a case, the absence of a
+   Content-Type header usually indicates that the corresponding body has
+
+
+
+Freed & Borenstein          Standards Track                    [Page 17]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   a content-type of "text/plain; charset=US-ASCII".
+
+   The only header fields that have defined meaning for body parts are
+   those the names of which begin with "Content-".  All other header
+   fields may be ignored in body parts.  Although they should generally
+   be retained if at all possible, they may be discarded by gateways if
+   necessary.  Such other fields are permitted to appear in body parts
+   but must not be depended on.  "X-" fields may be created for
+   experimental or private purposes, with the recognition that the
+   information they contain may be lost at some gateways.
+
+   NOTE:  The distinction between an RFC 822 message and a body part is
+   subtle, but important.  A gateway between Internet and X.400 mail,
+   for example, must be able to tell the difference between a body part
+   that contains an image and a body part that contains an encapsulated
+   message, the body of which is a JPEG image.  In order to represent
+   the latter, the body part must have "Content-Type: message/rfc822",
+   and its body (after the blank line) must be the encapsulated message,
+   with its own "Content-Type: image/jpeg" header field.  The use of
+   similar syntax facilitates the conversion of messages to body parts,
+   and vice versa, but the distinction between the two must be
+   understood by implementors.  (For the special case in which parts
+   actually are messages, a "digest" subtype is also defined.)
+
+   As stated previously, each body part is preceded by a boundary
+   delimiter line that contains the boundary delimiter.  The boundary
+   delimiter MUST NOT appear inside any of the encapsulated parts, on a
+   line by itself or as the prefix of any line.  This implies that it is
+   crucial that the composing agent be able to choose and specify a
+   unique boundary parameter value that does not contain the boundary
+   parameter value of an enclosing multipart as a prefix.
+
+   All present and future subtypes of the "multipart" type must use an
+   identical syntax.  Subtypes may differ in their semantics, and may
+   impose additional restrictions on syntax, but must conform to the
+   required syntax for the "multipart" type.  This requirement ensures
+   that all conformant user agents will at least be able to recognize
+   and separate the parts of any multipart entity, even those of an
+   unrecognized subtype.
+
+   As stated in the definition of the Content-Transfer-Encoding field
+   [RFC 2045], no encoding other than "7bit", "8bit", or "binary" is
+   permitted for entities of type "multipart".  The "multipart" boundary
+   delimiters and header fields are always represented as 7bit US-ASCII
+   in any case (though the header fields may encode non-US-ASCII header
+   text as per RFC 2047) and data within the body parts can be encoded
+   on a part-by-part basis, with Content-Transfer-Encoding fields for
+   each appropriate body part.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 18]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+5.1.1.  Common Syntax
+
+   This section defines a common syntax for subtypes of "multipart".
+   All subtypes of "multipart" must use this syntax.  A simple example
+   of a multipart message also appears in this section.  An example of a
+   more complex multipart message is given in RFC 2049.
+
+   The Content-Type field for multipart entities requires one parameter,
+   "boundary". The boundary delimiter line is then defined as a line
+   consisting entirely of two hyphen characters ("-", decimal value 45)
+   followed by the boundary parameter value from the Content-Type header
+   field, optional linear whitespace, and a terminating CRLF.
+
+   NOTE:  The hyphens are for rough compatibility with the earlier RFC
+   934 method of message encapsulation, and for ease of searching for
+   the boundaries in some implementations.  However, it should be noted
+   that multipart messages are NOT completely compatible with RFC 934
+   encapsulations; in particular, they do not obey RFC 934 quoting
+   conventions for embedded lines that begin with hyphens.  This
+   mechanism was chosen over the RFC 934 mechanism because the latter
+   causes lines to grow with each level of quoting.  The combination of
+   this growth with the fact that SMTP implementations sometimes wrap
+   long lines made the RFC 934 mechanism unsuitable for use in the event
+   that deeply-nested multipart structuring is ever desired.
+
+   WARNING TO IMPLEMENTORS:  The grammar for parameters on the Content-
+   type field is such that it is often necessary to enclose the boundary
+   parameter values in quotes on the Content-type line.  This is not
+   always necessary, but never hurts. Implementors should be sure to
+   study the grammar carefully in order to avoid producing invalid
+   Content-type fields.  Thus, a typical "multipart" Content-Type header
+   field might look like this:
+
+     Content-Type: multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p
+
+   But the following is not valid:
+
+     Content-Type: multipart/mixed; boundary=gc0pJq0M:08jU534c0p
+
+   (because of the colon) and must instead be represented as
+
+     Content-Type: multipart/mixed; boundary="gc0pJq0M:08jU534c0p"
+
+   This Content-Type value indicates that the content consists of one or
+   more parts, each with a structure that is syntactically identical to
+   an RFC 822 message, except that the header area is allowed to be
+   completely empty, and that the parts are each preceded by the line
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 19]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+     --gc0pJq0M:08jU534c0p
+
+   The boundary delimiter MUST occur at the beginning of a line, i.e.,
+   following a CRLF, and the initial CRLF is considered to be attached
+   to the boundary delimiter line rather than part of the preceding
+   part.  The boundary may be followed by zero or more characters of
+   linear whitespace. It is then terminated by either another CRLF and
+   the header fields for the next part, or by two CRLFs, in which case
+   there are no header fields for the next part.  If no Content-Type
+   field is present it is assumed to be "message/rfc822" in a
+   "multipart/digest" and "text/plain" otherwise.
+
+   NOTE:  The CRLF preceding the boundary delimiter line is conceptually
+   attached to the boundary so that it is possible to have a part that
+   does not end with a CRLF (line  break).  Body parts that must be
+   considered to end with line breaks, therefore, must have two CRLFs
+   preceding the boundary delimiter line, the first of which is part of
+   the preceding body part, and the second of which is part of the
+   encapsulation boundary.
+
+   Boundary delimiters must not appear within the encapsulated material,
+   and must be no longer than 70 characters, not counting the two
+   leading hyphens.
+
+   The boundary delimiter line following the last body part is a
+   distinguished delimiter that indicates that no further body parts
+   will follow.  Such a delimiter line is identical to the previous
+   delimiter lines, with the addition of two more hyphens after the
+   boundary parameter value.
+
+     --gc0pJq0M:08jU534c0p--
+
+   NOTE TO IMPLEMENTORS:  Boundary string comparisons must compare the
+   boundary value with the beginning of each candidate line.  An exact
+   match of the entire candidate line is not required; it is sufficient
+   that the boundary appear in its entirety following the CRLF.
+
+   There appears to be room for additional information prior to the
+   first boundary delimiter line and following the final boundary
+   delimiter line.  These areas should generally be left blank, and
+   implementations must ignore anything that appears before the first
+   boundary delimiter line or after the last one.
+
+   NOTE:  These "preamble" and "epilogue" areas are generally not used
+   because of the lack of proper typing of these parts and the lack of
+   clear semantics for handling these areas at gateways, particularly
+   X.400 gateways.  However, rather than leaving the preamble area
+   blank, many MIME implementations have found this to be a convenient
+
+
+
+Freed & Borenstein          Standards Track                    [Page 20]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   place to insert an explanatory note for recipients who read the
+   message with pre-MIME software, since such notes will be ignored by
+   MIME-compliant software.
+
+   NOTE:  Because boundary delimiters must not appear in the body parts
+   being encapsulated, a user agent must exercise care to choose a
+   unique boundary parameter value.  The boundary parameter value in the
+   example above could have been the result of an algorithm designed to
+   produce boundary delimiters with a very low probability of already
+   existing in the data to be encapsulated without having to prescan the
+   data.  Alternate algorithms might result in more "readable" boundary
+   delimiters for a recipient with an old user agent, but would require
+   more attention to the possibility that the boundary delimiter might
+   appear at the beginning of some line in the encapsulated part.  The
+   simplest boundary delimiter line possible is something like "---",
+   with a closing boundary delimiter line of "-----".
+
+   As a very simple example, the following multipart message has two
+   parts, both of them plain text, one of them explicitly typed and one
+   of them implicitly typed:
+
+     From: Nathaniel Borenstein <nsb@bellcore.com>
+     To: Ned Freed <ned@innosoft.com>
+     Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)
+     Subject: Sample message
+     MIME-Version: 1.0
+     Content-type: multipart/mixed; boundary="simple boundary"
+
+     This is the preamble.  It is to be ignored, though it
+     is a handy place for composition agents to include an
+     explanatory note to non-MIME conformant readers.
+
+     --simple boundary
+
+     This is implicitly typed plain US-ASCII text.
+     It does NOT end with a linebreak.
+     --simple boundary
+     Content-type: text/plain; charset=us-ascii
+
+     This is explicitly typed plain US-ASCII text.
+     It DOES end with a linebreak.
+
+     --simple boundary--
+
+     This is the epilogue.  It is also to be ignored.
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 21]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   The use of a media type of "multipart" in a body part within another
+   "multipart" entity is explicitly allowed.  In such cases, for obvious
+   reasons, care must be taken to ensure that each nested "multipart"
+   entity uses a different boundary delimiter.  See RFC 2049 for an
+   example of nested "multipart" entities.
+
+   The use of the "multipart" media type with only a single body part
+   may be useful in certain contexts, and is explicitly permitted.
+
+   NOTE: Experience has shown that a "multipart" media type with a
+   single body part is useful for sending non-text media types.  It has
+   the advantage of providing the preamble as a place to include
+   decoding instructions.  In addition, a number of SMTP gateways move
+   or remove the MIME headers, and a clever MIME decoder can take a good
+   guess at multipart boundaries even in the absence of the Content-Type
+   header and thereby successfully decode the message.
+
+   The only mandatory global parameter for the "multipart" media type is
+   the boundary parameter, which consists of 1 to 70 characters from a
+   set of characters known to be very robust through mail gateways, and
+   NOT ending with white space. (If a boundary delimiter line appears to
+   end with white space, the white space must be presumed to have been
+   added by a gateway, and must be deleted.)  It is formally specified
+   by the following BNF:
+
+     boundary := 0*69<bchars> bcharsnospace
+
+     bchars := bcharsnospace / " "
+
+     bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
+                      "+" / "_" / "," / "-" / "." /
+                      "/" / ":" / "=" / "?"
+
+   Overall, the body of a "multipart" entity may be specified as
+   follows:
+
+     dash-boundary := "--" boundary
+                      ; boundary taken from the value of
+                      ; boundary parameter of the
+                      ; Content-Type field.
+
+     multipart-body := [preamble CRLF]
+                       dash-boundary transport-padding CRLF
+                       body-part *encapsulation
+                       close-delimiter transport-padding
+                       [CRLF epilogue]
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 22]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+     transport-padding := *LWSP-char
+                          ; Composers MUST NOT generate
+                          ; non-zero length transport
+                          ; padding, but receivers MUST
+                          ; be able to handle padding
+                          ; added by message transports.
+
+     encapsulation := delimiter transport-padding
+                      CRLF body-part
+
+     delimiter := CRLF dash-boundary
+
+     close-delimiter := delimiter "--"
+
+     preamble := discard-text
+
+     epilogue := discard-text
+
+     discard-text := *(*text CRLF) *text
+                     ; May be ignored or discarded.
+
+     body-part := MIME-part-headers [CRLF *OCTET]
+                  ; Lines in a body-part must not start
+                  ; with the specified dash-boundary and
+                  ; the delimiter must not appear anywhere
+                  ; in the body part.  Note that the
+                  ; semantics of a body-part differ from
+                  ; the semantics of a message, as
+                  ; described in the text.
+
+     OCTET := <any 0-255 octet value>
+
+   IMPORTANT:  The free insertion of linear-white-space and RFC 822
+   comments between the elements shown in this BNF is NOT allowed since
+   this BNF does not specify a structured header field.
+
+   NOTE:  In certain transport enclaves, RFC 822 restrictions such as
+   the one that limits bodies to printable US-ASCII characters may not
+   be in force. (That is, the transport domains may exist that resemble
+   standard Internet mail transport as specified in RFC 821 and assumed
+   by RFC 822, but without certain restrictions.) The relaxation of
+   these restrictions should be construed as locally extending the
+   definition of bodies, for example to include octets outside of the
+   US-ASCII range, as long as these extensions are supported by the
+   transport and adequately documented in the Content- Transfer-Encoding
+   header field.  However, in no event are headers (either message
+   headers or body part headers) allowed to contain anything other than
+   US-ASCII characters.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 23]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   NOTE:  Conspicuously missing from the "multipart" type is a notion of
+   structured, related body parts. It is recommended that those wishing
+   to provide more structured or integrated multipart messaging
+   facilities should define subtypes of multipart that are syntactically
+   identical but define relationships between the various parts. For
+   example, subtypes of multipart could be defined that include a
+   distinguished part which in turn is used to specify the relationships
+   between the other parts, probably referring to them by their
+   Content-ID field.  Old implementations will not recognize the new
+   subtype if this approach is used, but will treat it as
+   multipart/mixed and will thus be able to show the user the parts that
+   are recognized.
+
+5.1.2.  Handling Nested Messages and Multiparts
+
+   The "message/rfc822" subtype defined in a subsequent section of this
+   document has no terminating condition other than running out of data.
+   Similarly, an improperly truncated "multipart" entity may not have
+   any terminating boundary marker, and can turn up operationally due to
+   mail system malfunctions.
+
+   It is essential that such entities be handled correctly when they are
+   themselves imbedded inside of another "multipart" structure.  MIME
+   implementations are therefore required to recognize outer level
+   boundary markers at ANY level of inner nesting.  It is not sufficient
+   to only check for the next expected marker or other terminating
+   condition.
+
+5.1.3.  Mixed Subtype
+
+   The "mixed" subtype of "multipart" is intended for use when the body
+   parts are independent and need to be bundled in a particular order.
+   Any "multipart" subtypes that an implementation does not recognize
+   must be treated as being of subtype "mixed".
+
+5.1.4.  Alternative Subtype
+
+   The "multipart/alternative" type is syntactically identical to
+   "multipart/mixed", but the semantics are different.  In particular,
+   each of the body parts is an "alternative" version of the same
+   information.
+
+   Systems should recognize that the content of the various parts are
+   interchangeable.  Systems should choose the "best" type based on the
+   local environment and references, in some cases even through user
+   interaction.  As with "multipart/mixed", the order of body parts is
+   significant.  In this case, the alternatives appear in an order of
+   increasing faithfulness to the original content.  In general, the
+
+
+
+Freed & Borenstein          Standards Track                    [Page 24]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   best choice is the LAST part of a type supported by the recipient
+   system's local environment.
+
+   "Multipart/alternative" may be used, for example, to send a message
+   in a fancy text format in such a way that it can easily be displayed
+   anywhere:
+
+     From: Nathaniel Borenstein <nsb@bellcore.com>
+     To: Ned Freed <ned@innosoft.com>
+     Date: Mon, 22 Mar 1993 09:41:09 -0800 (PST)
+     Subject: Formatted text mail
+     MIME-Version: 1.0
+     Content-Type: multipart/alternative; boundary=boundary42
+
+     --boundary42
+     Content-Type: text/plain; charset=us-ascii
+
+       ... plain text version of message goes here ...
+
+     --boundary42
+     Content-Type: text/enriched
+
+       ... RFC 1896 text/enriched version of same message
+           goes here ...
+
+     --boundary42
+     Content-Type: application/x-whatever
+
+       ... fanciest version of same message goes here ...
+
+     --boundary42--
+
+   In this example, users whose mail systems understood the
+   "application/x-whatever" format would see only the fancy version,
+   while other users would see only the enriched or plain text version,
+   depending on the capabilities of their system.
+
+   In general, user agents that compose "multipart/alternative" entities
+   must place the body parts in increasing order of preference, that is,
+   with the preferred format last.  For fancy text, the sending user
+   agent should put the plainest format first and the richest format
+   last.  Receiving user agents should pick and display the last format
+   they are capable of displaying.  In the case where one of the
+   alternatives is itself of type "multipart" and contains unrecognized
+   sub-parts, the user agent may choose either to show that alternative,
+   an earlier alternative, or both.
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 25]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   NOTE: From an implementor's perspective, it might seem more sensible
+   to reverse this ordering, and have the plainest alternative last.
+   However, placing the plainest alternative first is the friendliest
+   possible option when "multipart/alternative" entities are viewed
+   using a non-MIME-conformant viewer.  While this approach does impose
+   some burden on conformant MIME viewers, interoperability with older
+   mail readers was deemed to be more important in this case.
+
+   It may be the case that some user agents, if they can recognize more
+   than one of the formats, will prefer to offer the user the choice of
+   which format to view.  This makes sense, for example, if a message
+   includes both a nicely- formatted image version and an easily-edited
+   text version.  What is most critical, however, is that the user not
+   automatically be shown multiple versions of the same data.  Either
+   the user should be shown the last recognized version or should be
+   given the choice.
+
+   THE SEMANTICS OF CONTENT-ID IN MULTIPART/ALTERNATIVE:  Each part of a
+   "multipart/alternative" entity represents the same data, but the
+   mappings between the two are not necessarily without information
+   loss.  For example, information is lost when translating ODA to
+   PostScript or plain text.  It is recommended that each part should
+   have a different Content-ID value in the case where the information
+   content of the two parts is not identical.  And when the information
+   content is identical -- for example, where several parts of type
+   "message/external-body" specify alternate ways to access the
+   identical data -- the same Content-ID field value should be used, to
+   optimize any caching mechanisms that might be present on the
+   recipient's end.  However, the Content-ID values used by the parts
+   should NOT be the same Content-ID value that describes the
+   "multipart/alternative" as a whole, if there is any such Content-ID
+   field.  That is, one Content-ID value will refer to the
+   "multipart/alternative" entity, while one or more other Content-ID
+   values will refer to the parts inside it.
+
+5.1.5.  Digest Subtype
+
+   This document defines a "digest" subtype of the "multipart" Content-
+   Type.  This type is syntactically identical to "multipart/mixed", but
+   the semantics are different.  In particular, in a digest, the default
+   Content-Type value for a body part is changed from "text/plain" to
+   "message/rfc822".  This is done to allow a more readable digest
+   format that is largely compatible (except for the quoting convention)
+   with RFC 934.
+
+   Note: Though it is possible to specify a Content-Type value for a
+   body part in a digest which is other than "message/rfc822", such as a
+   "text/plain" part containing a description of the material in the
+
+
+
+Freed & Borenstein          Standards Track                    [Page 26]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   digest, actually doing so is undesireble. The "multipart/digest"
+   Content-Type is intended to be used to send collections of messages.
+   If a "text/plain" part is needed, it should be included as a seperate
+   part of a "multipart/mixed" message.
+
+   A digest in this format might, then, look something like this:
+
+     From: Moderator-Address
+     To: Recipient-List
+     Date: Mon, 22 Mar 1994 13:34:51 +0000
+     Subject: Internet Digest, volume 42
+     MIME-Version: 1.0
+     Content-Type: multipart/mixed;
+                   boundary="---- main boundary ----"
+
+     ------ main boundary ----
+
+       ...Introductory text or table of contents...
+
+     ------ main boundary ----
+     Content-Type: multipart/digest;
+                   boundary="---- next message ----"
+
+     ------ next message ----
+
+     From: someone-else
+     Date: Fri, 26 Mar 1993 11:13:32 +0200
+     Subject: my opinion
+
+       ...body goes here ...
+
+     ------ next message ----
+
+     From: someone-else-again
+     Date: Fri, 26 Mar 1993 10:07:13 -0500
+     Subject: my different opinion
+
+       ... another body goes here ...
+
+     ------ next message ------
+
+     ------ main boundary ------
+
+5.1.6.  Parallel Subtype
+
+   This document defines a "parallel" subtype of the "multipart"
+   Content-Type.  This type is syntactically identical to
+   "multipart/mixed", but the semantics are different.  In particular,
+
+
+
+Freed & Borenstein          Standards Track                    [Page 27]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   in a parallel entity, the order of body parts is not significant.
+
+   A common presentation of this type is to display all of the parts
+   simultaneously on hardware and software that are capable of doing so.
+   However, composing agents should be aware that many mail readers will
+   lack this capability and will show the parts serially in any event.
+
+5.1.7.  Other Multipart Subtypes
+
+   Other "multipart" subtypes are expected in the future.  MIME
+   implementations must in general treat unrecognized subtypes of
+   "multipart" as being equivalent to "multipart/mixed".
+
+5.2.  Message Media Type
+
+   It is frequently desirable, in sending mail, to encapsulate another
+   mail message.  A special media type, "message", is defined to
+   facilitate this.  In particular, the "rfc822" subtype of "message" is
+   used to encapsulate RFC 822 messages.
+
+   NOTE:  It has been suggested that subtypes of "message" might be
+   defined for forwarded or rejected messages.  However, forwarded and
+   rejected messages can be handled as multipart messages in which the
+   first part contains any control or descriptive information, and a
+   second part, of type "message/rfc822", is the forwarded or rejected
+   message.  Composing rejection and forwarding messages in this manner
+   will preserve the type information on the original message and allow
+   it to be correctly presented to the recipient, and hence is strongly
+   encouraged.
+
+   Subtypes of "message" often impose restrictions on what encodings are
+   allowed.  These restrictions are described in conjunction with each
+   specific subtype.
+
+   Mail gateways, relays, and other mail handling agents are commonly
+   known to alter the top-level header of an RFC 822 message.  In
+   particular, they frequently add, remove, or reorder header fields.
+   These operations are explicitly forbidden for the encapsulated
+   headers embedded in the bodies of messages of type "message."
+
+5.2.1.  RFC822 Subtype
+
+   A media type of "message/rfc822" indicates that the body contains an
+   encapsulated message, with the syntax of an RFC 822 message.
+   However, unlike top-level RFC 822 messages, the restriction that each
+   "message/rfc822" body must include a "From", "Date", and at least one
+   destination header is removed and replaced with the requirement that
+   at least one of "From", "Subject", or "Date" must be present.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 28]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   It should be noted that, despite the use of the numbers "822", a
+   "message/rfc822" entity isn't restricted to material in strict
+   conformance to RFC822, nor are the semantics of "message/rfc822"
+   objects restricted to the semantics defined in RFC822. More
+   specifically, a "message/rfc822" message could well be a News article
+   or a MIME message.
+
+   No encoding other than "7bit", "8bit", or "binary" is permitted for
+   the body of a "message/rfc822" entity.  The message header fields are
+   always US-ASCII in any case, and data within the body can still be
+   encoded, in which case the Content-Transfer-Encoding header field in
+   the encapsulated message will reflect this.  Non-US-ASCII text in the
+   headers of an encapsulated message can be specified using the
+   mechanisms described in RFC 2047.
+
+5.2.2.  Partial Subtype
+
+   The "partial" subtype is defined to allow large entities to be
+   delivered as several separate pieces of mail and automatically
+   reassembled by a receiving user agent.  (The concept is similar to IP
+   fragmentation and reassembly in the basic Internet Protocols.)  This
+   mechanism can be used when intermediate transport agents limit the
+   size of individual messages that can be sent.  The media type
+   "message/partial" thus indicates that the body contains a fragment of
+   a larger entity.
+
+   Because data of type "message" may never be encoded in base64 or
+   quoted-printable, a problem might arise if "message/partial" entities
+   are constructed in an environment that supports binary or 8bit
+   transport.  The problem is that the binary data would be split into
+   multiple "message/partial" messages, each of them requiring binary
+   transport.  If such messages were encountered at a gateway into a
+   7bit transport environment, there would be no way to properly encode
+   them for the 7bit world, aside from waiting for all of the fragments,
+   reassembling the inner message, and then encoding the reassembled
+   data in base64 or quoted-printable.  Since it is possible that
+   different fragments might go through different gateways, even this is
+   not an acceptable solution.  For this reason, it is specified that
+   entities of type "message/partial" must always have a content-
+   transfer-encoding of 7bit (the default).  In particular, even in
+   environments that support binary or 8bit transport, the use of a
+   content- transfer-encoding of "8bit" or "binary" is explicitly
+   prohibited for MIME entities of type "message/partial". This in turn
+   implies that the inner message must not use "8bit" or "binary"
+   encoding.
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 29]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   Because some message transfer agents may choose to automatically
+   fragment large messages, and because such agents may use very
+   different fragmentation thresholds, it is possible that the pieces of
+   a partial message, upon reassembly, may prove themselves to comprise
+   a partial message.  This is explicitly permitted.
+
+   Three parameters must be specified in the Content-Type field of type
+   "message/partial":  The first, "id", is a unique identifier, as close
+   to a world-unique identifier as possible, to be used to match the
+   fragments together. (In general, the identifier is essentially a
+   message-id; if placed in double quotes, it can be ANY message-id, in
+   accordance with the BNF for "parameter" given in RFC 2045.)  The
+   second, "number", an integer, is the fragment number, which indicates
+   where this fragment fits into the sequence of fragments.  The third,
+   "total", another integer, is the total number of fragments.  This
+   third subfield is required on the final fragment, and is optional
+   (though encouraged) on the earlier fragments.  Note also that these
+   parameters may be given in any order.
+
+   Thus, the second piece of a 3-piece message may have either of the
+   following header fields:
+
+     Content-Type: Message/Partial; number=2; total=3;
+                   id="oc=jpbe0M2Yt4s@thumper.bellcore.com"
+
+     Content-Type: Message/Partial;
+                   id="oc=jpbe0M2Yt4s@thumper.bellcore.com";
+                   number=2
+
+   But the third piece MUST specify the total number of fragments:
+
+     Content-Type: Message/Partial; number=3; total=3;
+                   id="oc=jpbe0M2Yt4s@thumper.bellcore.com"
+
+   Note that fragment numbering begins with 1, not 0.
+
+   When the fragments of an entity broken up in this manner are put
+   together, the result is always a complete MIME entity, which may have
+   its own Content-Type header field, and thus may contain any other
+   data type.
+
+5.2.2.1.  Message Fragmentation and Reassembly
+
+   The semantics of a reassembled partial message must be those of the
+   "inner" message, rather than of a message containing the inner
+   message.  This makes it possible, for example, to send a large audio
+   message as several partial messages, and still have it appear to the
+   recipient as a simple audio message rather than as an encapsulated
+
+
+
+Freed & Borenstein          Standards Track                    [Page 30]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   message containing an audio message.  That is, the encapsulation of
+   the message is considered to be "transparent".
+
+   When generating and reassembling the pieces of a "message/partial"
+   message, the headers of the encapsulated message must be merged with
+   the headers of the enclosing entities.  In this process the following
+   rules must be observed:
+
+    (1)   Fragmentation agents must split messages at line
+          boundaries only. This restriction is imposed because
+          splits at points other than the ends of lines in turn
+          depends on message transports being able to preserve
+          the semantics of messages that don't end with a CRLF
+          sequence. Many transports are incapable of preserving
+          such semantics.
+
+    (2)   All of the header fields from the initial enclosing
+          message, except those that start with "Content-" and
+          the specific header fields "Subject", "Message-ID",
+          "Encrypted", and "MIME-Version", must be copied, in
+          order, to the new message.
+
+    (3)   The header fields in the enclosed message which start
+          with "Content-", plus the "Subject", "Message-ID",
+          "Encrypted", and "MIME-Version" fields, must be
+          appended, in order, to the header fields of the new
+          message.  Any header fields in the enclosed message
+          which do not start with "Content-" (except for the
+          "Subject", "Message-ID", "Encrypted", and "MIME-
+          Version" fields) will be ignored and dropped.
+
+    (4)   All of the header fields from the second and any
+          subsequent enclosing messages are discarded by the
+          reassembly process.
+
+5.2.2.2.  Fragmentation and Reassembly Example
+
+   If an audio message is broken into two pieces, the first piece might
+   look something like this:
+
+     X-Weird-Header-1: Foo
+     From: Bill@host.com
+     To: joe@otherhost.com
+     Date: Fri, 26 Mar 1993 12:59:38 -0500 (EST)
+     Subject: Audio mail (part 1 of 2)
+     Message-ID: <id1@host.com>
+     MIME-Version: 1.0
+     Content-type: message/partial; id="ABC@host.com";
+
+
+
+Freed & Borenstein          Standards Track                    [Page 31]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+                   number=1; total=2
+
+     X-Weird-Header-1: Bar
+     X-Weird-Header-2: Hello
+     Message-ID: <anotherid@foo.com>
+     Subject: Audio mail
+     MIME-Version: 1.0
+     Content-type: audio/basic
+     Content-transfer-encoding: base64
+
+       ... first half of encoded audio data goes here ...
+
+   and the second half might look something like this:
+
+     From: Bill@host.com
+     To: joe@otherhost.com
+     Date: Fri, 26 Mar 1993 12:59:38 -0500 (EST)
+     Subject: Audio mail (part 2 of 2)
+     MIME-Version: 1.0
+     Message-ID: <id2@host.com>
+     Content-type: message/partial;
+                   id="ABC@host.com"; number=2; total=2
+
+       ... second half of encoded audio data goes here ...
+
+   Then, when the fragmented message is reassembled, the resulting
+   message to be displayed to the user should look something like this:
+
+     X-Weird-Header-1: Foo
+     From: Bill@host.com
+     To: joe@otherhost.com
+     Date: Fri, 26 Mar 1993 12:59:38 -0500 (EST)
+     Subject: Audio mail
+     Message-ID: <anotherid@foo.com>
+     MIME-Version: 1.0
+     Content-type: audio/basic
+     Content-transfer-encoding: base64
+
+       ... first half of encoded audio data goes here ...
+       ... second half of encoded audio data goes here ...
+
+   The inclusion of a "References" field in the headers of the second
+   and subsequent pieces of a fragmented message that references the
+   Message-Id on the previous piece may be of benefit to mail readers
+   that understand and track references.  However, the generation of
+   such "References" fields is entirely optional.
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 32]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   Finally, it should be noted that the "Encrypted" header field has
+   been made obsolete by Privacy Enhanced Messaging (PEM) [RFC-1421,
+   RFC-1422, RFC-1423, RFC-1424], but the rules above are nevertheless
+   believed to describe the correct way to treat it if it is encountered
+   in the context of conversion to and from "message/partial" fragments.
+
+5.2.3.  External-Body Subtype
+
+   The external-body subtype indicates that the actual body data are not
+   included, but merely referenced.  In this case, the parameters
+   describe a mechanism for accessing the external data.
+
+   When a MIME entity is of type "message/external-body", it consists of
+   a header, two consecutive CRLFs, and the message header for the
+   encapsulated message.  If another pair of consecutive CRLFs appears,
+   this of course ends the message header for the encapsulated message.
+   However, since the encapsulated message's body is itself external, it
+   does NOT appear in the area that follows.  For example, consider the
+   following message:
+
+     Content-type: message/external-body;
+                   access-type=local-file;
+                   name="/u/nsb/Me.jpeg"
+
+     Content-type: image/jpeg
+     Content-ID: <id42@guppylake.bellcore.com>
+     Content-Transfer-Encoding: binary
+
+     THIS IS NOT REALLY THE BODY!
+
+   The area at the end, which might be called the "phantom body", is
+   ignored for most external-body messages.  However, it may be used to
+   contain auxiliary information for some such messages, as indeed it is
+   when the access-type is "mail- server".  The only access-type defined
+   in this document that uses the phantom body is "mail-server", but
+   other access-types may be defined in the future in other
+   specifications that use this area.
+
+   The encapsulated headers in ALL "message/external-body" entities MUST
+   include a Content-ID header field to give a unique identifier by
+   which to reference the data.  This identifier may be used for caching
+   mechanisms, and for recognizing the receipt of the data when the
+   access-type is "mail-server".
+
+   Note that, as specified here, the tokens that describe external-body
+   data, such as file names and mail server commands, are required to be
+   in the US-ASCII character set.
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 33]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   If this proves problematic in practice, a new mechanism may be
+   required as a future extension to MIME, either as newly defined
+   access-types for "message/external-body" or by some other mechanism.
+
+   As with "message/partial", MIME entities of type "message/external-
+   body" MUST have a content-transfer-encoding of 7bit (the default).
+   In particular, even in environments that support binary or 8bit
+   transport, the use of a content- transfer-encoding of "8bit" or
+   "binary" is explicitly prohibited for entities of type
+   "message/external-body".
+
+5.2.3.1.  General External-Body Parameters
+
+   The parameters that may be used with any "message/external- body"
+   are:
+
+    (1)   ACCESS-TYPE -- A word indicating the supported access
+          mechanism by which the file or data may be obtained.
+          This word is not case sensitive.  Values include, but
+          are not limited to, "FTP", "ANON-FTP", "TFTP", "LOCAL-
+          FILE", and "MAIL-SERVER".  Future values, except for
+          experimental values beginning with "X-", must be
+          registered with IANA, as described in RFC 2048.
+          This parameter is unconditionally mandatory and MUST be
+          present on EVERY "message/external-body".
+
+    (2)   EXPIRATION -- The date (in the RFC 822 "date-time"
+          syntax, as extended by RFC 1123 to permit 4 digits in
+          the year field) after which the existence of the
+          external data is not guaranteed.  This parameter may be
+          used with ANY access-type and is ALWAYS optional.
+
+    (3)   SIZE -- The size (in octets) of the data.  The intent
+          of this parameter is to help the recipient decide
+          whether or not to expend the necessary resources to
+          retrieve the external data.  Note that this describes
+          the size of the data in its canonical form, that is,
+          before any Content-Transfer-Encoding has been applied
+          or after the data have been decoded.  This parameter
+          may be used with ANY access-type and is ALWAYS
+          optional.
+
+    (4)   PERMISSION -- A case-insensitive field that indicates
+          whether or not it is expected that clients might also
+          attempt to overwrite the data.  By default, or if
+          permission is "read", the assumption is that they are
+          not, and that if the data is retrieved once, it is
+          never needed again.  If PERMISSION is "read-write",
+
+
+
+Freed & Borenstein          Standards Track                    [Page 34]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+          this assumption is invalid, and any local copy must be
+          considered no more than a cache.  "Read" and "Read-
+          write" are the only defined values of permission.  This
+          parameter may be used with ANY access-type and is
+          ALWAYS optional.
+
+   The precise semantics of the access-types defined here are described
+   in the sections that follow.
+
+5.2.3.2.  The 'ftp' and 'tftp' Access-Types
+
+   An access-type of FTP or TFTP indicates that the message body is
+   accessible as a file using the FTP [RFC-959] or TFTP [RFC- 783]
+   protocols, respectively.  For these access-types, the following
+   additional parameters are mandatory:
+
+    (1)   NAME -- The name of the file that contains the actual
+          body data.
+
+    (2)   SITE -- A machine from which the file may be obtained,
+          using the given protocol.  This must be a fully
+          qualified domain name, not a nickname.
+
+    (3)   Before any data are retrieved, using FTP, the user will
+          generally need to be asked to provide a login id and a
+          password for the machine named by the site parameter.
+          For security reasons, such an id and password are not
+          specified as content-type parameters, but must be
+          obtained from the user.
+
+   In addition, the following parameters are optional:
+
+    (1)   DIRECTORY -- A directory from which the data named by
+          NAME should be retrieved.
+
+    (2)   MODE -- A case-insensitive string indicating the mode
+          to be used when retrieving the information.  The valid
+          values for access-type "TFTP" are "NETASCII", "OCTET",
+          and "MAIL", as specified by the TFTP protocol [RFC-
+          783].  The valid values for access-type "FTP" are
+          "ASCII", "EBCDIC", "IMAGE", and "LOCALn" where "n" is a
+          decimal integer, typically 8.  These correspond to the
+          representation types "A" "E" "I" and "L n" as specified
+          by the FTP protocol [RFC-959].  Note that "BINARY" and
+          "TENEX" are not valid values for MODE and that "OCTET"
+          or "IMAGE" or "LOCAL8" should be used instead.  IF MODE
+          is not specified, the  default value is "NETASCII" for
+          TFTP and "ASCII" otherwise.
+
+
+
+Freed & Borenstein          Standards Track                    [Page 35]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+5.2.3.3.  The 'anon-ftp' Access-Type
+
+   The "anon-ftp" access-type is identical to the "ftp" access type,
+   except that the user need not be asked to provide a name and password
+   for the specified site.  Instead, the ftp protocol will be used with
+   login "anonymous" and a password that corresponds to the user's mail
+   address.
+
+5.2.3.4.  The 'local-file' Access-Type
+
+   An access-type of "local-file" indicates that the actual body is
+   accessible as a file on the local machine.  Two additional parameters
+   are defined for this access type:
+
+    (1)   NAME -- The name of the file that contains the actual
+          body data.  This parameter is mandatory for the
+          "local-file" access-type.
+
+    (2)   SITE -- A domain specifier for a machine or set of
+          machines that are known to have access to the data
+          file.  This optional parameter is used to describe the
+          locality of reference for the data, that is, the site
+          or sites at which the file is expected to be visible.
+          Asterisks may be used for wildcard matching to a part
+          of a domain name, such as "*.bellcore.com", to indicate
+          a set of machines on which the data should be directly
+          visible, while a single asterisk may be used to
+          indicate a file that is expected to be universally
+          available, e.g., via a global file system.
+
+5.2.3.5.  The 'mail-server' Access-Type
+
+   The "mail-server" access-type indicates that the actual body is
+   available from a mail server.  Two additional parameters are defined
+   for this access-type:
+
+    (1)   SERVER -- The addr-spec of the mail server from which
+          the actual body data can be obtained.  This parameter
+          is mandatory for the "mail-server" access-type.
+
+    (2)   SUBJECT -- The subject that is to be used in the mail
+          that is sent to obtain the data.  Note that keying mail
+          servers on Subject lines is NOT recommended, but such
+          mail servers are known to exist.  This is an optional
+          parameter.
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 36]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   Because mail servers accept a variety of syntaxes, some of which is
+   multiline, the full command to be sent to a mail server is not
+   included as a parameter in the content-type header field.  Instead,
+   it is provided as the "phantom body" when the media type is
+   "message/external-body" and the access-type is mail-server.
+
+   Note that MIME does not define a mail server syntax.  Rather, it
+   allows the inclusion of arbitrary mail server commands in the phantom
+   body.  Implementations must include the phantom body in the body of
+   the message it sends to the mail server address to retrieve the
+   relevant data.
+
+   Unlike other access-types, mail-server access is asynchronous and
+   will happen at an unpredictable time in the future.  For this reason,
+   it is important that there be a mechanism by which the returned data
+   can be matched up with the original "message/external-body" entity.
+   MIME mail servers must use the same Content-ID field on the returned
+   message that was used in the original "message/external-body"
+   entities, to facilitate such matching.
+
+5.2.3.6.  External-Body Security Issues
+
+   "Message/external-body" entities give rise to two important security
+   issues:
+
+    (1)   Accessing data via a "message/external-body" reference
+          effectively results in the message recipient performing
+          an operation that was specified by the message
+          originator.  It is therefore possible for the message
+          originator to trick a recipient into doing something
+          they would not have done otherwise.  For example, an
+          originator could specify a action that attempts
+          retrieval of material that the recipient is not
+          authorized to obtain, causing the recipient to
+          unwittingly violate some security policy.  For this
+          reason, user agents capable of resolving external
+          references must always take steps to describe the
+          action they are to take to the recipient and ask for
+          explicit permisssion prior to performing it.
+
+          The 'mail-server' access-type is particularly
+          vulnerable, in that it causes the recipient to send a
+          new message whose contents are specified by the
+          original message's originator.  Given the potential for
+          abuse, any such request messages that are constructed
+          should contain a clear indication that they were
+          generated automatically (e.g. in a Comments: header
+          field) in an attempt to resolve a MIME
+
+
+
+Freed & Borenstein          Standards Track                    [Page 37]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+          "message/external-body" reference.
+
+    (2)   MIME will sometimes be used in environments that
+          provide some guarantee of message integrity and
+          authenticity.  If present, such guarantees may apply
+          only to the actual direct content of messages -- they
+          may or may not apply to data accessed through MIME's
+          "message/external-body" mechanism.  In particular, it
+          may be possible to subvert certain access mechanisms
+          even when the messaging system itself is secure.
+
+          It should be noted that this problem exists either with
+          or without the availabilty of MIME mechanisms.  A
+          casual reference to an FTP site containing a document
+          in the text of a secure message brings up similar
+          issues -- the only difference is that MIME provides for
+          automatic retrieval of such material, and users may
+          place unwarranted trust is such automatic retrieval
+          mechanisms.
+
+5.2.3.7.  Examples and Further Explanations
+
+   When the external-body mechanism is used in conjunction with the
+   "multipart/alternative" media type it extends the functionality of
+   "multipart/alternative" to include the case where the same entity is
+   provided in the same format but via different accces mechanisms.
+   When this is done the originator of the message must order the parts
+   first in terms of preferred formats and then by preferred access
+   mechanisms.  The recipient's viewer should then evaluate the list
+   both in terms of format and access mechanisms.
+
+   With the emerging possibility of very wide-area file systems, it
+   becomes very hard to know in advance the set of machines where a file
+   will and will not be accessible directly from the file system.
+   Therefore it may make sense to provide both a file name, to be tried
+   directly, and the name of one or more sites from which the file is
+   known to be accessible.  An implementation can try to retrieve remote
+   files using FTP or any other protocol, using anonymous file retrieval
+   or prompting the user for the necessary name and password.  If an
+   external body is accessible via multiple mechanisms, the sender may
+   include multiple entities of type "message/external-body" within the
+   body parts of an enclosing "multipart/alternative" entity.
+
+   However, the external-body mechanism is not intended to be limited to
+   file retrieval, as shown by the mail-server access-type.  Beyond
+   this, one can imagine, for example, using a video server for external
+   references to video clips.
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 38]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   The embedded message header fields which appear in the body of the
+   "message/external-body" data must be used to declare the media type
+   of the external body if it is anything other than plain US-ASCII
+   text, since the external body does not have a header section to
+   declare its type.  Similarly, any Content-transfer-encoding other
+   than "7bit" must also be declared here.  Thus a complete
+   "message/external-body" message, referring to an object in PostScript
+   format, might look like this:
+
+     From: Whomever
+     To: Someone
+     Date: Whenever
+     Subject: whatever
+     MIME-Version: 1.0
+     Message-ID: <id1@host.com>
+     Content-Type: multipart/alternative; boundary=42
+     Content-ID: <id001@guppylake.bellcore.com>
+
+     --42
+     Content-Type: message/external-body; name="BodyFormats.ps";
+                   site="thumper.bellcore.com"; mode="image";
+                   access-type=ANON-FTP; directory="pub";
+                   expiration="Fri, 14 Jun 1991 19:13:14 -0400 (EDT)"
+
+     Content-type: application/postscript
+     Content-ID: <id42@guppylake.bellcore.com>
+
+     --42
+     Content-Type: message/external-body; access-type=local-file;
+                   name="/u/nsb/writing/rfcs/RFC-MIME.ps";
+                   site="thumper.bellcore.com";
+                   expiration="Fri, 14 Jun 1991 19:13:14 -0400 (EDT)"
+
+     Content-type: application/postscript
+     Content-ID: <id42@guppylake.bellcore.com>
+
+     --42
+     Content-Type: message/external-body;
+                   access-type=mail-server
+                   server="listserv@bogus.bitnet";
+                   expiration="Fri, 14 Jun 1991 19:13:14 -0400 (EDT)"
+
+     Content-type: application/postscript
+     Content-ID: <id42@guppylake.bellcore.com>
+
+     get RFC-MIME.DOC
+
+     --42--
+
+
+
+Freed & Borenstein          Standards Track                    [Page 39]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+   Note that in the above examples, the default Content-transfer-
+   encoding of "7bit" is assumed for the external postscript data.
+
+   Like the "message/partial" type, the "message/external-body" media
+   type is intended to be transparent, that is, to convey the data type
+   in the external body rather than to convey a message with a body of
+   that type.  Thus the headers on the outer and inner parts must be
+   merged using the same rules as for "message/partial".  In particular,
+   this means that the Content-type and Subject fields are overridden,
+   but the From field is preserved.
+
+   Note that since the external bodies are not transported along with
+   the external body reference, they need not conform to transport
+   limitations that apply to the reference itself. In particular,
+   Internet mail transports may impose 7bit and line length limits, but
+   these do not automatically apply to binary external body references.
+   Thus a Content-Transfer-Encoding is not generally necessary, though
+   it is permitted.
+
+   Note that the body of a message of type "message/external-body" is
+   governed by the basic syntax for an RFC 822 message.  In particular,
+   anything before the first consecutive pair of CRLFs is header
+   information, while anything after it is body information, which is
+   ignored for most access-types.
+
+5.2.4.  Other Message Subtypes
+
+   MIME implementations must in general treat unrecognized subtypes of
+   "message" as being equivalent to "application/octet-stream".
+
+   Future subtypes of "message" intended for use with email should be
+   restricted to "7bit" encoding. A type other than "message" should be
+   used if restriction to "7bit" is not possible.
+
+6.  Experimental Media Type Values
+
+   A media type value beginning with the characters "X-" is a private
+   value, to be used by consenting systems by mutual agreement.  Any
+   format without a rigorous and public definition must be named with an
+   "X-" prefix, and publicly specified values shall never begin with
+   "X-".  (Older versions of the widely used Andrew system use the "X-
+   BE2" name, so new systems should probably choose a different name.)
+
+   In general, the use of "X-" top-level types is strongly discouraged.
+   Implementors should invent subtypes of the existing types whenever
+   possible. In many cases, a subtype of "application" will be more
+   appropriate than a new top-level type.
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 40]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+7.  Summary
+
+   The five discrete media types provide provide a standardized
+   mechanism for tagging entities as "audio", "image", or several other
+   kinds of data. The composite "multipart" and "message" media types
+   allow mixing and hierarchical structuring of entities of different
+   types in a single message. A distinguished parameter syntax allows
+   further specification of data format details, particularly the
+   specification of alternate character sets.  Additional optional
+   header fields provide mechanisms for certain extensions deemed
+   desirable by many implementors. Finally, a number of useful media
+   types are defined for general use by consenting user agents, notably
+   "message/partial" and "message/external-body".
+
+9.  Security Considerations
+
+   Security issues are discussed in the context of the
+   "application/postscript" type, the "message/external-body" type, and
+   in RFC 2048.  Implementors should pay special attention to the
+   security implications of any media types that can cause the remote
+   execution of any actions in the recipient's environment.  In such
+   cases, the discussion of the "application/postscript" type may serve
+   as a model for considering other media types with remote execution
+   capabilities.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 41]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+9.  Authors' Addresses
+
+   For more information, the authors of this document are best contacted
+   via Internet mail:
+
+   Ned Freed
+   Innosoft International, Inc.
+   1050 East Garvey Avenue South
+   West Covina, CA 91790
+   USA
+
+   Phone: +1 818 919 3600
+   Fax:   +1 818 919 3614
+   EMail: ned@innosoft.com
+
+
+   Nathaniel S. Borenstein
+   First Virtual Holdings
+   25 Washington Avenue
+   Morristown, NJ 07960
+   USA
+
+   Phone: +1 201 540 8967
+   Fax:   +1 201 993 3032
+   EMail: nsb@nsb.fv.com
+
+
+   MIME is a result of the work of the Internet Engineering Task Force
+   Working Group on RFC 822 Extensions.  The chairman of that group,
+   Greg Vaudreuil, may be reached at:
+
+   Gregory M. Vaudreuil
+   Octel Network Services
+   17080 Dallas Parkway
+   Dallas, TX 75248-1905
+   USA
+
+   EMail: Greg.Vaudreuil@Octel.Com
+
+
+
+
+
+
+
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 42]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+Appendix A -- Collected Grammar
+
+   This appendix contains the complete BNF grammar for all the syntax
+   specified by this document.
+
+   By itself, however, this grammar is incomplete.  It refers by name to
+   several syntax rules that are defined by RFC 822.  Rather than
+   reproduce those definitions here, and risk unintentional differences
+   between the two, this document simply refers the reader to RFC 822
+   for the remaining definitions. Wherever a term is undefined, it
+   refers to the RFC 822 definition.
+
+     boundary := 0*69<bchars> bcharsnospace
+
+     bchars := bcharsnospace / " "
+
+     bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
+                      "+" / "_" / "," / "-" / "." /
+                      "/" / ":" / "=" / "?"
+
+     body-part := <"message" as defined in RFC 822, with all
+                   header fields optional, not starting with the
+                   specified dash-boundary, and with the
+                   delimiter not occurring anywhere in the
+                   body part.  Note that the semantics of a
+                   part differ from the semantics of a message,
+                   as described in the text.>
+
+     close-delimiter := delimiter "--"
+
+     dash-boundary := "--" boundary
+                      ; boundary taken from the value of
+                      ; boundary parameter of the
+                      ; Content-Type field.
+
+     delimiter := CRLF dash-boundary
+
+     discard-text := *(*text CRLF)
+                     ; May be ignored or discarded.
+
+     encapsulation := delimiter transport-padding
+                      CRLF body-part
+
+     epilogue := discard-text
+
+     multipart-body := [preamble CRLF]
+                       dash-boundary transport-padding CRLF
+                       body-part *encapsulation
+
+
+
+Freed & Borenstein          Standards Track                    [Page 43]
+\f
+RFC 2046                      Media Types                  November 1996
+
+
+                       close-delimiter transport-padding
+                       [CRLF epilogue]
+
+     preamble := discard-text
+
+     transport-padding := *LWSP-char
+                          ; Composers MUST NOT generate
+                          ; non-zero length transport
+                          ; padding, but receivers MUST
+                          ; be able to handle padding
+                          ; added by message transports.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Freed & Borenstein          Standards Track                    [Page 44]
+\f
diff --git a/standards/rfc3282.txt b/standards/rfc3282.txt
new file mode 100644 (file)
index 0000000..bf5b868
--- /dev/null
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group                                      H. Alvestrand
+Request for Comments: 3282                                 Cisco Systems
+Obsoletes: 1766                                                 May 2002
+Category: Standards Track
+
+
+                       Content Language Headers
+
+Status of this Memo
+
+   This document specifies an Internet standards track protocol for the
+   Internet community, and requests discussion and suggestions for
+   improvements.  Please refer to the current edition of the "Internet
+   Official Protocol Standards" (STD 1) for the standardization state
+   and status of this protocol.  Distribution of this memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2002).  All Rights Reserved.
+
+Abstract
+
+   This document defines a "Content-language:" header, for use in cases
+   where one desires to indicate the language of something that has RFC
+   822-like headers, like MIME body parts or Web documents, and an
+   "Accept-Language:" header for use in cases where one wishes to
+   indicate one's preferences with regard to language.
+
+1. Introduction
+
+   There are a number of languages presently or previously used by human
+   beings in this world.
+
+   A great number of these people would prefer to have information
+   presented in a language which they understand.
+
+   In some contexts, it is possible to have information available in
+   more than one language, or it might be possible to provide tools
+   (such as dictionaries) to assist in the understanding of a language.
+
+   In other cases, it may be desirable to use a computer program to
+   convert information from one format (such as plaintext) into another
+   (such as computer-synthesized speech, or Braille, or high-quality
+   print renderings).
+
+
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 1]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+   A prerequisite for any such function is a means of labelling the
+   information content with an identifier for the language that is used
+   in this information content, such as is defined by [TAGS].  This
+   document specifies a protocol element for use with protocols that use
+   RFC 822-like headers for carrying language tags as defined in [TAGS].
+
+   The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+   document are to be interpreted as described in [RFC 2119].
+
+2. The Content-language header
+
+   The "Content-Language" header is intended for use in the case where
+   one desires to indicate the language(s) of something that has RFC
+   822-like headers, such as MIME body parts or Web documents.
+
+   The RFC 822 EBNF of the Content-Language header is:
+
+      Content-Language = "Content-Language" ":" 1#Language-tag
+
+   In the more strict RFC 2234 ABNF:
+
+      Content-Language = "Content-Language" ":" [CFWS] Language-List
+      Language-List = Language-Tag [CFWS]
+                         *("," [CFWS] Language-Tag [CFWS])
+
+   The Content-Language header may list several languages in a comma-
+   separated list.
+
+   The CFWS construct is intended to function like the whitespace
+   convention in RFC 822, which means also that one can place
+   parenthesized comments anywhere in the language sequence, or use
+   continuation lines.  A formal definition is given in RFC 2822
+   [RFC2822].
+
+   In keeping with the tradition of RFC 2822, a more liberal "obsolete"
+   grammar is also given:
+
+      obs-content-language = "Content-Language" *WSP ":"
+                              [CFWS] Language-List
+
+   Like RFC 2822, this specification says that conforming
+   implementations MUST accept the obs-content-language syntax, but MUST
+   NOT generate it; all generated headers MUST conform to the Content-
+   Language syntax.
+
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 2]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+2.1 Examples of Content-language values
+
+   Voice recording from Liverpool downtown
+
+      Content-type: audio/basic
+      Content-Language: en-scouse
+
+   Document in Mingo, an American Indian language which does not have an
+   ISO 639 code:
+
+      Content-type: text/plain
+      Content-Language: i-mingo
+
+   A English-French dictionary
+
+      Content-type: application/dictionary
+      Content-Language: en, fr (This is a dictionary)
+
+   An official European Commission document (in a few of its official
+   languages):
+
+      Content-type: multipart/alternative
+      Content-Language: da, de, el, en, fr, it
+
+   An excerpt from Star Trek
+
+      Content-type: video/mpeg
+      Content-Language: i-klingon
+
+3. The Accept-Language header
+
+   The "Accept-Language" header is intended for use in cases where a
+   user or a process desires to identify the preferred language(s) when
+   RFC 822-like headers, such as MIME body parts or Web documents, are
+   used.
+
+   The RFC 822 EBNF of the Accept-Language header is:
+
+      Accept-Language = "Accept-Language" ":"
+                             1#( language-range [ ";" "q" "=" qvalue ] )
+
+   A slightly more restrictive RFC 2234 ABNF definition is:
+
+      Accept-Language = "Accept-Language:" [CFWS] language-q
+                        *( "," [CFWS] language-q )
+      language-q = language-range [";" [CFWS] "q=" qvalue ] [CFWS]
+      qvalue         = ( "0" [ "." 0*3DIGIT ] )
+                     / ( "1" [ "." 0*3("0") ] )
+
+
+
+Alvestrand                  Standards Track                     [Page 3]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+
+   A more liberal RFC 2234 ABNF definition is:
+
+      Obs-accept-language = "Accept-Language" *WSP ":" [CFWS]
+           obs-language-q *( "," [CFWS] obs-language-q ) [CFWS]
+      obs-language-q = language-range
+            [ [CFWS] ";" [CFWS] "q" [CFWS] "=" qvalue ]
+
+   Like RFC 2822, this specification says that conforming
+   implementations MUST accept the obs-accept-language syntax, but MUST
+   NOT generate it; all generated messages MUST conform to the Accept-
+   Language syntax.
+
+   The syntax and semantics of language-range is defined in [TAGS].  The
+   Accept-Language header may list several language-ranges in a comma-
+   separated list, and each may include a quality value Q.  If no Q
+   values are given, the language-ranges are given in priority order,
+   with the leftmost language-range being the most preferred language;
+   this is an extension to the HTTP/1.1 rules, but matches current
+   practice.
+
+   If Q values are given, refer to HTTP/1.1 [RFC 2616] for the details
+   on how to evaluate it.
+
+4. Security Considerations
+
+   The only security issue that has been raised with language tags since
+   the publication of RFC 1766, which stated that "Security issues are
+   believed to be irrelevant to this memo", is a concern with language
+   ranges used in content negotiation - that they may be used to infer
+   the nationality of the sender, and thus identify potential targets
+   for surveillance.
+
+   This is a special case of the general problem that anything you send
+   is visible to the receiving party; it is useful to be aware that such
+   concerns can exist in some cases.
+
+   The exact magnitude of the threat, and any possible countermeasures,
+   is left to each application protocol.
+
+5. Character set considerations
+
+   This document adds no new considerations beyond what is mentioned in
+   [TAGS].
+
+
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 4]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+6. Acknowledgements
+
+   This document has benefited from many rounds of review and comments
+   in various fora of the IETF and the Internet working groups.
+
+   Any list of contributors is bound to be incomplete; please regard the
+   following as only a selection from the group of people who have
+   contributed to make this document what it is today.
+
+   In alphabetical order:
+
+   Tim Berners-Lee, Nathaniel Borenstein, Sean M. Burke, John Clews, Jim
+   Conklin, John Cowan, Dave Crocker, Martin Duerst, Michael Everson,
+   Ned Freed, Tim Goodwin, Dirk-Willem van Gulik, Marion Gunn, Paul
+   Hoffman, Olle Jarnefors, John Klensin, Bruce Lilly, Keith Moore,
+   Chris Newman, Masataka Ohta, Keld Jorn Simonsen, Rhys Weatherley,
+   Misha Wolf, Francois Yergeau and many, many others.
+
+   Special thanks must go to Michael Everson, who has served as language
+   tag reviewer for almost the entire period, since the publication of
+   RFC 1766, and has provided a great deal of input to this revision.
+   Bruce Lilly did a special job of reading and commenting on my ABNF
+   definitions.
+
+7. References
+
+   [TAGS]      Alvestrand, H., "Tags for the Identification of
+               Languages", BCP 47, RFC 3066
+
+   [ISO 639]   ISO 639:1988 (E/F) - Code for the representation of names
+               of languages - The International Organization for
+               Standardization, 1st edition, 1988-04-01 Prepared by
+               ISO/TC 37 - Terminology (principles and coordination).
+               Note that a new version (ISO 639-1:2000) is in
+               preparation at the time of this writing.
+
+   [ISO 639-2] ISO 639-2:1998 - Codes for the representation of names of
+               languages -- Part 2: Alpha-3 code  - edition 1, 1998-11-
+               01, 66 pages, prepared by ISO/TC 37/SC 2
+
+   [ISO 3166]  ISO 3166:1988 (E/F) - Codes for the representation of
+               names of countries - The International Organization for
+               Standardization, 3rd edition, 1988-08-15.
+
+   [ISO 15924] ISO/DIS 15924 - Codes for the representation of names of
+               scripts (under development by ISO TC46/SC2)
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 5]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+   [RFC 2045]  Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+               Extensions (MIME) Part One: Format of Internet Message
+               Bodies", RFC 2045, November 1996.
+
+   [RFC 2046]  Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+               Extensions (MIME) Part Two: Media Types", RFC 2046,
+               November 1996.
+
+   [RFC 2047]  Moore, K., "MIME (Multipurpose Internet Mail Extensions)
+               Part Three: Message Header Extensions for Non-ASCII
+               Text", RFC 2047, November 1996.
+
+   [RFC 2048]  Freed, N., Klensin, J. and J. Postel, "Multipurpose
+               Internet Mail Extensions (MIME) Part Four: Registration
+               Procedures", RFC 2048, November 1996.
+
+   [RFC 2049]  Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+               Extensions (MIME) Part Five: Conformance Criteria and
+               Examples", RFC 2049, November 1996.
+
+   [RFC 2119]  Bradner, S., "Key words for use in RFCs to Indicate
+               Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [RFC 2234]  Crocker, D. and P. Overell, "Augmented BNF for Syntax
+               Specifications: ABNF", RFC 2234, November 1997.
+
+   [RFC 2616]  Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
+               Masinter, L., Leach, P. and T. Berners-Lee, "Hypertext
+               Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
+
+   [RFC 2822]  Resnick, P., "Internet Message Format", RFC 2822, April
+               2001.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 6]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+Appendix A: Changes from RFC 1766
+
+   The definition of the language tags has been split, and is now RFC
+   3066.  The differences parameter to multipart/alternative is no
+   longer part of this standard, because no implementations of the
+   function were ever found.  Consult RFC 1766 if you need the
+   information.
+
+   The ABNF for content-language has been updated to use the RFC 2234
+   ABNF.
+
+Author's Address
+
+   Harald Tveit Alvestrand
+   Cisco Systems
+   Weidemanns vei 27
+   7043 Trondheim
+   NORWAY
+
+   EMail: Harald@Alvestrand.no
+   Phone: +47 73 50 33 52
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 7]
+\f
+RFC 3282                Content Language Headers                May 2002
+
+
+Full Copyright Statement
+
+   Copyright (C) The Internet Society (2002).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alvestrand                  Standards Track                     [Page 8]
+\f
diff --git a/standards/rfc4646.txt b/standards/rfc4646.txt
new file mode 100644 (file)
index 0000000..466d547
--- /dev/null
@@ -0,0 +1,3307 @@
+
+
+
+
+
+
+Network Working Group                                   A. Phillips, Ed.
+Request for Comments: 4646                                   Yahoo! Inc.
+BCP: 47                                                    M. Davis, Ed.
+Obsoletes: 3066                                                   Google
+Category: Best Current Practice                           September 2006
+
+
+                     Tags for Identifying Languages
+
+Status of This Memo
+
+   This document specifies an Internet Best Current Practices for the
+   Internet Community, and requests discussion and suggestions for
+   improvements.  Distribution of this memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2005).
+
+Abstract
+
+   This document describes the structure, content, construction, and
+   semantics of language tags for use in cases where it is desirable to
+   indicate the language used in an information object.  It also
+   describes how to register values for use in language tags and the
+   creation of user-defined extensions for private interchange.  This
+   document, in combination with RFC 4647, replaces RFC 3066, which
+   replaced RFC 1766.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 1]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+Table of Contents
+
+   1. Introduction ....................................................3
+   2. The Language Tag ................................................4
+      2.1. Syntax .....................................................4
+      2.2. Language Subtag Sources and Interpretation .................7
+           2.2.1. Primary Language Subtag .............................8
+           2.2.2. Extended Language Subtags ..........................10
+           2.2.3. Script Subtag ......................................11
+           2.2.4. Region Subtag ......................................11
+           2.2.5. Variant Subtags ....................................13
+           2.2.6. Extension Subtags ..................................14
+           2.2.7. Private Use Subtags ................................16
+           2.2.8. Preexisting RFC 3066 Registrations .................16
+           2.2.9. Classes of Conformance .............................17
+   3. Registry Format and Maintenance ................................18
+      3.1. Format of the IANA Language Subtag Registry ...............18
+      3.2. Language Subtag Reviewer ..................................24
+      3.3. Maintenance of the Registry ...............................24
+      3.4. Stability of IANA Registry Entries ........................25
+      3.5. Registration Procedure for Subtags ........................29
+      3.6. Possibilities for Registration ............................32
+      3.7. Extensions and Extensions Registry ........................34
+      3.8. Initialization of the Registries ..........................37
+   4. Formation and Processing of Language Tags ......................38
+      4.1. Choice of Language Tag ....................................38
+      4.2. Meaning of the Language Tag ...............................40
+      4.3. Length Considerations .....................................41
+           4.3.1. Working with Limited Buffer Sizes ..................42
+           4.3.2. Truncation of Language Tags ........................43
+      4.4. Canonicalization of Language Tags .........................44
+      4.5. Considerations for Private Use Subtags ....................45
+   5. IANA Considerations ............................................46
+      5.1. Language Subtag Registry ..................................46
+      5.2. Extensions Registry .......................................47
+   6. Security Considerations ........................................48
+   7. Character Set Considerations ...................................48
+   8. Changes from RFC 3066 ..........................................49
+   9. References .....................................................52
+      9.1. Normative References ......................................52
+      9.2. Informative References ....................................53
+   Appendix A. Acknowledgements ......................................55
+   Appendix B. Examples of Language Tags (Informative) ...............56
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 2]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+1.  Introduction
+
+   Human beings on our planet have, past and present, used a number of
+   languages.  There are many reasons why one would want to identify the
+   language used when presenting or requesting information.
+
+   A user's language preferences often need to be identified so that
+   appropriate processing can be applied.  For example, the user's
+   language preferences in a Web browser can be used to select Web pages
+   appropriately.  Language preferences can also be used to select among
+   tools (such as dictionaries) to assist in the processing or
+   understanding of content in different languages.
+
+   In addition, knowledge about the particular language used by some
+   piece of information content might be useful or even required by some
+   types of processing; for example, spell-checking, computer-
+   synthesized speech, Braille transcription, or high-quality print
+   renderings.
+
+   One means of indicating the language used is by labeling the
+   information content with an identifier or "tag".  These tags can be
+   used to specify user preferences when selecting information content,
+   or for labeling additional attributes of content and associated
+   resources.
+
+   Tags can also be used to indicate additional language attributes of
+   content.  For example, indicating specific information about the
+   dialect, writing system, or orthography used in a document or
+   resource may enable the user to obtain information in a form that
+   they can understand, or it can be important in processing or
+   rendering the given content into an appropriate form or style.
+
+   This document specifies a particular identifier mechanism (the
+   language tag) and a registration function for values to be used to
+   form tags.  It also defines a mechanism for private use values and
+   future extension.
+
+   This document, in combination with [RFC4647], replaces [RFC3066],
+   which replaced [RFC1766].  For a list of changes in this document,
+   see Section 8.
+
+   The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+   document are to be interpreted as described in [RFC2119].
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 3]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+2.  The Language Tag
+
+   Language tags are used to help identify languages, whether spoken,
+   written, signed, or otherwise signaled, for the purpose of
+   communication.  This includes constructed and artificial languages,
+   but excludes languages not intended primarily for human
+   communication, such as programming languages.
+
+2.1.  Syntax
+
+   The language tag is composed of one or more parts, known as
+   "subtags".  Each subtag consists of a sequence of alphanumeric
+   characters.  Subtags are distinguished and separated from one another
+   by a hyphen ("-", ABNF [RFC4234] %x2D).  A language tag consists of a
+   "primary language" subtag and a (possibly empty) series of subsequent
+   subtags, each of which refines or narrows the range of languages
+   identified by the overall tag.
+
+   Usually, each type of subtag is distinguished by length, position in
+   the tag, and content: subtags can be recognized solely by these
+   features.  The only exception to this is a fixed list of
+   grandfathered tags registered under RFC 3066 [RFC3066].  This makes
+   it possible to construct a parser that can extract and assign some
+   semantic information to the subtags, even if the specific subtag
+   values are not recognized.  Thus, a parser need not have an up-to-
+   date copy (or any copy at all) of the subtag registry to perform most
+   searching and matching operations.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 4]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The syntax of the language tag in ABNF [RFC4234] is:
+
+   Language-Tag  = langtag
+                 / privateuse             ; private use tag
+                 / grandfathered          ; grandfathered registrations
+
+   langtag       = (language
+                    ["-" script]
+                    ["-" region]
+                    *("-" variant)
+                    *("-" extension)
+                    ["-" privateuse])
+
+   language      = (2*3ALPHA [ extlang ]) ; shortest ISO 639 code
+                 / 4ALPHA                 ; reserved for future use
+                 / 5*8ALPHA               ; registered language subtag
+
+   extlang       = *3("-" 3ALPHA)         ; reserved for future use
+
+   script        = 4ALPHA                 ; ISO 15924 code
+
+   region        = 2ALPHA                 ; ISO 3166 code
+                 / 3DIGIT                 ; UN M.49 code
+
+   variant       = 5*8alphanum            ; registered variants
+                 / (DIGIT 3alphanum)
+
+   extension     = singleton 1*("-" (2*8alphanum))
+
+   singleton     = %x41-57 / %x59-5A / %x61-77 / %x79-7A / DIGIT
+                 ; "a"-"w" / "y"-"z" / "A"-"W" / "Y"-"Z" / "0"-"9"
+                 ; Single letters: x/X is reserved for private use
+
+   privateuse    = ("x"/"X") 1*("-" (1*8alphanum))
+
+   grandfathered = 1*3ALPHA 1*2("-" (2*8alphanum))
+                   ; grandfathered registration
+                   ; Note: i is the only singleton
+                   ; that starts a grandfathered tag
+
+   alphanum      = (ALPHA / DIGIT)       ; letters and numbers
+
+                        Figure 1: Language Tag ABNF
+
+   Note: There is a subtlety in the ABNF for 'variant': variants
+   starting with a digit MAY be four characters long, while those
+   starting with a letter MUST be at least five characters long.
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 5]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   All subtags have a maximum length of eight characters and whitespace
+   is not permitted in a language tag.  For examples of language tags,
+   see Appendix B.
+
+   Note that although [RFC4234] refers to octets, the language tags
+   described in this document are sequences of characters from the
+   US-ASCII [ISO646] repertoire.  Language tags MAY be used in documents
+   and applications that use other encodings, so long as these encompass
+   the US-ASCII repertoire.  An example of this would be an XML document
+   that uses the UTF-16LE [RFC2781] encoding of [Unicode].
+
+   The tags and their subtags, including private use and extensions, are
+   to be treated as case insensitive: there exist conventions for the
+   capitalization of some of the subtags, but these MUST NOT be taken to
+   carry meaning.
+
+   For example:
+
+   o  [ISO639-1] recommends that language codes be written in lowercase
+      ('mn' Mongolian).
+
+   o  [ISO3166-1] recommends that country codes be capitalized ('MN'
+      Mongolia).
+
+   o  [ISO15924] recommends that script codes use lowercase with the
+      initial letter capitalized ('Cyrl' Cyrillic).
+
+   However, in the tags defined by this document, the uppercase US-ASCII
+   letters in the range 'A' through 'Z' are considered equivalent and
+   mapped directly to their US-ASCII lowercase equivalents in the range
+   'a' through 'z'.  Thus, the tag "mn-Cyrl-MN" is not distinct from
+   "MN-cYRL-mn" or "mN-cYrL-Mn" (or any other combination), and each of
+   these variations conveys the same meaning: Mongolian written in the
+   Cyrillic script as used in Mongolia.
+
+   Although case distinctions do not carry meaning in language tags,
+   consistent formatting and presentation of the tags will aid users.
+   The format of the tags and subtags in the registry is RECOMMENDED.
+   In this format, all non-initial two-letter subtags are uppercase, all
+   non-initial four-letter subtags are titlecase, and all other subtags
+   are lowercase.
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 6]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+2.2.  Language Subtag Sources and Interpretation
+
+   The namespace of language tags and their subtags is administered by
+   the Internet Assigned Numbers Authority (IANA) [RFC2860] according to
+   the rules in Section 5 of this document.  The Language Subtag
+   Registry maintained by IANA is the source for valid subtags: other
+   standards referenced in this section provide the source material for
+   that registry.
+
+   Terminology in this section:
+
+   o  Tag or tags refers to a complete language tag, such as
+      "fr-Latn-CA".  Examples of tags in this document are enclosed in
+      double-quotes ("en-US").
+
+   o  Subtag refers to a specific section of a tag, delimited by hyphen,
+      such as the subtag 'Latn' in "fr-Latn-CA".  Examples of subtags in
+      this document are enclosed in single quotes ('Latn').
+
+   o  Code or codes refers to values defined in external standards (and
+      that are used as subtags in this document).  For example, 'Latn'
+      is an [ISO15924] script code that was used to define the 'Latn'
+      script subtag for use in a language tag.  Examples of codes in
+      this document are enclosed in single quotes ('en', 'Latn').
+
+   The definitions in this section apply to the various subtags within
+   the language tags defined by this document, excepting those
+   "grandfathered" tags defined in Section 2.2.8.
+
+   Language tags are designed so that each subtag type has unique length
+   and content restrictions.  These make identification of the subtag's
+   type possible, even if the content of the subtag itself is
+   unrecognized.  This allows tags to be parsed and processed without
+   reference to the latest version of the underlying standards or the
+   IANA registry and makes the associated exception handling when
+   parsing tags simpler.
+
+   Subtags in the IANA registry that do not come from an underlying
+   standard can only appear in specific positions in a tag.
+   Specifically, they can only occur as primary language subtags or as
+   variant subtags.
+
+   Note that sequences of private use and extension subtags MUST occur
+   at the end of the sequence of subtags and MUST NOT be interspersed
+   with subtags defined elsewhere in this document.
+
+   Single-letter and single-digit subtags are reserved for current or
+   future use.  These include the following current uses:
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 7]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   o  The single-letter subtag 'x' is reserved to introduce a sequence
+      of private use subtags.  The interpretation of any private use
+      subtags is defined solely by private agreement and is not defined
+      by the rules in this section or in any standard or registry
+      defined in this document.
+
+   o  All other single-letter subtags are reserved to introduce
+      standardized extension subtag sequences as described in
+      Section 3.7.
+
+   The single-letter subtag 'i' is used by some grandfathered tags, such
+   as "i-enochian", where it always appears in the first position and
+   cannot be confused with an extension.
+
+2.2.1.  Primary Language Subtag
+
+   The primary language subtag is the first subtag in a language tag
+   (with the exception of private use and certain grandfathered tags)
+   and cannot be omitted.  The following rules apply to the primary
+   language subtag:
+
+   1.  All two-character language subtags were defined in the IANA
+       registry according to the assignments found in the standard ISO
+       639 Part 1, "ISO 639-1:2002, Codes for the representation of
+       names of languages -- Part 1: Alpha-2 code" [ISO639-1], or using
+       assignments subsequently made by the ISO 639 Part 1 maintenance
+       agency or governing standardization bodies.
+
+   2.  All three-character language subtags were defined in the IANA
+       registry according to the assignments found in ISO 639 Part 2,
+       "ISO 639-2:1998 - Codes for the representation of names of
+       languages -- Part 2: Alpha-3 code - edition 1" [ISO639-2], or
+       assignments subsequently made by the ISO 639 Part 2 maintenance
+       agency or governing standardization bodies.
+
+   3.  The subtags in the range 'qaa' through 'qtz' are reserved for
+       private use in language tags.  These subtags correspond to codes
+       reserved by ISO 639-2 for private use.  These codes MAY be used
+       for non-registered primary language subtags (instead of using
+       private use subtags following 'x-').  Please refer to Section 4.5
+       for more information on private use subtags.
+
+   4.  All four-character language subtags are reserved for possible
+       future standardization.
+
+   5.  All language subtags of 5 to 8 characters in length in the IANA
+       registry were defined via the registration process in Section 3.5
+       and MAY be used to form the primary language subtag.  At the time
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 8]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+       this document was created, there were no examples of this kind of
+       subtag and future registrations of this type will be discouraged:
+       primary languages are strongly RECOMMENDED for registration with
+       ISO 639, and proposals rejected by ISO 639/RA will be closely
+       scrutinized before they are registered with IANA.
+
+   6.  The single-character subtag 'x' as the primary subtag indicates
+       that the language tag consists solely of subtags whose meaning is
+       defined by private agreement.  For example, in the tag "x-fr-CH",
+       the subtags 'fr' and 'CH' SHOULD NOT be taken to represent the
+       French language or the country of Switzerland (or any other value
+       in the IANA registry) unless there is a private agreement in
+       place to do so.  See Section 4.5.
+
+   7.  The single-character subtag 'i' is used by some grandfathered
+       tags (see Section 2.2.8) such as "i-klingon" and "i-bnn".  (Other
+       grandfathered tags have a primary language subtag in their first
+       position.)
+
+   8.  Other values MUST NOT be assigned to the primary subtag except by
+       revision or update of this document.
+
+   Note: For languages that have both an ISO 639-1 two-character code
+   and an ISO 639-2 three-character code, only the ISO 639-1 two-
+   character code is defined in the IANA registry.
+
+   Note: For languages that have no ISO 639-1 two-character code and for
+   which the ISO 639-2/T (Terminology) code and the ISO 639-2/B
+   (Bibliographic) codes differ, only the Terminology code is defined in
+   the IANA registry.  At the time this document was created, all
+   languages that had both kinds of three-character code were also
+   assigned a two-character code; it is not expected that future
+   assignments of this nature will occur.
+
+   Note: To avoid problems with versioning and subtag choice as
+   experienced during the transition between RFC 1766 and RFC 3066, as
+   well as the canonical nature of subtags defined by this document, the
+   ISO 639 Registration Authority Joint Advisory Committee (ISO 639/
+   RA-JAC) has included the following statement in [iso639.prin]:
+
+   "A language code already in ISO 639-2 at the point of freezing ISO
+   639-1 shall not later be added to ISO 639-1.  This is to ensure
+   consistency in usage over time, since users are directed in Internet
+   applications to employ the alpha-3 code when an alpha-2 code for that
+   language is not available."
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                  [Page 9]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   In order to avoid instability in the canonical form of tags, if a
+   two-character code is added to ISO 639-1 for a language for which a
+   three-character code was already included in ISO 639-2, the two-
+   character code MUST NOT be registered.  See Section 3.4.
+
+   For example, if some content were tagged with 'haw' (Hawaiian), which
+   currently has no two-character code, the tag would not be invalidated
+   if ISO 639-1 were to assign a two-character code to the Hawaiian
+   language at a later date.
+
+   For example, one of the grandfathered IANA registrations is
+   "i-enochian".  The subtag 'enochian' could be registered in the IANA
+   registry as a primary language subtag (assuming that ISO 639 does not
+   register this language first), making tags such as "enochian-AQ" and
+   "enochian-Latn" valid.
+
+2.2.2.  Extended Language Subtags
+
+   The following rules apply to the extended language subtags:
+
+   1.  Three-letter subtags immediately following the primary subtag are
+       reserved for future standardization, anticipating work that is
+       currently under way on ISO 639.
+
+   2.  Extended language subtags MUST follow the primary subtag and
+       precede any other subtags.
+
+   3.  There MAY be up to three extended language subtags.
+
+   4.  Extended language subtags MUST NOT be registered or used to form
+       language tags.  Their syntax is described here so that
+       implementations can be compatible with any future revision of
+       this document that does provide for their registration.
+
+   Extended language subtag records, once they appear in the registry,
+   MUST include exactly one 'Prefix' field indicating an appropriate
+   language subtag or sequence of subtags that MUST always appear as a
+   prefix to the extended language subtag.
+
+   Example: In a future revision or update of this document, the tag
+   "zh-gan" (registered under RFC 3066) might become a valid non-
+   grandfathered (that is, redundant) tag in which the subtag 'gan'
+   might represent the Chinese dialect 'Gan'.
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 10]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+2.2.3.  Script Subtag
+
+   Script subtags are used to indicate the script or writing system
+   variations that distinguish the written forms of a language or its
+   dialects.  The following rules apply to the script subtags:
+
+   1.  All four-character subtags were defined according to
+       [ISO15924]--"Codes for the representation of names of scripts":
+       alpha-4 script codes, or subsequently assigned by the ISO 15924
+       maintenance agency or governing standardization bodies, denoting
+       the script or writing system used in conjunction with this
+       language.
+
+   2.  Script subtags MUST immediately follow the primary language
+       subtag and all extended language subtags and MUST occur before
+       any other type of subtag described below.
+
+   3.  The script subtags 'Qaaa' through 'Qabx' are reserved for private
+       use in language tags.  These subtags correspond to codes reserved
+       by ISO 15924 for private use.  These codes MAY be used for non-
+       registered script values.  Please refer to Section 4.5 for more
+       information on private use subtags.
+
+   4.  Script subtags MUST NOT be registered using the process in
+       Section 3.5 of this document.  Variant subtags MAY be considered
+       for registration for that purpose.
+
+   5.  There MUST be at most one script subtag in a language tag, and
+       the script subtag SHOULD be omitted when it adds no
+       distinguishing value to the tag or when the primary language
+       subtag's record includes a Suppress-Script field listing the
+       applicable script subtag.
+
+   Example: "sr-Latn" represents Serbian written using the Latin script.
+
+2.2.4.  Region Subtag
+
+   Region subtags are used to indicate linguistic variations associated
+   with or appropriate to a specific country, territory, or region.
+   Typically, a region subtag is used to indicate regional dialects or
+   usage, or region-specific spelling conventions.  A region subtag can
+   also be used to indicate that content is expressed in a way that is
+   appropriate for use throughout a region, for instance, Spanish
+   content tailored to be useful throughout Latin America.
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 11]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The following rules apply to the region subtags:
+
+   1.  Region subtags MUST follow any language, extended language, or
+       script subtags and MUST precede all other subtags.
+
+   2.  All two-character subtags following the primary subtag were
+       defined in the IANA registry according to the assignments found
+       in [ISO3166-1] ("Codes for the representation of names of
+       countries and their subdivisions -- Part 1: Country codes") using
+       the list of alpha-2 country codes, or using assignments
+       subsequently made by the ISO 3166 maintenance agency or governing
+       standardization bodies.
+
+   3.  All three-character subtags consisting of digit (numeric)
+       characters following the primary subtag were defined in the IANA
+       registry according to the assignments found in UN Standard
+       Country or Area Codes for Statistical Use [UN_M.49] or
+       assignments subsequently made by the governing standards body.
+       Note that not all of the UN M.49 codes are defined in the IANA
+       registry.  The following rules define which codes are entered
+       into the registry as valid subtags:
+
+       A.  UN numeric codes assigned to 'macro-geographical
+           (continental)' or sub-regions MUST be registered in the
+           registry.  These codes are not associated with an assigned
+           ISO 3166 alpha-2 code and represent supra-national areas,
+           usually covering more than one nation, state, province, or
+           territory.
+
+       B.  UN numeric codes for 'economic groupings' or 'other
+           groupings' MUST NOT be registered in the IANA registry and
+           MUST NOT be used to form language tags.
+
+       C.  UN numeric codes for countries or areas with ambiguous ISO
+           3166 alpha-2 codes, when entered into the registry, MUST be
+           defined according to the rules in Section 3.4 and MUST be
+           used to form language tags that represent the country or
+           region for which they are defined.
+
+       D.  UN numeric codes for countries or areas for which there is an
+           associated ISO 3166 alpha-2 code in the registry MUST NOT be
+           entered into the registry and MUST NOT be used to form
+           language tags.  Note that the ISO 3166-based subtag in the
+           registry MUST actually be associated with the UN M.49 code in
+           question.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 12]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+       E.  UN numeric codes and ISO 3166 alpha-2 codes for countries or
+           areas listed as eligible for registration in [RFC4645] but
+           not presently registered MAY be entered into the IANA
+           registry via the process described in Section 3.5.  Once
+           registered, these codes MAY be used to form language tags.
+
+       F.  All other UN numeric codes for countries or areas that do not
+           have an associated ISO 3166 alpha-2 code MUST NOT be entered
+           into the registry and MUST NOT be used to form language tags.
+           For more information about these codes, see Section 3.4.
+
+   4.  Note: The alphanumeric codes in Appendix X of the UN document
+       MUST NOT be entered into the registry and MUST NOT be used to
+       form language tags.  (At the time this document was created,
+       these values matched the ISO 3166 alpha-2 codes.)
+
+   5.  There MUST be at most one region subtag in a language tag and the
+       region subtag MAY be omitted, as when it adds no distinguishing
+       value to the tag.
+
+   6.  The region subtags 'AA', 'QM'-'QZ', 'XA'-'XZ', and 'ZZ' are
+       reserved for private use in language tags.  These subtags
+       correspond to codes reserved by ISO 3166 for private use.  These
+       codes MAY be used for private use region subtags (instead of
+       using a private use subtag sequence).  Please refer to
+       Section 4.5 for more information on private use subtags.
+
+   "de-CH" represents German ('de') as used in Switzerland ('CH').
+
+   "sr-Latn-CS" represents Serbian ('sr') written using Latin script
+   ('Latn') as used in Serbia and Montenegro ('CS').
+
+   "es-419" represents Spanish ('es') appropriate to the UN-defined
+   Latin America and Caribbean region ('419').
+
+2.2.5.  Variant Subtags
+
+   Variant subtags are used to indicate additional, well-recognized
+   variations that define a language or its dialects that are not
+   covered by other available subtags.  The following rules apply to the
+   variant subtags:
+
+   1.  Variant subtags are not associated with any external standard.
+       Variant subtags and their meanings are defined by the
+       registration process defined in Section 3.5.
+
+   2.  Variant subtags MUST follow all of the other defined subtags, but
+       precede any extension or private use subtag sequences.
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 13]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   3.  More than one variant MAY be used to form the language tag.
+
+   4.  Variant subtags MUST be registered with IANA according to the
+       rules in Section 3.5 of this document before being used to form
+       language tags.  In order to distinguish variants from other types
+       of subtags, registrations MUST meet the following length and
+       content restrictions:
+
+       1.  Variant subtags that begin with a letter (a-z, A-Z) MUST be
+           at least five characters long.
+
+       2.  Variant subtags that begin with a digit (0-9) MUST be at
+           least four characters long.
+
+   Variant subtag records in the language subtag registry MAY include
+   one or more 'Prefix' fields, which indicate the language tag or tags
+   that would make a suitable prefix (with other subtags, as
+   appropriate) in forming a language tag with the variant.  For
+   example, the subtag 'nedis' has a Prefix of "sl", making it suitable
+   to form language tags such as "sl-nedis" and "sl-IT-nedis", but not
+   suitable for use in a tag such as "zh-nedis" or "it-IT-nedis".
+
+   "sl-nedis" represents the Natisone or Nadiza dialect of Slovenian.
+
+   "de-CH-1996" represents German as used in Switzerland and as written
+   using the spelling reform beginning in the year 1996 C.E.
+
+   Most variants that share a prefix are mutually exclusive.  For
+   example, the German orthographic variations '1996' and '1901' SHOULD
+   NOT be used in the same tag, as they represent the dates of different
+   spelling reforms.  A variant that can meaningfully be used in
+   combination with another variant SHOULD include a 'Prefix' field in
+   its registry record that lists that other variant.  For example, if
+   another German variant 'example' were created that made sense to use
+   with '1996', then 'example' should include two Prefix fields: "de"
+   and "de-1996".
+
+2.2.6.  Extension Subtags
+
+   Extensions provide a mechanism for extending language tags for use in
+   various applications.  See Section 3.7.  The following rules apply to
+   extensions:
+
+   1.   Extension subtags are separated from the other subtags defined
+        in this document by a single-character subtag ("singleton").
+        The singleton MUST be one allocated to a registration authority
+        via the mechanism described in Section 3.7 and MUST NOT be the
+        letter 'x', which is reserved for private use subtag sequences.
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 14]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   2.   Note: Private use subtag sequences starting with the singleton
+        subtag 'x' are described in Section 2.2.7 below.
+
+   3.   An extension MUST follow at least a primary language subtag.
+        That is, a language tag cannot begin with an extension.
+        Extensions extend language tags, they do not override or replace
+        them.  For example, "a-value" is not a well-formed language tag,
+        while "de-a-value" is.
+
+   4.   Each singleton subtag MUST appear at most one time in each tag
+        (other than as a private use subtag).  That is, singleton
+        subtags MUST NOT be repeated.  For example, the tag
+        "en-a-bbb-a-ccc" is invalid because the subtag 'a' appears
+        twice.  Note that the tag "en-a-bbb-x-a-ccc" is valid because
+        the second appearance of the singleton 'a' is in a private use
+        sequence.
+
+   5.   Extension subtags MUST meet all of the requirements for the
+        content and format of subtags defined in this document.
+
+   6.   Extension subtags MUST meet whatever requirements are set by the
+        document that defines their singleton prefix and whatever
+        requirements are provided by the maintaining authority.
+
+   7.   Each extension subtag MUST be from two to eight characters long
+        and consist solely of letters or digits, with each subtag
+        separated by a single '-'.
+
+   8.   Each singleton MUST be followed by at least one extension
+        subtag.  For example, the tag "tlh-a-b-foo" is invalid because
+        the first singleton 'a' is followed immediately by another
+        singleton 'b'.
+
+   9.   Extension subtags MUST follow all language, extended language,
+        script, region, and variant subtags in a tag.
+
+   10.  All subtags following the singleton and before another singleton
+        are part of the extension.  Example: In the tag "fr-a-Latn", the
+        subtag 'Latn' does not represent the script subtag 'Latn'
+        defined in the IANA Language Subtag Registry.  Its meaning is
+        defined by the extension 'a'.
+
+   11.  In the event that more than one extension appears in a single
+        tag, the tag SHOULD be canonicalized as described in
+        Section 4.4.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 15]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   For example, if the prefix singleton 'r' and the shown subtags were
+   defined, then the following tag would be a valid example:
+   "en-Latn-GB-boont-r-extended-sequence-x-private".
+
+2.2.7.  Private Use Subtags
+
+   Private use subtags are used to indicate distinctions in language
+   important in a given context by private agreement.  The following
+   rules apply to private use subtags:
+
+   1.  Private use subtags are separated from the other subtags defined
+       in this document by the reserved single-character subtag 'x'.
+
+   2.  Private use subtags MUST conform to the format and content
+       constraints defined in the ABNF for all subtags.
+
+   3.  Private use subtags MUST follow all language, extended language,
+       script, region, variant, and extension subtags in the tag.
+       Another way of saying this is that all subtags following the
+       singleton 'x' MUST be considered private use.  Example: The
+       subtag 'US' in the tag "en-x-US" is a private use subtag.
+
+   4.  A tag MAY consist entirely of private use subtags.
+
+   5.  No source is defined for private use subtags.  Use of private use
+       subtags is by private agreement only.
+
+   6.  Private use subtags are NOT RECOMMENDED where alternatives exist
+       or for general interchange.  See Section 4.5 for more information
+       on private use subtag choice.
+
+   For example: Users who wished to utilize codes from the Ethnologue
+   publication of SIL International for language identification might
+   agree to exchange tags such as "az-Arab-x-AZE-derbend".  This example
+   contains two private use subtags.  The first is 'AZE' and the second
+   is 'derbend'.
+
+2.2.8.  Preexisting RFC 3066 Registrations
+
+   Existing IANA-registered language tags from RFC 1766 and/or RFC 3066
+   maintain their validity.  These tags will be maintained in the
+   registry in records of either the "grandfathered" or "redundant"
+   type.  Grandfathered tags contain one or more subtags that are not
+   defined in the Language Subtag Registry (see Section 3).  Redundant
+   tags consist entirely of subtags defined above and whose independent
+   registration is superseded by this document.  For more information,
+   see Section 3.8.
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 16]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   It is important to note that all language tags formed under the
+   guidelines in this document were either legal, well-formed tags or
+   could have been registered under RFC 3066.
+
+2.2.9.  Classes of Conformance
+
+   Implementations sometimes need to describe their capabilities with
+   regard to the rules and practices described in this document.  There
+   are two classes of conforming implementations described by this
+   document: "well-formed" processors and "validating" processors.
+   Claims of conformance SHOULD explicitly reference one of these
+   definitions.
+
+   An implementation that claims to check for well-formed language tags
+   MUST:
+
+   o  Check that the tag and all of its subtags, including extension and
+      private use subtags, conform to the ABNF or that the tag is on the
+      list of grandfathered tags.
+
+   o  Check that singleton subtags that identify extensions do not
+      repeat.  For example, the tag "en-a-xx-b-yy-a-zz" is not well-
+      formed.
+
+   Well-formed processors are strongly encouraged to implement the
+   canonicalization rules contained in Section 4.4.
+
+   An implementation that claims to be validating MUST:
+
+   o  Check that the tag is well-formed.
+
+   o  Specify the particular registry date for which the implementation
+      performs validation of subtags.
+
+   o  Check that either the tag is a grandfathered tag, or that all
+      language, script, region, and variant subtags consist of valid
+      codes for use in language tags according to the IANA registry as
+      of the particular date specified by the implementation.
+
+   o  Specify which, if any, extension RFCs as defined in Section 3.7
+      are supported, including version, revision, and date.
+
+   o  For any such extensions supported, check that all subtags used in
+      that extension are valid.
+
+   o  For variant and extended language subtags, if the registry
+      contains one or more 'Prefix' fields for that subtag, check that
+      the tag matches at least one prefix.  The tag matches if all the
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 17]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+      subtags in the 'Prefix' also appear in the tag.  For example, the
+      prefix "es-CO" matches the tag "es-Latn-CO-x-private" because both
+      the 'es' language subtag and 'CO' region subtag appear in the tag.
+
+3.  Registry Format and Maintenance
+
+   This section defines the Language Subtag Registry and the maintenance
+   and update procedures associated with it, as well as a registry for
+   extensions to language tags (Section 3.7).
+
+   The Language Subtag Registry contains a comprehensive list of all of
+   the subtags valid in language tags.  This allows implementers a
+   straightforward and reliable way to validate language tags.  The
+   Language Subtag Registry will be maintained so that, except for
+   extension subtags, it is possible to validate all of the subtags that
+   appear in a language tag under the provisions of this document or its
+   revisions or successors.  In addition, the meaning of the various
+   subtags will be unambiguous and stable over time.  (The meaning of
+   private use subtags, of course, is not defined by the IANA registry.)
+
+3.1.  Format of the IANA Language Subtag Registry
+
+   The IANA Language Subtag Registry ("the registry") consists of a text
+   file that is machine readable in the format described in this
+   section, plus copies of the registration forms approved in accordance
+   with the process described in Section 3.5.  The existing registration
+   forms for grandfathered and redundant tags taken from RFC 3066 will
+   be maintained as part of the obsolete RFC 3066 registry.  The
+   remaining set of initial subtags will not have registration forms
+   created for them.
+
+   The registry is in the text format described below.  This format was
+   based on the record-jar format described in [record-jar].
+
+   Each line of text is limited to 72 characters, including all
+   whitespace.  Records are separated by lines containing only the
+   sequence "%%" (%x25.25).
+
+   Each field can be viewed as a single, logical line of ASCII
+   characters, comprising a field-name and a field-body separated by a
+   COLON character (%x3A).  For convenience, the field-body portion of
+   this conceptual entity can be split into a multiple-line
+   representation; this is called "folding".  The format of the registry
+   is described by the following ABNF (per [RFC4234]):
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 18]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   registry   = record *("%%" CRLF record)
+   record     = 1*( field-name *SP ":" *SP field-body CRLF )
+   field-name = (ALPHA / DIGIT) [*(ALPHA / DIGIT / "-") (ALPHA / DIGIT)]
+   field-body = *(ASCCHAR/LWSP)
+   ASCCHAR    = %x21-25 / %x27-7E / UNICHAR ; Note: AMPERSAND is %x26
+   UNICHAR    = "&#x" 2*6HEXDIG ";"
+
+                      Figure 2: Registry Format ABNF
+
+   The sequence '..' (%x2E.2E) in a field-body denotes a range of
+   values.  Such a range represents all subtags of the same length that
+   are in alphabetic or numeric order within that range, including the
+   values explicitly mentioned.  For example 'a..c' denotes the values
+   'a', 'b', and 'c' and '11..13' denotes the values '11', '12', and
+   '13'.
+
+   Characters from outside the US-ASCII [ISO646] repertoire, as well as
+   the AMPERSAND character ("&", %x26) when it occurs in a field-body,
+   are represented by a "Numeric Character Reference" using hexadecimal
+   notation in the style used by [XML10] (see
+   <http://www.w3.org/TR/REC-xml/#dt-charref>).  This consists of the
+   sequence "&#x" (%x26.23.78) followed by a hexadecimal representation
+   of the character's code point in [ISO10646] followed by a closing
+   semicolon (%x3B).  For example, the EURO SIGN, U+20AC, would be
+   represented by the sequence "&#x20AC;".  Note that the hexadecimal
+   notation MAY have between two and six digits.
+
+   All fields whose field-body contains a date value use the "full-date"
+   format specified in [RFC3339].  For example: "2004-06-28" represents
+   June 28, 2004, in the Gregorian calendar.
+
+   The first record in the file contains the single field whose field-
+   name is "File-Date" (see Figure 3).  The field-body of this record
+   contains the last modification date of this copy of the registry,
+   making it possible to compare different versions of the registry.
+   The registry on the IANA website is the most current.  Versions with
+   an older date than that one are not up-to-date.
+
+   File-Date: 2004-06-28
+   %%
+
+                 Figure 3: Example of the File-Date Record
+
+   Subsequent records represent subtags in the registry.  Each of the
+   fields in each record MUST occur no more than once, unless otherwise
+   noted below.  Each record MUST contain the following fields:
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 19]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   o  'Type'
+
+      *  Type's field-value MUST consist of one of the following
+         strings: "language", "extlang", "script", "region", "variant",
+         "grandfathered", and "redundant" and denotes the type of tag or
+         subtag.
+
+   o  Either 'Subtag' or 'Tag'
+
+      *  Subtag's field-value contains the subtag being defined.  This
+         field MUST only appear in records of whose 'Type' has one of
+         these values: "language", "extlang", "script", "region", or
+         "variant".
+
+      *  Tag's field-value contains a complete language tag.  This field
+         MUST only appear in records whose 'Type' has one of these
+         values: "grandfathered" or "redundant".  Note that the field-
+         value will always follow the 'grandfathered' production in the
+         ABNF in Section 2.1
+
+   o  Description
+
+      *  Description's field-value contains a non-normative description
+         of the subtag or tag.
+
+   o  Added
+
+      *  Added's field-value contains the date the record was added to
+         the registry.
+
+   The 'Subtag' or 'Tag' field MUST use lowercase letters to form the
+   subtag or tag, with two exceptions.  Subtags whose 'Type' field is
+   'script' (in other words, subtags defined by ISO 15924) MUST use
+   titlecase.  Subtags whose 'Type' field is 'region' (in other words,
+   subtags defined by ISO 3166) MUST use uppercase.  These exceptions
+   mirror the use of case in the underlying standards.
+
+   The field 'Description' MAY appear more than one time and contains a
+   description of the tag or subtag in the record.  At least one of the
+   'Description' fields MUST be written or transcribed into the Latin
+   script; the same or additional fields MAY also include a description
+   in a non-Latin script.  The 'Description' field is used for
+   identification purposes and SHOULD NOT be taken to represent the
+   actual native name of the language or variation or to be in any
+   particular language.  Most descriptions are taken directly from
+   source standards such as ISO 639 or ISO 3166.
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 20]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   Note: Descriptions in registry entries that correspond to ISO 639,
+   ISO 15924, ISO 3166, or UN M.49 codes are intended only to indicate
+   the meaning of that identifier as defined in the source standard at
+   the time it was added to the registry.  The description does not
+   replace the content of the source standard itself.  The descriptions
+   are not intended to be the English localized names for the subtags.
+   Localization or translation of language tag and subtag descriptions
+   is out of scope of this document.
+
+   Each record MAY also contain the following fields:
+
+   o  Preferred-Value
+
+      *  For fields of type 'language', 'extlang', 'script', 'region',
+         and 'variant', 'Preferred-Value' contains the subtag of the
+         same 'Type' that is preferred for forming the language tag.
+
+      *  For fields of type 'grandfathered' and 'redundant', a canonical
+         mapping to a complete language tag.
+
+   o  Deprecated
+
+      *  Deprecated's field-value contains the date the record was
+         deprecated.
+
+   o  Prefix
+
+      *  Prefix's field-value contains a language tag with which this
+         subtag MAY be used to form a new language tag, perhaps with
+         other subtags as well.  This field MUST only appear in records
+         whose 'Type' field-value is 'variant' or 'extlang'.  For
+         example, the 'Prefix' for the variant 'nedis' is 'sl', meaning
+         that the tags "sl-nedis" and "sl-IT-nedis" might be appropriate
+         while the tag "is-nedis" is not.
+
+   o  Comments
+
+      *  Comments contains additional information about the subtag, as
+         deemed appropriate for understanding the registry and
+         implementing language tags using the subtag or tag.
+
+   o  Suppress-Script
+
+      *  Suppress-Script contains a script subtag that SHOULD NOT be
+         used to form language tags with the associated primary language
+         subtag.  This field MUST only appear in records whose 'Type'
+         field-value is 'language'.  See Section 4.1.
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 21]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The field 'Deprecated' MAY be added to any record via the maintenance
+   process described in Section 3.3 or via the registration process
+   described in Section 3.5.  Usually, the addition of a 'Deprecated'
+   field is due to the action of one of the standards bodies, such as
+   ISO 3166, withdrawing a code.  In some historical cases, it might not
+   have been possible to reconstruct the original deprecation date.  For
+   these cases, an approximate date appears in the registry.  Although
+   valid in language tags, subtags and tags with a 'Deprecated' field
+   are deprecated and validating processors SHOULD NOT generate these
+   subtags.  Note that a record that contains a 'Deprecated' field and
+   no corresponding 'Preferred-Value' field has no replacement mapping.
+
+   The field 'Preferred-Value' contains a mapping between the record in
+   which it appears and another tag or subtag.  The value in this field
+   is STRONGLY RECOMMENDED as the best choice to represent the value of
+   this record when selecting a language tag.  These values form three
+   groups:
+
+   1.  ISO 639 language codes that were later withdrawn in favor of
+       other codes.  These values are mostly a historical curiosity.
+
+   2.  ISO 3166 region codes that have been withdrawn in favor of a new
+       code.  This sometimes happens when a country changes its name or
+       administration in such a way that warrants a new region code.
+
+   3.  Tags grandfathered from RFC 3066.  In many cases, these tags have
+       become obsolete because the values they represent were later
+       encoded by ISO 639.
+
+   Records that contain a 'Preferred-Value' field MUST also have a
+   'Deprecated' field.  This field contains a date of deprecation.
+   Thus, a language tag processor can use the registry to construct the
+   valid, non-deprecated set of subtags for a given date.  In addition,
+   for any given tag, a processor can construct the set of valid
+   language tags that correspond to that tag for all dates up to the
+   date of the registry.  The ability to do these mappings MAY be
+   beneficial to applications that are matching, selecting, for
+   filtering content based on its language tags.
+
+   Note that 'Preferred-Value' mappings in records of type 'region'
+   sometimes do not represent exactly the same meaning as the original
+   value.  There are many reasons for a country code to be changed, and
+   the effect this has on the formation of language tags will depend on
+   the nature of the change in question.
+
+   In particular, the 'Preferred-Value' field does not imply retagging
+   content that uses the affected subtag.
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 22]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The field 'Preferred-Value' MUST NOT be modified once created in the
+   registry.  The field MAY be added to records of type "grandfathered"
+   and "region" according to the rules in Section 3.3.  Otherwise the
+   field MUST NOT be added to any record already in the registry.
+
+   The 'Preferred-Value' field in records of type "grandfathered" and
+   "redundant" contains whole language tags that are strongly
+   RECOMMENDED for use in place of the record's value.  In many cases,
+   the mappings were created by deprecation of the tags during the
+   period before this document was adopted.  For example, the tag
+   "no-nyn" was deprecated in favor of the ISO 639-1-defined language
+   code 'nn'.
+
+   Records of type 'variant' MAY have more than one field of type
+   'Prefix'.  Additional fields of this type MAY be added to a 'variant'
+   record via the registration process.
+
+   Records of type 'extlang' MUST have _exactly_ one 'Prefix' field.
+
+   The field-value of the 'Prefix' field consists of a language tag
+   whose subtags are appropriate to use with this subtag.  For example,
+   the variant subtag '1996' has a 'Prefix' field of "de".  This means
+   that tags starting with the sequence "de-" are appropriate with this
+   subtag, so "de-Latg-1996" and "de-CH-1996" are both acceptable, while
+   the tag "fr-1996" is an inappropriate choice.
+
+   The field of type 'Prefix' MUST NOT be removed from any record.  The
+   field-value for this type of field MUST NOT be modified.
+
+   The field 'Comments' MAY appear more than once per record.  This
+   field MAY be inserted or changed via the registration process and no
+   guarantee of stability is provided.  The content of this field is not
+   restricted, except by the need to register the information, the
+   suitability of the request, and by reasonable practical size
+   limitations.
+
+   The field 'Suppress-Script' MUST only appear in records whose 'Type'
+   field-value is 'language'.  This field MUST NOT appear more than one
+   time in a record.  This field indicates a script used to write the
+   overwhelming majority of documents for the given language and that
+   therefore adds no distinguishing information to a language tag.  It
+   helps ensure greater compatibility between the language tags
+   generated according to the rules in this document and language tags
+   and tag processors or consumers based on RFC 3066.  For example,
+   virtually all Icelandic documents are written in the Latin script,
+   making the subtag 'Latn' redundant in the tag "is-Latn".
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 23]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+3.2.  Language Subtag Reviewer
+
+   The Language Subtag Reviewer is appointed by the IESG for an
+   indefinite term, subject to removal or replacement at the IESG's
+   discretion.  The Language Subtag Reviewer moderates the ietf-
+   languages mailing list, responds to requests for registration, and
+   performs the other registry maintenance duties described in
+   Section 3.3.  Only the Language Subtag Reviewer is permitted to
+   request IANA to change, update, or add records to the Language Subtag
+   Registry.
+
+   The performance or decisions of the Language Subtag Reviewer MAY be
+   appealed to the IESG under the same rules as other IETF decisions
+   (see [RFC2026]).  The IESG can reverse or overturn the decision of
+   the Language Subtag Reviewer, provide guidance, or take other
+   appropriate actions.
+
+3.3.  Maintenance of the Registry
+
+   Maintenance of the registry requires that as codes are assigned or
+   withdrawn by ISO 639, ISO 15924, ISO 3166, and UN M.49, the Language
+   Subtag Reviewer MUST evaluate each change, determine whether it
+   conflicts with existing registry entries, and submit the information
+   to IANA for inclusion in the registry.  If a change takes place and
+   the Language Subtag Reviewer does not do this in a timely manner,
+   then any interested party MAY use the procedure in Section 3.5 to
+   register the appropriate update.
+
+   Note: The redundant and grandfathered entries together are the
+   complete list of tags registered under [RFC3066].  The redundant tags
+   are those that can now be formed using the subtags defined in the
+   registry together with the rules of Section 2.2.  The grandfathered
+   entries include those that can never be legal under those same
+   provisions.
+
+   The set of redundant and grandfathered tags is permanent and stable:
+   new entries in this section MUST NOT be added and existing entries
+   MUST NOT be removed.  Records of type 'grandfathered' MAY have their
+   type converted to 'redundant'; see item 12 in Section 3.6 for more
+   information.  The decision-making process about which tags were
+   initially grandfathered and which were made redundant is described in
+   [RFC4645].
+
+   RFC 3066 tags that were deprecated prior to the adoption of this
+   document are part of the list of grandfathered tags, and their
+   component subtags were not included as registered variants (although
+   they remain eligible for registration).  For example, the tag
+   "art-lojban" was deprecated in favor of the language subtag 'jbo'.
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 24]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The Language Subtag Reviewer MUST ensure that new subtags meet the
+   requirements in Section 4.1 or submit an appropriate alternate subtag
+   as described in that section.  When either a change or addition to
+   the registry is needed, the Language Subtag Reviewer MUST prepare the
+   complete record, including all fields, and forward it to IANA for
+   insertion into the registry.  Each record being modified or inserted
+   MUST be forwarded in a separate message.
+
+   If a record represents a new subtag that does not currently exist in
+   the registry, then the message's subject line MUST include the word
+   "INSERT".  If the record represents a change to an existing subtag,
+   then the subject line of the message MUST include the word "MODIFY".
+   The message MUST contain both the record for the subtag being
+   inserted or modified and the new File-Date record.  Here is an
+   example of what the body of the message might contain:
+
+   LANGUAGE SUBTAG MODIFICATION
+   File-Date: 2005-01-02
+   %%
+   Type: variant
+   Subtag: nedis
+   Description: Natisone dialect
+   Description: Nadiza dialect
+   Added: 2003-10-09
+   Prefix: sl
+   Comments: This is a comment shown
+     as an example.
+   %%
+
+         Figure 4: Example of a Language Subtag Modification Form
+
+   Whenever an entry is created or modified in the registry, the
+   'File-Date' record at the start of the registry is updated to reflect
+   the most recent modification date in the [RFC3339] "full-date"
+   format.
+
+   Before forwarding a new registration to IANA, the Language Subtag
+   Reviewer MUST ensure that values in the 'Subtag' field match case
+   according to the description in Section 3.1.
+
+3.4.  Stability of IANA Registry Entries
+
+   The stability of entries and their meaning in the registry is
+   critical to the long-term stability of language tags.  The rules in
+   this section guarantee that a specific language tag's meaning is
+   stable over time and will not change.
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 25]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   These rules specifically deal with how changes to codes (including
+   withdrawal and deprecation of codes) maintained by ISO 639, ISO
+   15924, ISO 3166, and UN M.49 are reflected in the IANA Language
+   Subtag Registry.  Assignments to the IANA Language Subtag Registry
+   MUST follow the following stability rules:
+
+   1.   Values in the fields 'Type', 'Subtag', 'Tag', 'Added',
+        'Deprecated' and 'Preferred-Value' MUST NOT be changed and are
+        guaranteed to be stable over time.
+
+   2.   Values in the 'Description' field MUST NOT be changed in a way
+        that would invalidate previously-existing tags.  They MAY be
+        broadened somewhat in scope, changed to add information, or
+        adapted to the most common modern usage.  For example, countries
+        occasionally change their official names; a historical example
+        of this would be "Upper Volta" changing to "Burkina Faso".
+
+   3.   Values in the field 'Prefix' MAY be added to records of type
+        'variant' via the registration process.
+
+   4.   Values in the field 'Prefix' MAY be modified, so long as the
+        modifications broaden the set of prefixes.  That is, a prefix
+        MAY be replaced by one of its own prefixes.  For example, the
+        prefix "en-US" could be replaced by "en", but not by the
+        prefixes "en-Latn", "fr", or "en-US-boont".  If one of those
+        prefixes were needed, a new Prefix SHOULD be registered.
+
+   5.   Values in the field 'Prefix' MUST NOT be removed.
+
+   6.   The field 'Comments' MAY be added, changed, modified, or removed
+        via the registration process or any of the processes or
+        considerations described in this section.
+
+   7.   The field 'Suppress-Script' MAY be added or removed via the
+        registration process.
+
+   8.   Codes assigned by ISO 639, ISO 15924, and ISO 3166 that do not
+        conflict with existing subtags of the associated type and whose
+        meaning is not the same as an existing subtag of the same type
+        are entered into the IANA registry as new records.
+
+   9.   Codes assigned by ISO 639, ISO 15924, or ISO 3166 that are
+        withdrawn by their respective maintenance or registration
+        authority remain valid in language tags.  A 'Deprecated' field
+        containing the date of withdrawal is added to the record.  If a
+        new record of the same type is added that represents a
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 26]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+        replacement value, then a 'Preferred-Value' field MAY also be
+        added.  The registration process MAY be used to add comments
+        about the withdrawal of the code by the respective standard.
+
+        Example
+           The region code 'TL' was assigned to the country 'Timor-
+           Leste', replacing the code 'TP' (which was assigned to 'East
+           Timor' when it was under administration by Portugal).  The
+           subtag 'TP' remains valid in language tags, but its record
+           contains the a 'Preferred-Value' of 'TL' and its field
+           'Deprecated' contains the date the new code was assigned
+           ('2004-07-06').
+
+   10.  Codes assigned by ISO 639, ISO 15924, or ISO 3166 that conflict
+        with existing subtags of the associated type, including subtags
+        that are deprecated, MUST NOT be entered into the registry.  The
+        following additional considerations apply to subtag values that
+        are reassigned:
+
+        A.  For ISO 639 codes, if the newly assigned code's meaning is
+            not represented by a subtag in the IANA registry, the
+            Language Subtag Reviewer, as described in Section 3.5, SHALL
+            prepare a proposal for entering in the IANA registry as soon
+            as practical a registered language subtag as an alternate
+            value for the new code.  The form of the registered language
+            subtag will be at the discretion of the Language Subtag
+            Reviewer and MUST conform to other restrictions on language
+            subtags in this document.
+
+        B.  For all subtags whose meaning is derived from an external
+            standard (i.e., ISO 639, ISO 15924, ISO 3166, or UN M.49),
+            if a new meaning is assigned to an existing code and the new
+            meaning broadens the meaning of that code, then the meaning
+            for the associated subtag MAY be changed to match.  The
+            meaning of a subtag MUST NOT be narrowed, however, as this
+            can result in an unknown proportion of the existing uses of
+            a subtag becoming invalid.  Note: ISO 639 maintenance
+            agency/registration authority (MA/RA) has adopted a similar
+            stability policy.
+
+        C.  For ISO 15924 codes, if the newly assigned code's meaning is
+            not represented by a subtag in the IANA registry, the
+            Language Subtag Reviewer, as described in Section 3.5, SHALL
+            prepare a proposal for entering in the IANA registry as soon
+            as practical a registered variant subtag as an alternate
+            value for the new code.  The form of the registered variant
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 27]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+            subtag will be at the discretion of the Language Subtag
+            Reviewer and MUST conform to other restrictions on variant
+            subtags in this document.
+
+        D.  For ISO 3166 codes, if the newly assigned code's meaning is
+            associated with the same UN M.49 code as another 'region'
+            subtag, then the existing region subtag remains as the
+            preferred value for that region and no new entry is created.
+            A comment MAY be added to the existing region subtag
+            indicating the relationship to the new ISO 3166 code.
+
+        E.  For ISO 3166 codes, if the newly assigned code's meaning is
+            associated with a UN M.49 code that is not represented by an
+            existing region subtag, then the Language Subtag Reviewer,
+            as described in Section 3.5, SHALL prepare a proposal for
+            entering the appropriate UN M.49 country code as an entry in
+            the IANA registry.
+
+        F.  For ISO 3166 codes, if there is no associated UN numeric
+            code, then the Language Subtag Reviewer SHALL petition the
+            UN to create one.  If there is no response from the UN
+            within ninety days of the request being sent, the Language
+            Subtag Reviewer SHALL prepare a proposal for entering in the
+            IANA registry as soon as practical a registered variant
+            subtag as an alternate value for the new code.  The form of
+            the registered variant subtag will be at the discretion of
+            the Language Subtag Reviewer and MUST conform to other
+            restrictions on variant subtags in this document.  This
+            situation is very unlikely to ever occur.
+
+   11.  UN M.49 has codes for both countries and areas (such as '276'
+        for Germany) and geographical regions and sub-regions (such as
+        '150' for Europe).  UN M.49 country or area codes for which
+        there is no corresponding ISO 3166 code SHOULD NOT be
+        registered, except as a surrogate for an ISO 3166 code that is
+        blocked from registration by an existing subtag.  If such a code
+        becomes necessary, then the registration authority for ISO 3166
+        SHOULD first be petitioned to assign a code to the region.  If
+        the petition for a code assignment by ISO 3166 is refused or not
+        acted on in a timely manner, the registration process described
+        in Section 3.5 MAY then be used to register the corresponding UN
+        M.49 code.  At the time this document was written, there were
+        only four such codes: 830 (Channel Islands), 831 (Guernsey), 832
+        (Jersey), and 833 (Isle of Man).  This way, UN M.49 codes remain
+        available as the value of last resort in cases where ISO 3166
+        reassigns a deprecated value in the registry.
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 28]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   12.  Stability provisions apply to grandfathered tags with this
+        exception: should all of the subtags in a grandfathered tag
+        become valid subtags in the IANA registry, then the field 'Type'
+        in that record is changed from 'grandfathered' to 'redundant'.
+        Note that this will not affect language tags that match the
+        grandfathered tag, since these tags will now match valid
+        generative subtag sequences.  For example, if the subtag 'gan'
+        in the language tag "zh-gan" were to be registered as an
+        extended language subtag, then the grandfathered tag "zh-gan"
+        would be deprecated (but existing content or implementations
+        that use "zh-gan" would remain valid).
+
+3.5.  Registration Procedure for Subtags
+
+   The procedure given here MUST be used by anyone who wants to use a
+   subtag not currently in the IANA Language Subtag Registry.
+
+   Only subtags of type 'language' and 'variant' will be considered for
+   independent registration of new subtags.  Handling of subtags needed
+   for stability and subtags necessary to keep the registry synchronized
+   with ISO 639, ISO 15924, ISO 3166, and UN M.49 within the limits
+   defined by this document are described in Section 3.3.  Stability
+   provisions are described in Section 3.4.
+
+   This procedure MAY also be used to register or alter the information
+   for the 'Description', 'Comments', 'Deprecated', or 'Prefix' fields
+   in a subtag's record as described in Section 3.4.  Changes to all
+   other fields in the IANA registry are NOT permitted.
+
+   Registering a new subtag or requesting modifications to an existing
+   tag or subtag starts with the requester filling out the registration
+   form reproduced below.  Note that each response is not limited in
+   size so that the request can adequately describe the registration.
+   The fields in the "Record Requested" section SHOULD follow the
+   requirements in Section 3.1.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 29]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   LANGUAGE SUBTAG REGISTRATION FORM
+   1. Name of requester:
+   2. E-mail address of requester:
+   3. Record Requested:
+
+      Type:
+      Subtag:
+      Description:
+      Prefix:
+      Preferred-Value:
+      Deprecated:
+      Suppress-Script:
+      Comments:
+
+   4. Intended meaning of the subtag:
+   5. Reference to published description
+      of the language (book or article):
+   6. Any other relevant information:
+
+              Figure 5: The Language Subtag Registration Form
+
+   The subtag registration form MUST be sent to
+   <ietf-languages@iana.org> for a two-week review period before it can
+   be submitted to IANA.  (This is an open list and can be joined by
+   sending a request to <ietf-languages-request@iana.org>.)
+
+   Variant subtags are usually registered for use with a particular
+   range of language tags.  For example, the subtag 'rozaj' is intended
+   for use with language tags that start with the primary language
+   subtag "sl", since Resian is a dialect of Slovenian.  Thus, the
+   subtag 'rozaj' would be appropriate in tags such as "sl-Latn-rozaj"
+   or "sl-IT-rozaj".  This information is stored in the 'Prefix' field
+   in the registry.  Variant registration requests SHOULD include at
+   least one 'Prefix' field in the registration form.
+
+   Extended language subtags are reserved for future standardization.
+   These subtags will be REQUIRED to include exactly one 'Prefix' field
+   once they are allowed for registration.
+
+   The 'Prefix' field for a given registered subtag exists in the IANA
+   registry as a guide to usage.  Additional prefixes MAY be added by
+   filing an additional registration form.  In that form, the "Any other
+   relevant information:" field MUST indicate that it is the addition of
+   a prefix.
+
+   Requests to add a prefix to a variant subtag that imply a different
+   semantic meaning will probably be rejected.  For example, a request
+   to add the prefix "de" to the subtag 'nedis' so that the tag
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 30]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   "de-nedis" represented some German dialect would be rejected.  The
+   'nedis' subtag represents a particular Slovenian dialect and the
+   additional registration would change the semantic meaning assigned to
+   the subtag.  A separate subtag SHOULD be proposed instead.
+
+   The 'Description' field MUST contain a description of the tag being
+   registered written or transcribed into the Latin script; it MAY also
+   include a description in a non-Latin script.  Non-ASCII characters
+   MUST be escaped using the syntax described in Section 3.1.  The
+   'Description' field is used for identification purposes and doesn't
+   necessarily represent the actual native name of the language or
+   variation or to be in any particular language.
+
+   While the 'Description' field itself is not guaranteed to be stable
+   and errata corrections MAY be undertaken from time to time, attempts
+   to provide translations or transcriptions of entries in the registry
+   itself will probably be frowned upon by the community or rejected
+   outright, as changes of this nature have an impact on the provisions
+   in Section 3.4.
+
+   When the two-week period has passed, the Language Subtag Reviewer
+   either forwards the record to be inserted or modified to
+   iana@iana.org according to the procedure described in Section 3.3, or
+   rejects the request because of significant objections raised on the
+   list or due to problems with constraints in this document (which MUST
+   be explicitly cited).  The Language Subtag Reviewer MAY also extend
+   the review period in two-week increments to permit further
+   discussion.  The Language Subtag Reviewer MUST indicate on the list
+   whether the registration has been accepted, rejected, or extended
+   following each two-week period.
+
+   Note that the Language Subtag Reviewer MAY raise objections on the
+   list if he or she so desires.  The important thing is that the
+   objection MUST be made publicly.
+
+   The applicant is free to modify a rejected application with
+   additional information and submit it again; this restarts the two-
+   week comment period.
+
+   Decisions made by the Language Subtag Reviewer MAY be appealed to the
+   IESG [RFC2028] under the same rules as other IETF decisions
+   [RFC2026].
+
+   All approved registration forms are available online in the directory
+   http://www.iana.org/numbers.html under "languages".
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 31]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   Updates or changes to existing records follow the same procedure as
+   new registrations.  The Language Subtag Reviewer decides whether
+   there is consensus to update the registration following the two-week
+   review period; normally, objections by the original registrant will
+   carry extra weight in forming such a consensus.
+
+   Registrations are permanent and stable.  Once registered, subtags
+   will not be removed from the registry and will remain a valid way in
+   which to specify a specific language or variant.
+
+   Note: The purpose of the "Description" in the registration form is to
+   aid people trying to verify whether a language is registered or what
+   language or language variation a particular subtag refers to.  In
+   most cases, reference to an authoritative grammar or dictionary of
+   that language will be useful; in cases where no such work exists,
+   other well-known works describing that language or in that language
+   MAY be appropriate.  The Language Subtag Reviewer decides what
+   constitutes "good enough" reference material.  This requirement is
+   not intended to exclude particular languages or dialects due to the
+   size of the speaker population or lack of a standardized orthography.
+   Minority languages will be considered equally on their own merits.
+
+3.6.  Possibilities for Registration
+
+   Possibilities for registration of subtags or information about
+   subtags include:
+
+   o  Primary language subtags for languages not listed in ISO 639 that
+      are not variants of any listed or registered language MAY be
+      registered.  At the time this document was created, there were no
+      examples of this form of subtag.  Before attempting to register a
+      language subtag, there MUST be an attempt to register the language
+      with ISO 639.  Subtags MUST NOT be registered for codes that exist
+      in ISO 639-1 or ISO 639-2, that are under consideration by the ISO
+      639 maintenance or registration authorities, or that have never
+      been attempted for registration with those authorities.  If ISO
+      639 has previously rejected a language for registration, it is
+      reasonable to assume that there must be additional, very
+      compelling evidence of need before it will be registered in the
+      IANA registry (to the extent that it is very unlikely that any
+      subtags will be registered of this type).
+
+   o  Dialect or other divisions or variations within a language, its
+      orthography, writing system, regional or historical usage,
+      transliteration or other transformation, or distinguishing
+      variation MAY be registered as variant subtags.  An example is the
+      'rozaj' subtag (the Resian dialect of Slovenian).
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 32]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   o  The addition or maintenance of fields (generally of an
+      informational nature) in Tag or Subtag records as described in
+      Section 3.1 and subject to the stability provisions in
+      Section 3.4.  This includes descriptions, comments, deprecation
+      and preferred values for obsolete or withdrawn codes, or the
+      addition of script or extlang information to primary language
+      subtags.
+
+   o  The addition of records and related field value changes necessary
+      to reflect assignments made by ISO 639, ISO 15924, ISO 3166, and
+      UN M.49 as described in Section 3.4.
+
+   Subtags proposed for registration that would cause all or part of a
+   grandfathered tag to become redundant but whose meaning conflicts
+   with or alters the meaning of the grandfathered tag MUST be rejected.
+
+   This document leaves the decision on what subtags or changes to
+   subtags are appropriate (or not) to the registration process
+   described in Section 3.5.
+
+   Note: four-character primary language subtags are reserved to allow
+   for the possibility of alpha4 codes in some future addition to the
+   ISO 639 family of standards.
+
+   ISO 639 defines a maintenance agency for additions to and changes in
+   the list of languages in ISO 639.  This agency is:
+
+   International Information Centre for Terminology (Infoterm)
+   Aichholzgasse 6/12, AT-1120
+   Wien, Austria
+   Phone: +43 1 26 75 35 Ext. 312 Fax: +43 1 216 32 72
+
+   ISO 639-2 defines a maintenance agency for additions to and changes
+   in the list of languages in ISO 639-2.  This agency is:
+
+   Library of Congress
+   Network Development and MARC Standards Office
+   Washington, D.C. 20540 USA
+   Phone: +1 202 707 6237 Fax: +1 202 707 0115
+   URL: http://www.loc.gov/standards/iso639-2
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 33]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The maintenance agency for ISO 3166 (country codes) is:
+
+   ISO 3166 Maintenance Agency
+   c/o International Organization for Standardization
+   Case postale 56
+   CH-1211 Geneva 20 Switzerland
+   Phone: +41 22 749 72 33 Fax: +41 22 749 73 49
+   URL: http://www.iso.org/iso/en/prods-services/iso3166ma/index.html
+
+   The registration authority for ISO 15924 (script codes) is:
+
+   Unicode Consortium Box 391476
+   Mountain View, CA 94039-1476, USA
+   URL: http://www.unicode.org/iso15924
+
+   The Statistics Division of the United Nations Secretariat maintains
+   the Standard Country or Area Codes for Statistical Use and can be
+   reached at:
+
+   Statistical Services Branch
+   Statistics Division
+   United Nations, Room DC2-1620
+   New York, NY 10017, USA
+
+   Fax: +1-212-963-0623
+   E-mail: statistics@un.org
+   URL: http://unstats.un.org/unsd/methods/m49/m49alpha.htm
+
+3.7.  Extensions and Extensions Registry
+
+   Extension subtags are those introduced by single-character subtags
+   ("singletons") other than 'x'.  They are reserved for the generation
+   of identifiers that contain a language component and are compatible
+   with applications that understand language tags.
+
+   The structure and form of extensions are defined by this document so
+   that implementations can be created that are forward compatible with
+   applications that might be created using singletons in the future.
+   In addition, defining a mechanism for maintaining singletons will
+   lend stability to this document by reducing the likely need for
+   future revisions or updates.
+
+   Single-character subtags are assigned by IANA using the "IETF
+   Consensus" policy defined by [RFC2434].  This policy requires the
+   development of an RFC, which SHALL define the name, purpose,
+   processes, and procedures for maintaining the subtags.  The
+   maintaining or registering authority, including name, contact email,
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 34]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   discussion list email, and URL location of the registry, MUST be
+   indicated clearly in the RFC.  The RFC MUST specify or include each
+   of the following:
+
+   o  The specification MUST reference the specific version or revision
+      of this document that governs its creation and MUST reference this
+      section of this document.
+
+   o  The specification and all subtags defined by the specification
+      MUST follow the ABNF and other rules for the formation of tags and
+      subtags as defined in this document.  In particular, it MUST
+      specify that case is not significant and that subtags MUST NOT
+      exceed eight characters in length.
+
+   o  The specification MUST specify a canonical representation.
+
+   o  The specification of valid subtags MUST be available over the
+      Internet and at no cost.
+
+   o  The specification MUST be in the public domain or available via a
+      royalty-free license acceptable to the IETF and specified in the
+      RFC.
+
+   o  The specification MUST be versioned, and each version of the
+      specification MUST be numbered, dated, and stable.
+
+   o  The specification MUST be stable.  That is, extension subtags,
+      once defined by a specification, MUST NOT be retracted or change
+      in meaning in any substantial way.
+
+   o  The specification MUST include in a separate section the
+      registration form reproduced in this section (below) to be used in
+      registering the extension upon publication as an RFC.
+
+   o  IANA MUST be informed of changes to the contact information and
+      URL for the specification.
+
+   IANA will maintain a registry of allocated single-character
+   (singleton) subtags.  This registry MUST use the record-jar format
+   described by the ABNF in Section 3.1.  Upon publication of an
+   extension as an RFC, the maintaining authority defined in the RFC
+   MUST forward this registration form to iesg@ietf.org, who MUST
+   forward the request to iana@iana.org.  The maintaining authority of
+   the extension MUST maintain the accuracy of the record by sending an
+   updated full copy of the record to iana@iana.org with the subject
+   line "LANGUAGE TAG EXTENSION UPDATE" whenever content changes.  Only
+   the 'Comments', 'Contact_Email', 'Mailing_List', and 'URL' fields MAY
+   be modified in these updates.
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 35]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   Failure to maintain this record, maintain the corresponding registry,
+   or meet other conditions imposed by this section of this document MAY
+   be appealed to the IESG [RFC2028] under the same rules as other IETF
+   decisions (see [RFC2026]) and MAY result in the authority to maintain
+   the extension being withdrawn or reassigned by the IESG.
+
+   %%
+   Identifier:
+   Description:
+   Comments:
+   Added:
+   RFC:
+   Authority:
+   Contact_Email:
+   Mailing_List:
+   URL:
+   %%
+
+    Figure 6: Format of Records in the Language Tag Extensions Registry
+
+   'Identifier' contains the single-character subtag (singleton)
+   assigned to the extension.  The Internet-Draft submitted to define
+   the extension SHOULD specify which letter or digit to use, although
+   the IESG MAY change the assignment when approving the RFC.
+
+   'Description' contains the name and description of the extension.
+
+   'Comments' is an OPTIONAL field and MAY contain a broader description
+   of the extension.
+
+   'Added' contains the date the RFC was published in the "full-date"
+   format specified in [RFC3339].  For example: 2004-06-28 represents
+   June 28, 2004, in the Gregorian calendar.
+
+   'RFC' contains the RFC number assigned to the extension.
+
+   'Authority' contains the name of the maintaining authority for the
+   extension.
+
+   'Contact_Email' contains the email address used to contact the
+   maintaining authority.
+
+   'Mailing_List' contains the URL or subscription email address of the
+   mailing list used by the maintaining authority.
+
+   'URL' contains the URL of the registry for this extension.
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 36]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The determination of whether an Internet-Draft meets the above
+   conditions and the decision to grant or withhold such authority rests
+   solely with the IESG and is subject to the normal review and appeals
+   process associated with the RFC process.
+
+   Extension authors are strongly cautioned that many (including most
+   well-formed) processors will be unaware of any special relationships
+   or meaning inherent in the order of extension subtags.  Extension
+   authors SHOULD avoid subtag relationships or canonicalization
+   mechanisms that interfere with matching or with length restrictions
+   that sometimes exist in common protocols where the extension is used.
+   In particular, applications MAY truncate the subtags in doing
+   matching or in fitting into limited lengths, so it is RECOMMENDED
+   that the most significant information be in the most significant
+   (left-most) subtags and that the specification gracefully handle
+   truncated subtags.
+
+   When a language tag is to be used in a specific, known, protocol, it
+   is RECOMMENDED that the language tag not contain extensions not
+   supported by that protocol.  In addition, note that some protocols
+   MAY impose upper limits on the length of the strings used to store or
+   transport the language tag.
+
+3.8.  Initialization of the Registries
+
+   Upon adoption of this document, an initial version of the Language
+   Subtag Registry containing the various subtags initially valid in a
+   language tag is necessary.  This collection of subtags, along with a
+   description of the process used to create it, is described by
+   [RFC4645].  IANA SHALL publish the initial version of the registry
+   described by this document from the content of [RFC4645].  Once
+   published by IANA, the maintenance procedures, rules, and
+   registration processes described in this document will be available
+   for new registrations or updates.
+
+   Registrations that are in process under the rules defined in
+   [RFC3066] when this document is adopted MAY be completed under the
+   former rules, at the discretion of the Language Tag Reviewer (as
+   described in [RFC3066]).  Until the IESG officially appoints a
+   Language Subtag Reviewer, the existing Language Tag Reviewer SHALL
+   serve as the Language Subtag Reviewer.
+
+   Any new registrations submitted using the RFC 3066 forms or format
+   after the adoption of this document and publication of the registry
+   by IANA MUST be rejected.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 37]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   An initial version of the Language Tag Extensions Registry described
+   in Section 3.7 is also needed.  The Language Tag Extensions Registry
+   SHALL be initialized with a single record containing a single field
+   of type "File-Date" as a placeholder for future assignments.
+
+4.  Formation and Processing of Language Tags
+
+   This section addresses how to use the information in the registry
+   with the tag syntax to choose, form, and process language tags.
+
+4.1.  Choice of Language Tag
+
+   One is sometimes faced with the choice between several possible tags
+   for the same body of text.
+
+   Interoperability is best served when all users use the same language
+   tag in order to represent the same language.  If an application has
+   requirements that make the rules here inapplicable, then that
+   application risks damaging interoperability.  It is strongly
+   RECOMMENDED that users not define their own rules for language tag
+   choice.
+
+   Subtags SHOULD only be used where they add useful distinguishing
+   information; extraneous subtags interfere with the meaning,
+   understanding, and processing of language tags.  In particular, users
+   and implementations SHOULD follow the 'Prefix' and 'Suppress-Script'
+   fields in the registry (defined in Section 3.1): these fields provide
+   guidance on when specific additional subtags SHOULD (and SHOULD NOT)
+   be used in a language tag.
+
+   Of particular note, many applications can benefit from the use of
+   script subtags in language tags, as long as the use is consistent for
+   a given context.  Script subtags were not formally defined in RFC
+   3066 and their use can affect matching and subtag identification by
+   implementations of RFC 3066, as these subtags appear between the
+   primary language and region subtags.  For example, if a user requests
+   content in an implementation of Section 2.5 of [RFC3066] using the
+   language range "en-US", content labeled "en-Latn-US" will not match
+   the request.  Therefore, it is important to know when script subtags
+   will customarily be used and when they ought not be used.  In the
+   registry, the Suppress-Script field helps ensure greater
+   compatibility between the language tags generated according to the
+   rules in this document and language tags and tag processors or
+   consumers based on RFC 3066 by defining when users SHOULD NOT include
+   a script subtag with a particular primary language subtag.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 38]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   Extended language subtags (type 'extlang' in the registry; see
+   Section 3.1) also appear between the primary language and region
+   subtags and are reserved for future standardization.  Applications
+   might benefit from their judicious use in forming language tags in
+   the future.  Similar recommendations are expected to apply to their
+   use as apply to script subtags.
+
+   Standards, protocols, and applications that reference this document
+   normatively but apply different rules to the ones given in this
+   section MUST specify how the procedure varies from the one given
+   here.
+
+   The choice of subtags used to form a language tag SHOULD be guided by
+   the following rules:
+
+   1.  Use as precise a tag as possible, but no more specific than is
+       justified.  Avoid using subtags that are not important for
+       distinguishing content in an application.
+
+       *  For example, 'de' might suffice for tagging an email written
+          in German, while "de-CH-1996" is probably unnecessarily
+          precise for such a task.
+
+   2.  The script subtag SHOULD NOT be used to form language tags unless
+       the script adds some distinguishing information to the tag.  The
+       field 'Suppress-Script' in the primary language record in the
+       registry indicates which script subtags do not add distinguishing
+       information for most applications.
+
+       *  For example, the subtag 'Latn' should not be used with the
+          primary language 'en' because nearly all English documents are
+          written in the Latin script and it adds no distinguishing
+          information.  However, if a document were written in English
+          mixing Latin script with another script such as Braille
+          ('Brai'), then it might be appropriate to choose to indicate
+          both scripts to aid in content selection, such as the
+          application of a style sheet.
+
+   3.  If a tag or subtag has a 'Preferred-Value' field in its registry
+       entry, then the value of that field SHOULD be used to form the
+       language tag in preference to the tag or subtag in which the
+       preferred value appears.
+
+       *  For example, use 'he' for Hebrew in preference to 'iw'.
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 39]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   4.  The 'und' (Undetermined) primary language subtag SHOULD NOT be
+       used to label content, even if the language is unknown.  Omitting
+       the language tag altogether is preferred to using a tag with a
+       primary language subtag of 'und'.  The 'und' subtag MAY be useful
+       for protocols that require a language tag to be provided.  The
+       'und' subtag MAY also be useful when matching language tags in
+       certain situations.
+
+   5.  The 'mul' (Multiple) primary language subtag SHOULD NOT be used
+       whenever the protocol allows the separate tags for multiple
+       languages, as is the case for the Content-Language header in
+       HTTP.  The 'mul' subtag conveys little useful information:
+       content in multiple languages SHOULD individually tag the
+       languages where they appear or otherwise indicate the actual
+       language in preference to the 'mul' subtag.
+
+   6.  The same variant subtag SHOULD NOT be used more than once within
+       a language tag.
+
+       *  For example, do not use "de-DE-1901-1901".
+
+   To ensure consistent backward compatibility, this document contains
+   several provisions to account for potential instability in the
+   standards used to define the subtags that make up language tags.
+   These provisions mean that no language tag created under the rules in
+   this document will become obsolete.
+
+4.2.  Meaning of the Language Tag
+
+   The relationship between the tag and the information it relates to is
+   defined by the context in which the tag appears.  Accordingly, this
+   section gives only possible examples of its usage.
+
+   o  For a single information object, the associated language tags
+      might be interpreted as the set of languages that is necessary for
+      a complete comprehension of the complete object.  Example: Plain
+      text documents.
+
+   o  For an aggregation of information objects, the associated language
+      tags could be taken as the set of languages used inside components
+      of that aggregation.  Examples: Document stores and libraries.
+
+   o  For information objects whose purpose is to provide alternatives,
+      the associated language tags could be regarded as a hint that the
+      content is provided in several languages and that one has to
+      inspect each of the alternatives in order to find its language or
+      languages.  In this case, the presence of multiple tags might not
+      mean that one needs to be multi-lingual to get complete
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 40]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+      understanding of the document.  Example: MIME multipart/
+      alternative.
+
+   o  In markup languages, such as HTML and XML, language information
+      can be added to each part of the document identified by the markup
+      structure (including the whole document itself).  For example, one
+      could write <span lang="fr">C'est la vie.</span> inside a
+      Norwegian document; the Norwegian-speaking user could then access
+      a French-Norwegian dictionary to find out what the marked section
+      meant.  If the user were listening to that document through a
+      speech synthesis interface, this formation could be used to signal
+      the synthesizer to appropriately apply French text-to-speech
+      pronunciation rules to that span of text, instead of applying the
+      inappropriate Norwegian rules.
+
+   Language tags are related when they contain a similar sequence of
+   subtags.  For example, if a language tag B contains language tag A as
+   a prefix, then B is typically "narrower" or "more specific" than A.
+   Thus, "zh-Hant-TW" is more specific than "zh-Hant".
+
+   This relationship is not guaranteed in all cases: specifically,
+   languages that begin with the same sequence of subtags are NOT
+   guaranteed to be mutually intelligible, although they might be.  For
+   example, the tag "az" shares a prefix with both "az-Latn"
+   (Azerbaijani written using the Latin script) and "az-Cyrl"
+   (Azerbaijani written using the Cyrillic script).  A person fluent in
+   one script might not be able to read the other, even though the text
+   might be identical.  Content tagged as "az" most probably is written
+   in just one script and thus might not be intelligible to a reader
+   familiar with the other script.
+
+4.3.  Length Considerations
+
+   [RFC3066] did not provide an upper limit on the size of language
+   tags.  While RFC 3066 did define the semantics of particular subtags
+   in such a way that most language tags consisted of language and
+   region subtags with a combined total length of up to six characters,
+   larger registered tags were not only possible but were actually
+   registered.
+
+   Neither the language tag syntax nor other requirements in this
+   document impose a fixed upper limit on the number of subtags in a
+   language tag (and thus an upper bound on the size of a tag).  The
+   language tag syntax suggests that, depending on the specific
+   language, more subtags (and thus a longer tag) are sometimes
+   necessary to completely identify the language for certain
+   applications; thus, it is possible to envision long or complex subtag
+   sequences.
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 41]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+4.3.1.  Working with Limited Buffer Sizes
+
+   Some applications and protocols are forced to allocate fixed buffer
+   sizes or otherwise limit the length of a language tag.  A conformant
+   implementation or specification MAY refuse to support the storage of
+   language tags that exceed a specified length.  Any such limitation
+   SHOULD be clearly documented, and such documentation SHOULD include
+   what happens to longer tags (for example, whether an error value is
+   generated or the language tag is truncated).  A protocol that allows
+   tags to be truncated at an arbitrary limit, without giving any
+   indication of what that limit is, has the potential for causing harm
+   by changing the meaning of tags in substantial ways.
+
+   In practice, most language tags do not require more than a few
+   subtags and will not approach reasonably sized buffer limitations;
+   see Section 4.1.
+
+   Some specifications or protocols have limits on tag length but do not
+   have a fixed length limitation.  For example, [RFC2231] has no
+   explicit length limitation: the length available for the language tag
+   is constrained by the length of other header components (such as the
+   charset's name) coupled with the 76-character limit in [RFC2047].
+   Thus, the "limit" might be 50 or more characters, but it could
+   potentially be quite small.
+
+   The considerations for assigning a buffer limit are:
+
+      Implementations SHOULD NOT truncate language tags unless the
+      meaning of the tag is purposefully being changed, or unless the
+      tag does not fit into a limited buffer size specified by a
+      protocol for storage or transmission.
+
+      Implementations SHOULD warn the user when a tag is truncated since
+      truncation changes the semantic meaning of the tag.
+
+      Implementations of protocols or specifications that are space
+      constrained but do not have a fixed limit SHOULD use the longest
+      possible tag in preference to truncation.
+
+      Protocols or specifications that specify limited buffer sizes for
+      language tags MUST allow for language tags of up to 33 characters.
+
+      Protocols or specifications that specify limited buffer sizes for
+      language tags SHOULD allow for language tags of at least 42
+      characters.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 42]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The following illustration shows how the 42-character recommendation
+   was derived.  The combination of language and extended language
+   subtags was chosen for future compatibility.  At up to 15 characters,
+   this combination is longer than the longest possible primary language
+   subtag (8 characters):
+
+   language      =  3 (ISO 639-2; ISO 639-1 requires 2)
+   extlang1      =  4 (each subsequent subtag includes '-')
+   extlang2      =  4 (unlikely: needs prefix="language-extlang1")
+   extlang3      =  4 (extremely unlikely)
+   script        =  5 (if not suppressed: see Section 4.1)
+   region        =  4 (UN M.49; ISO 3166 requires 3)
+   variant1      =  9 (MUST have language as a prefix)
+   variant2      =  9 (MUST have language-variant1 as a prefix)
+
+   total         = 42 characters
+
+              Figure 7: Derivation of the Limit on Tag Length
+
+4.3.2.  Truncation of Language Tags
+
+   Truncation of a language tag alters the meaning of the tag, and thus
+   SHOULD be avoided.  However, truncation of language tags is sometimes
+   necessary due to limited buffer sizes.  Such truncation MUST NOT
+   permit a subtag to be chopped off in the middle or the formation of
+   invalid tags (for example, one ending with the "-" character).
+
+   This means that applications or protocols that truncate tags MUST do
+   so by progressively removing subtags along with their preceding "-"
+   from the right side of the language tag until the tag is short enough
+   for the given buffer.  If the resulting tag ends with a single-
+   character subtag, that subtag and its preceding "-" MUST also be
+   removed.  For example:
+
+   Tag to truncate: zh-Latn-CN-variant1-a-extend1-x-wadegile-private1
+   1. zh-Latn-CN-variant1-a-extend1-x-wadegile
+   2. zh-Latn-CN-variant1-a-extend1
+   3. zh-Latn-CN-variant1
+   4. zh-Latn-CN
+   5. zh-Latn
+   6. zh
+
+                    Figure 8: Example of Tag Truncation
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 43]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+4.4.  Canonicalization of Language Tags
+
+   Since a particular language tag is sometimes used by many processes,
+   language tags SHOULD always be created or generated in a canonical
+   form.
+
+   A language tag is in canonical form when:
+
+   1.  The tag is well-formed according the rules in Section 2.1 and
+       Section 2.2.
+
+   2.  Subtags of type 'Region' that have a Preferred-Value mapping in
+       the IANA registry (see Section 3.1) SHOULD be replaced with their
+       mapped value.  Note: In rare cases, the mapped value will also
+       have a Preferred-Value.
+
+   3.  Redundant or grandfathered tags that have a Preferred-Value
+       mapping in the IANA registry (see Section 3.1) MUST be replaced
+       with their mapped value.  These items either are deprecated
+       mappings created before the adoption of this document (such as
+       the mapping of "no-nyn" to "nn" or "i-klingon" to "tlh") or are
+       the result of later registrations or additions to this document
+       (for example, "zh-guoyu" might be mapped to a language-extlang
+       combination such as "zh-cmn" by some future update of this
+       document).
+
+   4.  Other subtags that have a Preferred-Value mapping in the IANA
+       registry (see Section 3.1) MUST be replaced with their mapped
+       value.  These items consist entirely of clerical corrections to
+       ISO 639-1 in which the deprecated subtags have been maintained
+       for compatibility purposes.
+
+   5.  If more than one extension subtag sequence exists, the extension
+       sequences are ordered into case-insensitive ASCII order by
+       singleton subtag.
+
+   Example: The language tag "en-A-aaa-B-ccc-bbb-x-xyz" is in canonical
+   form, while "en-B-ccc-bbb-A-aaa-X-xyz" is well-formed but not in
+   canonical form.
+
+   Example: The language tag "en-BU" (English as used in Burma) is not
+   canonical because the 'BU' subtag has a canonical mapping to 'MM'
+   (Myanmar), although the tag "en-BU" maintains its validity.
+
+   Canonicalization of language tags does not imply anything about the
+   use of upper or lowercase letters when processing or comparing
+   subtags (and as described in Section 2.1).  All comparisons MUST be
+   performed in a case-insensitive manner.
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 44]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   When performing canonicalization of language tags, processors MAY
+   regularize the case of the subtags (that is, this process is
+   OPTIONAL), following the case used in the registry.  Note that this
+   corresponds to the following casing rules: uppercase all non-initial
+   two-letter subtags; titlecase all non-initial four-letter subtags;
+   lowercase everything else.
+
+   Note: Case folding of ASCII letters in certain locales, unless
+   carefully handled, sometimes produces non-ASCII character values.
+   The Unicode Character Database file "SpecialCasing.txt" defines the
+   specific cases that are known to cause problems with this.  In
+   particular, the letter 'i' (U+0069) in Turkish and Azerbaijani is
+   uppercased to U+0130 (LATIN CAPITAL LETTER I WITH DOT ABOVE).
+   Implementers SHOULD specify a locale-neutral casing operation to
+   ensure that case folding of subtags does not produce this value,
+   which is illegal in language tags.  For example, if one were to
+   uppercase the region subtag 'in' using Turkish locale rules, the
+   sequence U+0130 U+004E would result instead of the expected 'IN'.
+
+   Note: if the field 'Deprecated' appears in a registry record without
+   an accompanying 'Preferred-Value' field, then that tag or subtag is
+   deprecated without a replacement.  Validating processors SHOULD NOT
+   generate tags that include these values, although the values are
+   canonical when they appear in a language tag.
+
+   An extension MUST define any relationships that exist between the
+   various subtags in the extension and thus MAY define an alternate
+   canonicalization scheme for the extension's subtags.  Extensions MAY
+   define how the order of the extension's subtags are interpreted.  For
+   example, an extension could define that its subtags are in canonical
+   order when the subtags are placed into ASCII order: that is,
+   "en-a-aaa-bbb-ccc" instead of "en-a-ccc-bbb-aaa".  Another extension
+   might define that the order of the subtags influences their semantic
+   meaning (so that "en-b-ccc-bbb-aaa" has a different value from
+   "en-b-aaa-bbb-ccc").  However, extension specifications SHOULD be
+   designed so that they are tolerant of the typical processes described
+   in Section 3.7.
+
+4.5.  Considerations for Private Use Subtags
+
+   Private use subtags, like all other subtags, MUST conform to the
+   format and content constraints in the ABNF.  Private use subtags have
+   no meaning outside the private agreement between the parties that
+   intend to use or exchange language tags that employ them.  The same
+   subtags MAY be used with a different meaning under a separate private
+   agreement.  They SHOULD NOT be used where alternatives exist and
+   SHOULD NOT be used in content or protocols intended for general use.
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 45]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   Private use subtags are simply useless for information exchange
+   without prior arrangement.  The value and semantic meaning of private
+   use tags and of the subtags used within such a language tag are not
+   defined by this document.
+
+   Subtags defined in the IANA registry as having a specific private use
+   meaning convey more information that a purely private use tag
+   prefixed by the singleton subtag 'x'.  For applications, this
+   additional information MAY be useful.
+
+   For example, the region subtags 'AA', 'ZZ', and in the ranges
+   'QM'-'QZ' and 'XA'-'XZ' (derived from ISO 3166 private use codes) MAY
+   be used to form a language tag.  A tag such as "zh-Hans-XQ" conveys a
+   great deal of public, interchangeable information about the language
+   material (that it is Chinese in the simplified Chinese script and is
+   suitable for some geographic region 'XQ').  While the precise
+   geographic region is not known outside of private agreement, the tag
+   conveys far more information than an opaque tag such as "x-someLang",
+   which contains no information about the language subtag or script
+   subtag outside of the private agreement.
+
+   However, in some cases content tagged with private use subtags MAY
+   interact with other systems in a different and possibly unsuitable
+   manner compared to tags that use opaque, privately defined subtags,
+   so the choice of the best approach sometimes depends on the
+   particular domain in question.
+
+5.  IANA Considerations
+
+   This section deals with the processes and requirements necessary for
+   IANA to undertake to maintain the subtag and extension registries as
+   defined by this document and in accordance with the requirements of
+   [RFC2434].
+
+   The impact on the IANA maintainers of the two registries defined by
+   this document will be a small increase in the frequency of new
+   entries or updates.
+
+5.1.  Language Subtag Registry
+
+   Upon adoption of this document, the registry will be initialized by a
+   companion document: [RFC4645].  The criteria and process for
+   selecting the initial set of records are described in that document.
+   The initial set of records represents no impact on IANA, since the
+   work to create it will be performed externally.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 46]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The new registry MUST be listed under "Language Tags" at
+   <http://www.iana.org/numbers.html>, replacing the existing
+   registrations defined by [RFC3066].  The existing set of registration
+   forms and RFC 3066 registrations MUST be relabeled as "Language Tags
+   (Obsolete)" and maintained (but not added to or modified).
+
+   Future work on the Language Subtag Registry SHALL be limited to
+   inserting or replacing whole records preformatted for IANA by the
+   Language Subtag Reviewer as described in Section 3.3 of this document
+   and archiving the forwarded registration form.
+
+   Each record MUST be sent to iana@iana.org with a subject line
+   indicating whether the enclosed record is an insertion of a new
+   record (indicated by the word "INSERT" in the subject line) or a
+   replacement of an existing record (indicated by the word "MODIFY" in
+   the subject line).  Records MUST NOT be deleted from the registry.
+   IANA MUST place any inserted or modified records into the appropriate
+   section of the language subtag registry, grouping the records by
+   their 'Type' field.  Inserted records MAY be placed anywhere in the
+   appropriate section; there is no guarantee of the order of the
+   records beyond grouping them together by 'Type'.  Modified records
+   MUST overwrite the record they replace.
+
+   Included in any request to insert or modify records MUST be a new
+   File-Date record.  This record MUST be placed first in the registry.
+   In the event that the File-Date record present in the registry has a
+   later date than the record being inserted or modified, the existing
+   record MUST be preserved.
+
+5.2.  Extensions Registry
+
+   The Language Tag Extensions Registry will also be generated and sent
+   to IANA as described in Section 3.7.  This registry can contain at
+   most 35 records, and thus changes to this registry are expected to be
+   very infrequent.
+
+   Future work by IANA on the Language Tag Extensions Registry is
+   limited to two cases.  First, the IESG MAY request that new records
+   be inserted into this registry from time to time.  These requests
+   MUST include the record to insert in the exact format described in
+   Section 3.7.  In addition, there MAY be occasional requests from the
+   maintaining authority for a specific extension to update the contact
+   information or URLs in the record.  These requests MUST include the
+   complete, updated record.  IANA is not responsible for validating the
+   information provided, only that it is properly formatted.  It should
+   reasonably be seen to come from the maintaining authority named in
+   the record present in the registry.
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 47]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+6.  Security Considerations
+
+   Language tags used in content negotiation, like any other information
+   exchanged on the Internet, might be a source of concern because they
+   might be used to infer the nationality of the sender, and thus
+   identify potential targets for surveillance.
+
+   This is a special case of the general problem that anything sent is
+   visible to the receiving party and possibly to third parties as well.
+   It is useful to be aware that such concerns can exist in some cases.
+
+   The evaluation of the exact magnitude of the threat, and any possible
+   countermeasures, is left to each application protocol (see BCP 72
+   [RFC3552] for best current practice guidance on security threats and
+   defenses).
+
+   The language tag associated with a particular information item is of
+   no consequence whatsoever in determining whether that content might
+   contain possible homographs.  The fact that a text is tagged as being
+   in one language or using a particular script subtag provides no
+   assurance whatsoever that it does not contain characters from scripts
+   other than the one(s) associated with or specified by that language
+   tag.
+
+   Since there is no limit to the number of variant, private use, and
+   extension subtags, and consequently no limit on the possible length
+   of a tag, implementations need to guard against buffer overflow
+   attacks.  See Section 4.3 for details on language tag truncation,
+   which can occur as a consequence of defenses against buffer overflow.
+
+   Although the specification of valid subtags for an extension (see
+   Section 3.7) MUST be available over the Internet, implementations
+   SHOULD NOT mechanically depend on it being always accessible, to
+   prevent denial-of-service attacks.
+
+7.  Character Set Considerations
+
+   The syntax in this document requires that language tags use only the
+   characters A-Z, a-z, 0-9, and HYPHEN-MINUS, which are present in most
+   character sets, so the composition of language tags should not have
+   any character set issues.
+
+   Rendering of characters based on the content of a language tag is not
+   addressed in this memo.  Historically, some languages have relied on
+   the use of specific character sets or other information in order to
+   infer how a specific character should be rendered (notably this
+   applies to language- and culture-specific variations of Han
+   ideographs as used in Japanese, Chinese, and Korean).  When language
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 48]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   tags are applied to spans of text, rendering engines sometimes use
+   that information in deciding which font to use in the absence of
+   other information, particularly where languages with distinct writing
+   traditions use the same characters.
+
+8.  Changes from RFC 3066
+
+   The main goals for this revision of language tags were the following:
+
+   *Compatibility.* All RFC 3066 language tags (including those in the
+   IANA registry) remain valid in this specification.  The changes in
+   this document represent additional constraints on language tags.
+   That is, in no case is the syntax more permissive and processors
+   based on the ABNF and other provisions of RFC 3066 (such as those
+   described in [XMLSchema]) will be able to process the tags described
+   by this document.  In addition, this document defines language tags
+   in such as way as to ensure future compatibility.
+
+   *Stability.* Because of changes in the past in the underlying ISO
+   standards, a valid RFC 3066 language tag could become invalid or have
+   its meaning change.  This has the potential of invalidating content
+   that may have an extensive shelf-life.  In this specification, once a
+   language tag is valid, it remains valid forever.
+
+   *Validity.* The structure of language tags defined by this document
+   makes it possible to determine if a particular tag is well-formed
+   without regard for the actual content or "meaning" of the tag as a
+   whole.  This is important because the registry grows and underlying
+   standards change over time.  In addition, it must be possible to
+   determine if a tag is valid (or not) for a given point in time in
+   order to provide reproducible, testable results.  This process must
+   not be error-prone; otherwise implementations might give different
+   results.  By having an authoritative registry with specific
+   versioning information, the validity of language tags at any point in
+   time can be precisely determined (instead of interpolating values
+   from many separate sources).
+
+   *Utility.* It is sometimes important to be able to differentiate
+   between written forms of a language -- for many implementations this
+   is more important than distinguishing between the spoken variants of
+   a language.  Languages are written in a wide variety of different
+   scripts, so this document provides for the generative use of ISO
+   15924 script codes.  Like the generative use of ISO language and
+   country codes in RFC 3066, this allows combinations to be produced
+   without resorting to the registration process.  The addition of UN
+   M.49 codes provides for the generation of language tags with regional
+   scope, which is also required by some applications.
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 49]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The recast of the registry from containing whole language tags to
+   subtags is a key part of this.  An important feature of RFC 3066 was
+   that it allowed generative use of subtags.  This allows people to
+   meaningfully use generated tags, without the delays in registering
+   whole tags or the need to register all of the combinations that might
+   be useful.
+
+   The choice of placing the extended language and script subtags
+   between the primary language and region subtags was widely debated.
+   This design was chosen because the prevalent matching and content
+   negotiation schemes rely on the subtags being arranged in order of
+   increasing specificity.  That is, the subtags that mark a greater
+   barrier to mutual intelligibility appear left-most in a tag.  For
+   example, when selecting content written in Azerbaijani, the script
+   (Arabic, Cyrillic, or Latin) represents a greater barrier to
+   understanding than any regional variations (those associated with
+   Azerbaijan or Iran, for example).  Individuals who prefer documents
+   in a particular script, but can deal with the minor regional
+   differences, can therefore select appropriate content.  Applications
+   that do not deal with written content will continue to omit these
+   subtags.
+
+   *Extensibility.* Because of the widespread use of language tags, it
+   is disruptive to have periodic revisions of the core specification,
+   even in the face of demonstrated need.  The extension mechanism
+   provides for a way for independent RFCs to define extensions to
+   language tags.  These extensions have a very constrained, well-
+   defined structure that prevents extensions from interfering with
+   implementations of language tags defined in this document.
+
+   The document also anticipates features of ISO 639-3 with the addition
+   of the extended language subtags, as well as the possibility of other
+   ISO 639 parts becoming useful for the formation of language tags in
+   the future.
+
+   The use and definition of private use tags have also been modified,
+   to allow people to use private use subtags to extend or modify
+   defined tags and to move as much information as possible out of
+   private use and into the regular structure.
+
+   The goal for each of these modifications is to reduce or eliminate
+   the need for future revisions of this document.
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 50]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   The specific changes in this document to meet these goals are:
+
+   o  Defines the ABNF and rules for subtags so that the category of all
+      subtags can be determined without reference to the registry.
+
+   o  Adds the concept of well-formed vs. validating processors,
+      defining the rules by which an implementation can claim to be one
+      or the other.
+
+   o  Replaces the IANA language tag registry with a language subtag
+      registry that provides a complete list of valid subtags in the
+      IANA registry.  This allows for robust implementation and ease of
+      maintenance.  The language subtag registry becomes the canonical
+      source for forming language tags.
+
+   o  Provides a process that guarantees stability of language tags, by
+      handling reuse of values by ISO 639, ISO 15924, and ISO 3166 in
+      the event that they register a previously used value for a new
+      purpose.
+
+   o  Allows ISO 15924 script code subtags and allows them to be used
+      generatively.  Defines a method for indicating in the registry
+      when script subtags are necessary for a given language tag.
+
+   o  Adds the concept of a variant subtag and allows variants to be
+      used generatively.
+
+   o  Adds the ability to use a class of UN M.49 tags for supra-national
+      regions and to resolve conflicts in the assignment of ISO 3166
+      codes.
+
+   o  Defines the private use tags in ISO 639, ISO 15924, and ISO 3166
+      as the mechanism for creating private use language, script, and
+      region subtags, respectively.
+
+   o  Adds a well-defined extension mechanism.
+
+   o  Defines an extended language subtag, possibly for use with certain
+      anticipated features of ISO 639-3.
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 51]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+9.  References
+
+9.1.  Normative References
+
+   [ISO10646]     International Organization for Standardization,
+                  "ISO/IEC 10646:2003. Information technology --
+                  Universal Multiple-Octet Coded Character Set (UCS)",
+                  2003.
+
+   [ISO15924]     International Organization for Standardization, "ISO
+                  15924:2004. Information and documentation -- Codes for
+                  the representation of names of scripts", January 2004.
+
+   [ISO3166-1]    International Organization for Standardization, "ISO
+                  3166-1:1997. Codes for the representation of names of
+                  countries and their subdivisions -- Part 1: Country
+                  codes", 1997.
+
+   [ISO639-1]     International Organization for Standardization, "ISO
+                  639-1:2002. Codes for the representation of names of
+                  languages -- Part 1: Alpha-2 code", 2002.
+
+   [ISO639-2]     International Organization for Standardization, "ISO
+                  639-2:1998. Codes for the representation of names of
+                  languages -- Part 2: Alpha-3 code, first edition",
+                  1998.
+
+   [ISO646]       International Organization for Standardization,
+                  "ISO/IEC 646:1991, Information technology -- ISO 7-bit
+                  coded character set for information interchange.",
+                  1991.
+
+   [RFC2026]      Bradner, S., "The Internet Standards Process --
+                  Revision 3", BCP 9, RFC 2026, October 1996.
+
+   [RFC2028]      Hovey, R. and S. Bradner, "The Organizations Involved
+                  in the IETF Standards Process", BCP 11, RFC 2028,
+                  October 1996.
+
+   [RFC2119]      Bradner, S., "Key words for use in RFCs to Indicate
+                  Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [RFC2434]      Narten, T. and H. Alvestrand, "Guidelines for Writing
+                  an IANA Considerations Section in RFCs", BCP 26,
+                  RFC 2434, October 1998.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 52]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   [RFC2860]      Carpenter, B., Baker, F., and M. Roberts, "Memorandum
+                  of Understanding Concerning the Technical Work of the
+                  Internet Assigned Numbers Authority", RFC 2860,
+                  June 2000.
+
+   [RFC3339]      Klyne, G., Ed. and C. Newman, "Date and Time on the
+                  Internet: Timestamps", RFC 3339, July 2002.
+
+   [RFC4234]      Crocker, D., Ed. and P. Overell, "Augmented BNF for
+                  Syntax Specifications: ABNF", RFC 4234, October 2005.
+
+   [UN_M.49]      Statistics Division, United Nations, "Standard Country
+                  or Area Codes for Statistical Use", UN Standard
+                  Country or Area Codes for Statistical Use, Revision 4
+                  (United Nations publication, Sales No. 98.XVII.9,
+                  June 1999.
+
+9.2.  Informative References
+
+   [RFC1766]      Alvestrand, H., "Tags for the Identification of
+                  Languages", RFC 1766, March 1995.
+
+   [RFC2047]      Moore, K., "MIME (Multipurpose Internet Mail
+                  Extensions) Part Three: Message Header Extensions for
+                  Non-ASCII Text", RFC 2047, November 1996.
+
+   [RFC2231]      Freed, N. and K. Moore, "MIME Parameter Value and
+                  Encoded Word Extensions: Character Sets, Languages,
+                  and Continuations", RFC 2231, November 1997.
+
+   [RFC2781]      Hoffman, P. and F. Yergeau, "UTF-16, an encoding of
+                  ISO 10646", RFC 2781, February 2000.
+
+   [RFC3066]      Alvestrand, H., "Tags for the Identification of
+                  Languages", BCP 47, RFC 3066, January 2001.
+
+   [RFC3552]      Rescorla, E. and B. Korver, "Guidelines for Writing
+                  RFC Text on Security Considerations", BCP 72,
+                  RFC 3552, July 2003.
+
+   [RFC4645]      Ewell, D., Ed., "Initial Language Subtag Registry",
+                  RFC 4645, September 2006.
+
+   [RFC4647]      Phillips, A., Ed. and M. Davis, Ed., "Matching of
+                  Language Tags", BCP 47, RFC 4647, September 2006.
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 53]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   [Unicode]      Unicode Consortium, "The Unicode Standard, Version
+                  5.0", Boston, MA, Addison-Wesley, 2007. ISBN 0-321-
+                  48091-0.
+
+   [XML10]        Bray (et al), T., "Extensible Markup Language (XML)
+                  1.0", 02 2004.
+
+   [XMLSchema]    Biron, P., Ed. and A. Malhotra, Ed., "XML Schema Part
+                  2: Datatypes Second Edition", 10 2004, <
+                  http://www.w3.org/TR/xmlschema-2/>.
+
+   [iso639.prin]  ISO 639 Joint Advisory Committee, "ISO 639 Joint
+                  Advisory Committee:  Working principles for ISO 639
+                  maintenance", March 2000, <http://www.loc.gov/
+                  standards/iso639-2/iso639jac_n3r.html>.
+
+   [record-jar]   Raymond, E., "The Art of Unix Programming", 2003,
+                  <urn:isbn:0-13-142901-9>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 54]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+Appendix A.  Acknowledgements
+
+   Any list of contributors is bound to be incomplete; please regard the
+   following as only a selection from the group of people who have
+   contributed to make this document what it is today.
+
+   The contributors to RFC 3066 and RFC 1766, the precursors of this
+   document, made enormous contributions directly or indirectly to this
+   document and are generally responsible for the success of language
+   tags.
+
+   The following people (in alphabetical order) contributed to this
+   document or to RFCs 1766 and 3066:
+
+   Glenn Adams, Harald Tveit Alvestrand, Tim Berners-Lee, Marc Blanchet,
+   Nathaniel Borenstein, Karen Broome, Eric Brunner, Sean M. Burke, M.T.
+   Carrasco Benitez, Jeremy Carroll, John Clews, Jim Conklin, Peter
+   Constable, John Cowan, Mark Crispin, Dave Crocker, Elwyn Davies,
+   Martin Duerst, Frank Ellerman, Michael Everson, Doug Ewell, Ned
+   Freed, Tim Goodwin, Dirk-Willem van Gulik, Marion Gunn, Joel Halpren,
+   Elliotte Rusty Harold, Paul Hoffman, Scott Hollenbeck, Richard
+   Ishida, Olle Jarnefors, Kent Karlsson, John Klensin, Erkki
+   Kolehmainen, Alain LaBonte, Eric Mader, Ira McDonald, Keith Moore,
+   Chris Newman, Masataka Ohta, Dylan Pierce, Randy Presuhn, George
+   Rhoten, Felix Sasaki, Markus Scherer, Keld Jorn Simonsen, Thierry
+   Sourbier, Otto Stolz, Tex Texin, Andrea Vine, Rhys Weatherley, Misha
+   Wolf, Francois Yergeau and many, many others.
+
+   Very special thanks must go to Harald Tveit Alvestrand, who
+   originated RFCs 1766 and 3066, and without whom this document would
+   not have been possible.  Special thanks must go to Michael Everson,
+   who has served as Language Tag Reviewer for almost the complete
+   period since the publication of RFC 1766.  Special thanks to Doug
+   Ewell, for his production of the first complete subtag registry, and
+   his work in producing a test parser for verifying language tags.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 55]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+Appendix B.  Examples of Language Tags (Informative)
+
+   Simple language subtag:
+
+      de (German)
+
+      fr (French)
+
+      ja (Japanese)
+
+      i-enochian (example of a grandfathered tag)
+
+   Language subtag plus Script subtag:
+
+      zh-Hant (Chinese written using the Traditional Chinese script)
+
+      zh-Hans (Chinese written using the Simplified Chinese script)
+
+      sr-Cyrl (Serbian written using the Cyrillic script)
+
+      sr-Latn (Serbian written using the Latin script)
+
+   Language-Script-Region:
+
+      zh-Hans-CN (Chinese written using the Simplified script as used in
+      mainland China)
+
+      sr-Latn-CS (Serbian written using the Latin script as used in
+      Serbia and Montenegro)
+
+   Language-Variant:
+
+      sl-rozaj (Resian dialect of Slovenian
+
+      sl-nedis (Nadiza dialect of Slovenian)
+
+   Language-Region-Variant:
+
+      de-CH-1901 (German as used in Switzerland using the 1901 variant
+      [orthography])
+
+      sl-IT-nedis (Slovenian as used in Italy, Nadiza dialect)
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 56]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+   Language-Script-Region-Variant:
+
+      sl-Latn-IT-nedis (Nadiza dialect of Slovenian written using the
+      Latin script as used in Italy.  Note that this tag is NOT
+      RECOMMENDED because subtag 'sl' has a Suppress-Script value of
+      'Latn')
+
+   Language-Region:
+
+      de-DE (German for Germany)
+
+      en-US (English as used in the United States)
+
+      es-419 (Spanish appropriate for the Latin America and Caribbean
+      region using the UN region code)
+
+   Private use subtags:
+
+      de-CH-x-phonebk
+
+      az-Arab-x-AZE-derbend
+
+   Extended language subtags (examples ONLY: extended languages MUST be
+   defined by revision or update to this document):
+
+      zh-min
+
+      zh-min-nan-Hant-CN
+
+   Private use registry values:
+
+      x-whatever (private use using the singleton 'x')
+
+      qaa-Qaaa-QM-x-southern (all private tags)
+
+      de-Qaaa (German, with a private script)
+
+      sr-Latn-QM (Serbian, Latin-script, private region)
+
+      sr-Qaaa-CS (Serbian, private script, for Serbia and Montenegro)
+
+   Tags that use extensions (examples ONLY: extensions MUST be defined
+   by revision or update to this document or by RFC):
+
+      en-US-u-islamCal
+
+      zh-CN-a-myExt-x-private
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 57]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+      en-a-myExt-b-another
+
+   Some Invalid Tags:
+
+      de-419-DE (two region tags)
+
+      a-DE (use of a single-character subtag in primary position; note
+      that there are a few grandfathered tags that start with "i-" that
+      are valid)
+
+      ar-a-aaa-b-bbb-a-ccc (two extensions with same single-letter
+      prefix)
+
+Authors' Addresses
+
+   Addison Phillips (Editor)
+   Yahoo! Inc.
+
+   EMail: addison@inter-locale.com
+
+
+   Mark Davis (Editor)
+   Google
+
+   EMail: mark.davis@macchiato.com or mark.davis@google.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 58]
+\f
+RFC 4646             Tags for Identifying Languages       September 2006
+
+
+Full Copyright Statement
+
+   Copyright (C) The Internet Society (2006).
+
+   This document is subject to the rights, licenses and restrictions
+   contained in BCP 78, and except as set forth therein, the authors
+   retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+   ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+   INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at
+   ietf-ipr@ietf.org.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is provided by the IETF
+   Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Phillips & Davis         Best Current Practice                 [Page 59]
+\f
index f0b18081377fa47135f7f552a23c9ead5731ba16..32aa60e0e317726dfeb6cdaf286c07a7a0676d02 100644 (file)
@@ -44,12 +44,13 @@ lpoptions.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
 lpoptions.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 lpoptions.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
 lpoptions.o: ../cups/transcode.h
-lppasswd.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
-lppasswd.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-lppasswd.o: ../cups/file.h ../cups/language.h ../cups/i18n.h
-lppasswd.o: ../cups/transcode.h ../cups/md5.h
-lpstat.o: ../cups/http-private.h ../config.h ../cups/http.h
-lpstat.o: ../cups/versioning.h ../cups/md5.h ../cups/ipp-private.h
-lpstat.o: ../cups/ipp.h ../cups/string.h ../cups/cups.h ../cups/ppd.h
-lpstat.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/i18n.h
-lpstat.o: ../cups/transcode.h ../cups/debug.h
+lppasswd.o: ../cups/globals.h ../cups/string.h ../config.h
+lppasswd.o: ../cups/http-private.h ../cups/http.h ../cups/versioning.h
+lppasswd.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+lppasswd.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+lppasswd.o: ../cups/i18n.h ../cups/transcode.h ../cups/md5.h
+lpstat.o: ../cups/globals.h ../cups/string.h ../config.h
+lpstat.o: ../cups/http-private.h ../cups/http.h ../cups/versioning.h
+lpstat.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+lpstat.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+lpstat.o: ../cups/i18n.h ../cups/transcode.h ../cups/debug.h
index 0df674a0ffe2f6dc3177df965a20384f8e0c35fc..ae5f5a06309062d29b3613b1b517c93615140ac8 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7929 2008-09-10 22:23:59Z mike $"
 #
-#   System V commands makefile for the Common UNIX Printing System (CUPS).
+#   System V commands makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -212,10 +212,10 @@ cupstestppd:      cupstestppd.o ../cups/$(LIBCUPS) ../filter/$(LIBCUPSIMAGE)
        echo Linking $@...
        $(CC) $(LDFLAGS) -o $@ cupstestppd.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
 
-cupstestppd-static:    cupstestppd.o ../cups/libcups.a ../filter/libcupsimage.a
+cupstestppd-static:    cupstestppd.o ../cups/$(LIBCUPSSTATIC) ../filter/libcupsimage.a
        echo Linking $@...
        $(CC) $(LDFLAGS) -o $@ cupstestppd.o ../filter/libcupsimage.a \
-               ../cups/libcups.a $(IMGLIBS) $(LIBGSSAPI) $(LIBS) $(LIBZ)
+               ../cups/$(LIBCUPSSTATIC) $(IMGLIBS) $(LIBGSSAPI) $(LIBS) $(LIBZ)
 
 
 #
index 5dfeb48a3110420878d442a5e9490927c64603cc..cd51014b5c96443963dbd7077a4edd5171ecd1fe 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: lppasswd.c 6649 2007-07-11 21:46:42Z mike $"
  *
- *   MD5 password program for the Common UNIX Printing System (CUPS).
+ *   MD5 password program for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -31,9 +31,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <cups/string.h>
-#include <cups/cups.h>
-#include <cups/i18n.h>
+#include <cups/globals.h>
 #include <cups/md5.h>
 
 #ifndef WIN32
@@ -79,7 +77,6 @@ main(int  argc,                               /* I - Number of command-line arguments */
                groupline[17],          /* Group from line */
                md5line[33],            /* MD5-sum from line */
                md5new[33];             /* New MD5 sum */
-  const char   *root;                  /* CUPS server root directory */
   char         passwdmd5[1024],        /* passwd.md5 file */
                passwdold[1024],        /* passwd.old file */
                passwdnew[1024];        /* passwd.tmp file */
@@ -88,12 +85,15 @@ main(int  argc,                             /* I - Number of command-line arguments */
   int          flag;                   /* Password check flags... */
   int          fd;                     /* Password file descriptor */
   int          error;                  /* Write error */
+  _cups_globals_t *cg = _cupsGlobals();        /* Global data */
+  cups_lang_t  *lang;                  /* Language info */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
   struct sigaction action;             /* Signal action */
 #endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
 
 
   _cupsSetLocale(argv);
+  lang = cupsLangDefault();
 
  /*
   * Check to see if stdin, stdout, and stderr are still open...
@@ -113,18 +113,11 @@ main(int  argc,                           /* I - Number of command-line arguments */
 
  /*
   * Find the server directory...
-  *
-  * We use the CUPS_SERVERROOT environment variable when we are running
-  * as root or when lppasswd is not setuid...
   */
 
-  if ((root = getenv("CUPS_SERVERROOT")) == NULL ||
-      (getuid() != geteuid() && getuid()))
-    root = CUPS_SERVERROOT;
-
-  snprintf(passwdmd5, sizeof(passwdmd5), "%s/passwd.md5", root);
-  snprintf(passwdold, sizeof(passwdold), "%s/passwd.old", root);
-  snprintf(passwdnew, sizeof(passwdnew), "%s/passwd.new", root);
+  snprintf(passwdmd5, sizeof(passwdmd5), "%s/passwd.md5", cg->cups_serverroot);
+  snprintf(passwdold, sizeof(passwdold), "%s/passwd.old", cg->cups_serverroot);
+  snprintf(passwdnew, sizeof(passwdnew), "%s/passwd.new", cg->cups_serverroot);
 
  /*
   * Find the default system group...
@@ -220,7 +213,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
   if (op != DELETE)
   {
-    if ((passwd = cupsGetPassword(_("Enter password:"))) == NULL)
+    if ((passwd = cupsGetPassword(
+            _cupsLangString(lang, _("Enter password:")))) == NULL)
       return (1);
 
     if ((newpass = strdup(passwd)) == NULL)
@@ -231,7 +225,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
       return (1);
     }
 
-    if ((passwd = cupsGetPassword(_("Enter password again:"))) == NULL)
+    if ((passwd = cupsGetPassword(
+            _cupsLangString(lang, _("Enter password again:")))) == NULL)
       return (1);
 
     if (strcmp(passwd, newpass) != 0)
index e98aaa70d749b0c7ee4ed57d34b444469911a90e..5f4e0b47af3cd12a15ddb32baa33bec392a8ebea 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: lpstat.c 7921 2008-09-10 15:42:24Z mike $"
  *
- *   "lpstat" command for the Common UNIX Printing System (CUPS).
+ *   "lpstat" command for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <cups/http-private.h>
-#include <cups/string.h>
-#include <cups/cups.h>
-#include <cups/i18n.h>
+#include <cups/globals.h>
 #include <cups/debug.h>
 
 
@@ -1518,7 +1515,7 @@ show_printers(const char  *printers,      /* I - Destinations */
   char         printer_uri[HTTP_MAX_URI],
                                        /* Printer URI */
                printer_state_time[255];/* Printer state time */
-  const char   *root;                  /* Server root directory... */
+  _cups_globals_t *cg = _cupsGlobals();        /* Global data */
   static const char *pattrs[] =                /* Attributes we need for printers... */
                {
                  "printer-name",
@@ -1543,9 +1540,6 @@ show_printers(const char  *printers,      /* I - Destinations */
   DEBUG_printf(("show_printers(printers=\"%s\", num_dests=%d, dests=%p, "
                 "long_status=%d)\n", printers, num_dests, dests, long_status));
 
-  if ((root = getenv("CUPS_SERVERROOT")) == NULL)
-    root = CUPS_SERVERROOT;
-
   if (printers != NULL && !strcmp(printers, "all"))
     printers = NULL;
 
@@ -1820,10 +1814,11 @@ show_printers(const char  *printers,    /* I - Destinations */
            if (make_model && strstr(make_model, "System V Printer"))
              _cupsLangPrintf(stdout,
                              _("\tInterface: %s/interfaces/%s\n"),
-                             root, printer);
+                             cg->cups_serverroot, printer);
            else if (make_model && !strstr(make_model, "Raw Printer"))
              _cupsLangPrintf(stdout,
-                             _("\tInterface: %s/ppd/%s.ppd\n"), root, printer);
+                             _("\tInterface: %s/ppd/%s.ppd\n"),
+                             cg->cups_serverroot, printer);
           }
          _cupsLangPuts(stdout, _("\tOn fault: no alert\n"));
          _cupsLangPuts(stdout, _("\tAfter fault: continue\n"));
@@ -1933,10 +1928,11 @@ show_printers(const char  *printers,    /* I - Destinations */
                if (make_model && strstr(make_model, "System V Printer"))
                  _cupsLangPrintf(stdout,
                                  _("\tInterface: %s/interfaces/%s\n"),
-                                 root, printer);
+                                 cg->cups_serverroot, printer);
                else if (make_model && !strstr(make_model, "Raw Printer"))
                  _cupsLangPrintf(stdout,
-                                 _("\tInterface: %s/ppd/%s.ppd\n"), root, printer);
+                                 _("\tInterface: %s/ppd/%s.ppd\n"),
+                                 cg->cups_serverroot, printer);
               }
              _cupsLangPuts(stdout, _("\tOn fault: no alert\n"));
              _cupsLangPuts(stdout, _("\tAfter fault: continue\n"));
index 0bb15f18df330d034a20ee7cb5cb4256d219b473..eaf52d73dcc8f3ffdfa16d96f52a68ab2df80f4d 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Add Class</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 7f375078a7a24f18bacc8df66b50b828a57ae906..361958b67474c56685100ac5ea3ad048702cfb4e 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Add Printer</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 810fb3a5028749c8abed93d7037f0557ce99569a..e0727835b40a04844aceabeaafa936ed6f8168e5 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">Add RSS Subscription</H2>
index bbf9db7cd55eb8993c1c1ad8ed0cb77c56734d45..da89d54e245a05f571ab57284c442c670a4d26ea 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Printers</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Add Printer"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Find New Printers"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Add Printer"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Find New Printers"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Manage Printers"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Export Printers to Samba"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Export Printers to Samba"></FORM>:}
 </P>
 
 <H2 CLASS="title">Classes</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Add Class"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Add Class"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Manage Classes"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Server</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Edit Configuration File"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Edit Configuration File"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="View Access Log"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="View Error Log"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="View Page Log"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Server Settings\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">RSS Subscriptions</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Add RSS Subscription"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Add RSS Subscription"></FORM>
 </P>
 
 </DIV>
index a4877ca637e3e3e543e3c4f9dbc8d9b45fd5366e..c5ab251b5478799ba9252e21965688ec88df0a88 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Add Printer}</H2>
 
 {CUPS_GET_DEVICES_DONE?<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index e2731dea3d4cc6d9609f456d94b626b14cbf3fc6..65096ad9a6773f9544922ead29448e253efcdff1 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Add Printer}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 33282fb15ac54ffd3124cb57a9d1fac04363a447..992cd01fd6806286702a809f22d4de3990580c02 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Add Printer}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index d714779b38b24c710b7ea251a163a6daa31b16bb..56a14a4cbfef1e954183a19031ef753dc55b9674 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Add Printer}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 907c02acab0dd4f9b8d97fcea2730c8a337a0429..e62ea1e13f6c09de306b0d814d37109c670497d6 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Add Printer}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index c14d354820edb60db9726aa2eea791c7112e8570..5f0277cb51387ed170b9dcd04db87a5c2a2d40b7 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Warning:</B> Are you sure you want to delete class
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Delete Class"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Delete Class"></FORM></P>
 
 </DIV>
index 535af64a693f9385b7740e55c6f70159bb7605ec..9987062d2ecec039b92a47e458144674fb704c46 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?Not:{printer_is_shared=0?Not:}} Shared{default_name={printer_name}?, Server Default:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Maintenance</OPTION>
 <OPTION VALUE="print-test-page">Print Test Page</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administration</OPTION>
index 019bdf2b2d3dd7d3f63e5f943215e294f0af3a3f..264a019bfaf2b403ac36c63d799698cf724f41f1 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">>Klasse hinzuf&uuml;gen</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 42d18fe0e7716f0b9a8fef2ffda5b5b2abeb58a9..15380b97bcbb42709491575af5355fa38b8c174d 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Drucker hinzuf&uuml;gen</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 264457de04a99a43093d0aa0a5cbb9818080d133..cef109ca9d80046cc4211f3805726a779dbb38db 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">>RSS Subskription hinzuf&uuml;gen</H2>
index a3445479cf7c109542bdf1f38e39cc910fba80a2..1ad1326918bfa27320abd770bceadf214ef24bb8 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Drucker</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Drucker hinzuf&uuml;gen"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Verf&uuml;gbare Drucker auflisten"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Drucker hinzuf&uuml;gen"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Verf&uuml;gbare Drucker auflisten"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Drucker verwalten"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Drucker f&uuml;r Samba freigeben"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Drucker f&uuml;r Samba freigeben"></FORM>:}
 </P>
 
 <H2 CLASS="title">Klassen</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Klasse hinzuf&uuml;gen"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Klasse hinzuf&uuml;gen"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Klassen verwalten"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Server</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Konfigurationsdatei bearbeiten"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Konfigurationsdatei bearbeiten"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Zugriffsprotokoll betrachten"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Fehlerprotokoll betrachten"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Seitenprotokoll betrachten"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Erweiterte Servereinstellungen\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">RSS Subskriptionen</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription hinzuf&uuml;gen"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription hinzuf&uuml;gen"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Name</TH><TH>Ereignis</TH><TH>Warteschlange</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription k&uuml;ndigen"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Alle Warteschlangen}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="RSS Subskription k&uuml;ndigen"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Alle Warteschlangen}</TD></TR>}
 </TBODY>
 </TABLE>:}
index c292f0a37b984b9277d471ae29ee24bf0099766f..3be8a350c1ac7db97278d0f05c21e840f62b696c 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Suche nach Druckern...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 96b32e309d3ed0c7578400cd6944eb801e28ebf4..6d572a6b26be74f3170d9d534ed41042b0c29302 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 0b651fcbbf6afe61f37c552f5ed62fff21095aa3..2f5bb18d888d99cdfe779bbe5424d18d829801a1 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
@@ -45,7 +46,7 @@ Diesen Drucker {?printer_is_shared=?nicht:{?printer_is_shared=0?nicht:}} freigeb
 </TD>
 </TR>
 <TR>
-<TH CLASS="label">>Oder stellen Sie eine PPD Datei bereit:</TH>
+<TH CLASS="label">Oder stellen Sie eine PPD Datei bereit:</TH>
 <TD><INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="262144"><INPUT
 TYPE="FILE" NAME="PPD_FILE"></TD>
 </TR>
index 7fab7ca9496040b2b39966aa0687af5d2936914f..a6f0044b551df2768f4407b7b2cd35fa349666db 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 6d2244f58ba99b17fb28fafcedbdbb14fb26e9dd..073b0d82472214bb821ef2bd85d5796b9e19352a 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name} &auml;ndern:Drucker hinzuf&uuml;gen}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index 20cd6db2d562baa87fb19156f4e2674569ecbe6d..5e0223cffd44a2e198abc1470bef3361568aafcb 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Warnung:</B> Sind Sie sicher, dass Sie die Klasse
 {printer_name} l&ouml;schen wollen?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Klasse l&ouml;schen"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Klasse l&ouml;schen"></FORM></P>
 
 </DIV>
index da72bc44ced22b681760b099fd80ea08b0c4bf59..a64a2daef553ce21a99fbddd5bcec4c013069ff2 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?Nicht:{printer_is_shared=0?Nicht:}} Freigegeben{default_name={printer_name}?, Standarddrucker:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Wartung</OPTION>
 <OPTION VALUE="print-test-page">Drucke Testseite</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administration</OPTION>
index 7439c98844487704c967195e60fc5c68c51414c1..f2913138b92f69030f307438c48a70a5171c5db4 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Konfigurationsdatei &auml;ndern</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 90cc98e7a75b0f82104bd069578a971cbd6fe72c..67c57dd31b76a2cbd1b46d0e8f2ba5befc86be83 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index 3a524bb58ff3752f05abf642d99a92954b2bb863..94a60b0aa7590bacb5d23556c1423efcca09c27d 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Auftrag neu drucken"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Auftrag freigeben"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Auftrag anhalten"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Auftrag l&ouml;schen"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Auftrag verschieben"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Auftrag verschieben"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 9ca2b53770d6b5bcd947f9fd7123810240651696..08a04522a8fabd9b16586e69ddef6b1f405258a1 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>Keine Drucker gefunden.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Diesen Drucker hinzuf&uuml;gen"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Diesen Drucker hinzuf&uuml;gen"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index 1db4a3fd59005af17236944c6c306f0e16f3cef1..2e0bae80dc6477a43220880899ca0048977d1352 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Klasse {printer_name} &auml;ndern</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index a44da2bea4434295d59f3242c38413e166241636..d128471d73243583740dee52d38957572c9d5bcb 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{printer_name} &auml;ndern</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 3bbe1fb344bff5a2b665b22eb93535618fa98243..030f6524ac18ad053266b90525bf33156f7b5727 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Warnung:</B> Sind Sie sicher, dass Sie den Drucker
 {printer_name} l&ouml;schen wollen?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Drucker l&ouml;schen"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Drucker l&ouml;schen"></FORM></P>
 
 </DIV>
index e3e1ebc4a53386b1956fde48c2f904f58a08c7c8..ffc58e91949ea0a01296abcb1e10bc4caf9f56bd 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?Nicht:{printer_is_shared=0?Nicht:}} freigegeben{default_name={printer_name}?, Standarddrucker:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Wartung</OPTION>
 <OPTION VALUE="print-test-page">Testseite drucken</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administration</OPTION>
index 1cb202b90522808f133f17dd21d965358282dd0f..ab2b0c60cb4ccacc8c8eb7c3ddf3782bffc25394 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Drucker f&uuml;r Samba freigeben</H2>
index b4187e3219ab7f60f809165bfc45d7f8d5a20935..75f9f4ff2c0acfd7ff8e384e4fff6f7e59f94a17 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Standardeinstellungen f&uuml;r {printer_name} festlegen</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Drucker nach Standardeinstellungen fragen">:}
index acb8892726cb80a265e24fb55064e2cb740fe67e..0704e87540b2fee13ad106aea587117eb89a11a4 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index ea45d81f5aeeff365a69e107f2c503dc18daa115..8947382b19b89f5ea1d9d16e826615221c74f679 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Edit Configuration File</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index bc2db61ed1b708dc61477d40c67a22fe76313117..f7e79fa8980126ef77aa94fdaa73f5919dc753ac 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">A&ntilde;adir clase</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 9e65a93b93bf2a335b952e00272a1cbebdd821cb..eedc3db40fea5afd8d518aba42460cd0690c72cf 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">A&ntilde;adir impresora</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 89d77ced6744745d2829f1cf09f813ae36b459c7..8fb7f3da0c14c4108d1684abe1f8838ec39050f4 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">A&ntilde;adir subscripci&oacute;n RSS</H2>
index 81a92ba18d4b35b1dd347624014fd99658284585..53e5d34d8bdad8bcb41a28b2aaf858ae874a2032 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Impresoras</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir impresora"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Encontrar nuevas impresoras"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir impresora"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Encontrar nuevas impresoras"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Administrar impresoras"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Exportar impresoras a Samba"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Exportar impresoras a Samba"></FORM>:}
 </P>
 
 <H2 CLASS="title">Clases</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir clase"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir clase"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Administrar clases"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Servidor</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Editar archivo configuraci&oacute;n"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Editar archivo configuraci&oacute;n"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Ver archivo de registro de accesos"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Ver archivo de registro de errores"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Ver archivo de registro de p&aacute;ginas"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Configuraci&oacute;n del servidor\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">Subscripciones RSS</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir subscripci&oacute;n RSS"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir subscripci&oacute;n RSS"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Nombre</TH><TH>Eventos</TH><TH>Nombre de la cola</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Cancelar subscripci&oacute;n RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Todas las colas}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Cancelar subscripci&oacute;n RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Todas las colas}</TD></TR>}
 </TBODY>
 </TABLE>:}
index 79ac4942d62bdac8f72e5449b372edfdef0d456c..9f314fdf662417a51f9e582801b9c113a40d36a8 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Buscando impresoras...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 370db237dabd749137e6736712b14d56eaa2da6b..c846de4df52f8186d64a4890479037a18a4cf2ab 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modificar {printer_name}:A&ntilde;adir impresora}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 8338da27d0385b6aab0e770fdda724da8feea516..497d4b1d1c2d9f8080eae0dacf573665d6bfaa26 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modificar {printer_name}:A&ntilde;adir impresora}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 513d0a20d9468c888665e7b91fd9c7a654b494bb..e296fb95f4d3897cfb92acb71cf220f141e0cfef 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modificar {printer_name}:A&ntilde;adir impresora}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index a7ff12d2cee16108a7b053723ab532440f7d9287..c02577395c8f0e365236eb8f7be1409ecb9c862d 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modificar {printer_name}:A&ntilde;adir impresora}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index f55f1c64b67989661a2920ac74884ef365654e21..a30ff726f1e7ca83188dd7e162eb1f357a8e4cac 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Advertencia:</B> &iquest;Est&aacute; seguro de querer borrar la clase
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Borrar clase"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Borrar clase"></FORM></P>
 
 </DIV>
index 9b511ae8714e43fafff0eb17e6697b15481ce9cc..f3704380bb71ec612fa7a3403081702c461a50f2 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?no:{printer_is_shared=0?no:}} compartida{default_name={printer_name}?, predeterminada del servidor:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Mantenimiento</OPTION>
 <OPTION VALUE="print-test-page">Imprimir p&aacute;gina de prueba</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administraci&oacute;n</OPTION>
index cfa4ac99e75d6d6eddfa791d37aef52050fb92b9..a0c663436a7b7aac9c148edb8c5e508b04de68b3 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Editar archivo de configuraci&oacute;n</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 30919df5d4291815b9a2fbce614c4d0d31e2e47c..e6aac39a59b14130c9e4aef665b877d6e4f74d0d 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index 26d1e7adf087c5086bb82cccbe1277f65523771a..e1bc195b5680d525e9ece0c2dda35995b1d9db52 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Reimprimir trabajo"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Liberar trabajo"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Retener trabajo"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Cancelar trabajo"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Mover trabajo"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Mover trabajo"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index b4ea626ad4706951b04dd95745bcaee0eda14eae..51e0eb98206f8f3093581077244b3440e546462f 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>No se encuentran impresoras.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir esta impresora"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="A&ntilde;adir esta impresora"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index 0dfb4736e894566bb1275caf55ced2aa6a8cc5d0..a50b2bb727805bd1da529a7e9466b6bb5e2f63b6 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modificar clase {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index 944a087bcc72e13268e96d8f748cb7321cf54f85..3c09da09e22ece281798543b7ceeaac42cc3bad2 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modificar {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index bd97f50d94ca207901a0a31860e636d817f2e294..1de104a6385bef715ac1074de3cdbe6cd65c2c59 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Advertencia:</B> &iquest;Est&aacute; seguro de querer borrar la impresora
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Borrar impresora"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Borrar impresora"></FORM></P>
 
 </DIV>
index 2a1ad09559910866031b5d99c3e89e92413da263..f7642ac0cddbe9aeea69a25269e9c1b82930c208 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?no:{printer_is_shared=0?no:}} compartida{default_name={printer_name}?, predeterminada del servidor:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Mantenimiento</OPTION>
 <OPTION VALUE="print-test-page">Imprimir p&aacute;gina de prueba</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administraci&oacute;n</OPTION>
index 8898f6e4fe5c7ad07e40a9ede6cd93f626146c24..0036372eded5c109af5db0c9aaafaac607153423 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Exportar impresoras a Samba</H2>
index fed45926d1db4877ec638c093dc788ab99e7fae4..8a2740b3be0af0e18ae478ea0a79d0dae8dbad07 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Establecer opciones predeterminadas de {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Consultar a la impresora las opciones predeterminadas">:}
index 1b308427857e558ba1204ac279c6b5789d53e925..a8a645e6f6d0ac2186eecf71a3bee64bbf425c50 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index a17ce98529458be799be9d477b58f77682cbec06..bd7436ae27f3f68991d3e3f20f4ab94dff93f625 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Gehitu klasea</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 853d052ffb5055e666b96d50bfe854741ecd3f3b..312da1e6eaa5891a46294533963863d5f24f92db 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Gehitu inprimagailua</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 01421c4553eae7cd4e055ccac663a31f7d66fcfa..b81b5b22f38bd56bbadff90151f5eba848413bd5 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">Gehitu RSS harpidetza</H2>
index 5f13fe21e905fefb047265569a43cb2d8fefa2f3..8b5ecddcbe162e2219bcab3a72db4db3d17b3fe3 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Inprimagailuak</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Gehitu inprimagailua"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Bilatu inprimagailu berriak"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Gehitu inprimagailua"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Bilatu inprimagailu berriak"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Kudeatu inprimagailuak"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Esportatu inprimagailuak Samba-ra"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Esportatu inprimagailuak Samba-ra"></FORM>:}
 </P>
 
 <H2 CLASS="title">Klaseak</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Gehitu klasea"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Gehitu klasea"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Kudeatu klaseak"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Zerbitzaria</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Editatu konfigurazioko fitxategia"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Editatu konfigurazioko fitxategia"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Ikusi atzipenen egunkaria"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Ikusi erroreen egunkaria"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Ikusi orrialdeen egunkaria"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Zerbitzariaren ezarpenak\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">RSS harpidetzak</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Gehitu RSS harpidetza"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Gehitu RSS harpidetza"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Izena</TH><TH>Gertaerak</TH><TH>Ilararen izena</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Utzi RSS harpidetza"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Ilara guztiak}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Utzi RSS harpidetza"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Ilara guztiak}</TD></TR>}
 </TBODY>
 </TABLE>:}
index e2e9b26b13a8f65969ba7de36d09b680c2afbdae..36b7b86b7c43faf22904e81318d29643880cb484 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Inprimagailuak bilatzen...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 4e61c1577444a04ac93f81fc03bd94692fecc5bc..9fb38976443f7e1384a8659ce53f8b978190f428 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Aldatu {printer_name}:Gehitu inprimagailua}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index d89fe8eabc29cf50cebf77a499fa78db8dff9a23..5824932b7ff9676f933b9d466d8c98ded4d5c04c 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Aldatu {printer_name}:Gehitu inprimagailua}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 1cea7c0b8948b687a305c29bff6b2cc2046227de..a4dbba2e53bf4674527d02639ce33443918dec6b 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Aldatu {printer_name}:Gehitu inprimagailua}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index dfecf4f71412826f3b8f2ea465fdea18ac69dec0..2c7d0f27028aab75129e30ff276379b9660f92fe 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Aldatu {printer_name}:Gehitu inprimagailua}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index 30e9be0c8bcaf73d797ba6f88f9e071e6284d48f..f4a1a6f4008ca5e7f7beb178df9f4af492325af7 100644 (file)
@@ -4,6 +4,6 @@
 
 <P><B>Abisua:</B> ziur zaude {printer_name} klasea ezabatu nahi duzula?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Ezabatu klasea"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Ezabatu klasea"></FORM></P>
 
 </DIV>
index d569f2049acaa84176e85f448746c5b4a2d6a01b..17e8c2694b1c5cc18f00c799eacd5172aff54daf 100644 (file)
@@ -5,6 +5,7 @@
 {default_name={printer_name}?, zerbitzariaren lehenetsiak:} partekatuta {server_is_sharing_printers=0?ez:{printer_is_shared=0?ez:}} daude)</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Mantenimendua</OPTION>
 <OPTION VALUE="print-test-page">Inprimatu probako orrialdea</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administrazioa</OPTION>
index b6760b4c0fc317614578fe79f87e86200e7e1b95..4b2ba7bca456f55dcd09e95f215c45dfacc05f3c 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Editatu konfigurazioko fitxategia</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index d1cb5e7f90657bf8becba61982987f05b7518670..f337353b288f8bccf319bc18321f4bc4a97b5393 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index 9aabce2d25f010ee135d7e0498bd03d7b6410244..3071f6d40b2e5b70211854bc267ea154eda31259 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Inprimatu berriro lana"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Askatu lana"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Eutsi lana"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Utzi lana"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Aldatu lana lekuz"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Aldatu lana lekuz"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 0431c8ac15b0456f6d6fd5578a15ea8fde41260e..c8a397f3e67d64c6c2a066bc5cb36543a32b34d6 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>Ez da inprimagailurik aurkitu.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Gehitu inprimagailu hau"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Gehitu inprimagailu hau"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index dfd1322eaa3b57534063787becda0e693d642fc6..bce650341e68792a20c76e590ad376c444b8b41b 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Aldatu {printer_name} klasea</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index 23f308b66e1aabb8743b1b5cd7d48db027b7ed97..9b0417a54935d80d98785ce6965ac828ed312337 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Aldatu {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 29ff12bccc511ca5457c7e053097918ff212ef8e..d72d24010affdfd83523a03ee6e5dad0776de5b3 100644 (file)
@@ -4,6 +4,6 @@
 
 <P><B>Abisua:</B> ziur zaude {printer_name} inprimagailua ezabatzea nahi duzula?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Ezabatu inprimagailua"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Ezabatu inprimagailua"></FORM></P>
 
 </DIV>
index e1ec7c7c9c44b1365921b212b73f739764ad70f6..ac984ebd044ea5945efcb2e980ebf7780eca66bc 100644 (file)
@@ -6,6 +6,7 @@
 {default_name={printer_name}?, Zerbitzariaren lehenetsia:} partekatuta {server_is_sharing_printers=0?ez:{printer_is_shared=0?ez:}} dago)</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Mantenimendua</OPTION>
 <OPTION VALUE="print-test-page">Inprimatu probako orrialdea</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administrazioa</OPTION>
index 6368c53f9753ea7ef4d25f3d8dfd2554afeafeb7..b6851f86b1fc6925976258ad014c05c98ae6218f 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Esportatu inprimagailuak Samba-ra</H2>
index d84e91c2d5544d87ee698fc66b3240b2898a684f..89b548b2f121c472e491542f78eb98c21d83a5d5 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Ezarri {printer_name}(r)en aukera lehenetsiak</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Kontsultatu inprimagailuaren aukera lehenetsiei buruz">:}
index fb4ef638d2c09f260e7b9fa55db1e1427d2269f4..ba0ee968b73f886ee0f122cec8a612828e2bce7a 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index b64af5d6c3f45233295100bffff09be590e16dc7..55f90ad2ea20042e201b920a54fedcf89ce8e886 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Tambah Kelas</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 92529565cc417de1dd9be1a093703a7dd62dbd0b..5c7c7ccdd9224c104690fe9d9b5c12ab1a1d636e 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Add Printer</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {?current_make!?<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE" VALUE="{current_make}">:}
 {?current_make_and_model!?<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{current_make_and_model}">:}
index ac9e3d40343d3db4fbf58c0a634a71df958c2057..3d5ae7d7075b27d2c244ed625c2427cf165f78d3 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">Tambah Subskripsi RSS</H2>
index d7ea6a62321ee54615ec68407ff3f07acf9d53a4..9106d6518aa07dfd480aa399b842068946b13aa8 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Pencetak</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Tambah Pencetak"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Cari Pencetak Baru"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Tambah Pencetak"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Cari Pencetak Baru"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Atur Pencetak"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Ekspor Pencetak ke Samba"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Ekspor Pencetak ke Samba"></FORM>:}
 </P>
 
 <H2 CLASS="title">Kelas</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Tambah Kelas"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Tambah Kelas"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Atur Kelas"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Server</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Sunting Berkas Konfigurasi"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Sunting Berkas Konfigurasi"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Lihat Log Akses"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Lihat Log Kesalahan"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Lihat Log Halaman"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Pengaturan Server\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">Subskripsi RSS</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Tambah Subskripsi RSS"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Tambah Subskripsi RSS"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Nama</TH><TH>Kejadian</TH><TH>Nama Antrian</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Cancel RSS Subscription"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Semua Antrian}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Cancel RSS Subscription"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Semua Antrian}</TD></TR>}
 </TBODY>
 </TABLE>:}
index 6bd91bd1498cd3faa245763d8c4429f9940c146d..8f812a5e41663f46cd82291150fa327e4f87817d 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Mencari pencetak...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 3362738def662d5e3d118d870fbbdbee946edf7d..d04338fcc650183db324f91f036f162cbdcaac43 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Ubah {printer_name}:Tambah Pencetak}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index d294a3b25589ee741086dae9ff28ed494e8c31d3..c4cfdb9d0e468c1bb9d6d77f4208aea980ebf86c 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Tambah Pencetak}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index ceb291f8f5bcb63234c812b5709c805c6e5149c3..19de16c4fdc75597b385bf7780efc4b93dc02d91 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Tambah Pencetak}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 57380f6c461af32b664c6a05d1fb66dd32084430..61dfdfe62f7dc3a498ebe830153fb0a26959771f 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Tambah Pencetak}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index 23bec54ffd96cd8c0fa27a270e53476663985741..3805b91771decbeb1d264f8127a9492efc31995d 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Peringatan:</B> Anda yakin untuk menghapus kelas
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Hapus Kelas"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Hapus Kelas"></FORM></P>
 
 </DIV>
index ab85b1f882712f342cc54c0ee1efe026b322ec2d..6cb78c99aa20509a8de6ca4c323888eeba55c699 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?Jangan:{printer_is_shared=0?Jangan:}} Berbagi{default_name={printer_name}?, Server Baku:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Perawatan</OPTION>
 <OPTION VALUE="print-test-page">Halaman Uji Cetak</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administrasi</OPTION>
index fde6c632f1511eff66996ab43d3d082400996153..6701f84ac48c98bafbc289cb9474160f416a32be 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Sunting Berkas Konfigurasi</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 91fdbc421558d2a18681980a0e20b134d0d5ca58..9ec881a04a8e9d42862dfbe2520be43ef588d58d 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index 5670d6d22a3bf92178415fbd5351d3aeb3279dd6..1cd13a0ec2ca0ce2d993af8fc518512fc17d4386 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
-<INPUT TYPE="SUBMIT" VALUE="Reprint Job"></FORM>:}:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}"><INPUT TYPE="SUBMIT" VALUE="Reprint Job"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Release Job"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Hold Job"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Cancel Job"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Move Job"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Move Job"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 3c8884c2b7042abed4eff071f165ab46171f26af..f3ca39fd9804346972f7cd889951f6be63cb1fcb 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>Tidak ada pencetak.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Tambah Pencetak Ini"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Tambah Pencetak Ini"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index ad8f3113a446c1a14e4da1f2cb4285da543e3dce..db2d65e26d0eefce484ab42219fe6aed52189f25 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Ubah Kelas {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index ffe1203dfe6e91148b86efa49781989addfb0626..9bdb0c4f14687fdeae2aa37f9033ada7dcbb874e 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Ubah {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index de668e7413cc6bbcf7e52828a22091aaa5b41539..e6d89d616bfa55c2ecb3bf081a16a087d611b0c4 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Peringatan:</B> Anda yakin untuk menghapus
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Hapus Pencetak"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Hapus Pencetak"></FORM></P>
 
 </DIV>
index 68e0a39811ba3da384b7c951478481603632c1a2..4c56b6761118a1374f5e9dc6788a5f1dd65cb649 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?Tidak:{printer_is_shared=0?Tidak:}} Berbagi{default_name={printer_name}?, Server Baku:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Perawatan</OPTION>
 <OPTION VALUE="print-test-page">Cetak Halaman Uji</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administrasi</OPTION>
index c42f7b6a3f837bb13423e6e7b0d9c262101a0487..4d9e17519dc941655ae9b3162798076d4aa3c17f 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Ekspor Pencetak ke Samba</H2>
index 12386dc29f5601d2ab033fea000edfa9830c167a..017e2c4757e0991dcd97770b40aea7e59b1c589f 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Atur Opsi Baku untuk {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Kuiri Pencetak untuk Opsi Baku">:}
index 3795d694a7415febf4ca7795de13b6404f8cc5b2..fe9107050ebff53dd32a4e4150270d533a07c628 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index 91130b02a3d95bd939a90567bda0ac8eb5a9d368..cff0d45bc5675e9829687453814d03c369a1c4fd 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Aggiungi classe</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index bfd208020d9b6d9a00d03002adcd0910f24180d4..3bf0906fa534330c8082dbdba2d66382af116c09 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Aggiungi stampante</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {?current_make!?<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE" VALUE="{current_make}">:}
 {?current_make_and_model!?<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{current_make_and_model}">:}
index 69f658b15dfd301eeff37e434dd868a097a96698..ba33c14fd4b24894e4a2ff5ac9fbdd35711ac6c6 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">Aggiungi iscrizione RSS</H2>
index 5ffa0019d6d49cd016169c4770cdd3fbbf6851c3..355c51fcc6cc0d0e158c1eaa7d86afd7a9ad4f75 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Stampanti</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Aggiungi stampante"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Trova nuove stampanti"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Aggiungi stampante"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Trova nuove stampanti"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Gestisci stampanti"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Esporta stampanti a Samba"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Esporta stampanti a Samba"></FORM>:}
 </P>
 
 <H2 CLASS="title">Classi</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Aggiungi classe"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Aggiungi classe"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Gestisci classi"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Server</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Modifica file di configurazione"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Modifica file di configurazione"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Mostra registro degli accessi"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Visualizza registro di errore"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Visualizza registro delle pagine"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Impostazioni del server\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">Iscrizioni RSS</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Aggiungi iscrizione RSS"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Aggiungi iscrizione RSS"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Nome</TH><TH>Eventi</TH><TH>Nome coda</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Annulla iscrizione RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Tutte le code}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Annulla iscrizione RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Tutte le code}</TD></TR>}
 </TBODY>
 </TABLE>:}
index f02a680fb0aeefc4a021cea0e2d94a70c2c80582..3420fdfe1ac3f1545c893a0ded75c697640dda8d 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Ricerca stampanti...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 12c596176931e017b38dd8e89c9acdf6eb5c366a..3bb4c78c4481cc2675c7468ffe54b525838fae5f 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Aggiungi stampante}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index aa9e0efea337ed1ad0a5ea16e1ec818a62715c3b..d7e935769925697ab047ddd28f16e769365640bd 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Aggiungi stampante}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index a17eb0574dacc4864b75324a17b74f5cd4017414..106393adb6b8ec8aa040bca62ef374f917e1f668 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modifica {printer_name}:Aggiungi stampante}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index fe4f8c3252728e6bdf38ac0420c351c96f3d4d40..8a4b68584193f2cdb7d4f8c0a845f8ee82d02924 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modifica {printer_name}:Aggiungi stampante}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index f05657f13935eac290281002c7fc14681460b223..4e99f4574258ae8597a04af6830cd36b542fa50e 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Warning:</B> Sei sicuro di voler eliminare la classe
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Elimina classe"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Elimina classe"></FORM></P>
 
 </DIV>
index fd5b3e83ba08c01084787135c4894070b1d1cfa5..06a768acf8ee756c18ad41220c4971c52713f7c8 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?Not:{printer_is_shared=0?Not:}} Shared{default_name={printer_name}?, Server Default:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Manutenzione</OPTION>
 <OPTION VALUE="print-test-page">Stampa pagina di prova</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Amministrazione</OPTION>
index 9568843dba22312b1be18fb6ab59b979b06d2db1..c8d8ea8a96cb3e30a89cc0df0e798720c0af166d 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Modifica file di configurazione</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 2ddc44a904672c4ca2197eef69752d447a77922c..0a52ba2f23c2f00d6040c3e5632ebac117196bef 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index 4c0ac244dc83d85f9a9539b1dd5ac7aa302d066a..494c1eebd3d3de1a208505075c13d5de030988ee 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Ripeti stampa"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Release Job"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Hold Job"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Annulla stampa"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Sposta stampa"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Sposta stampa"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 3245f59094c54a84dc11a08f7b265436dd490121..147d6103cff2d5dc813a44347981911b5a026bef 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>Nessuna stampante trovata.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Stampante locale"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Aggiungi stampante"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Stampante locale"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Aggiungi stampante"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index f6216954551771100c0b4a1f3700b70cc0d102cb..065f2b91abcb29de9a041062afcead09b80d8aa4 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modifica classe {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index 4d1c97b7f1f2ea6744f2d1546e14f122b127baa3..a6303f298381c17f5462d795e9a0cbb5698a61ec 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modifica {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index b9c009d800bdfcc3b759234a7a0c1be4f9c41d31..e23071c9f273068c422c4e40bd84a56dd49b030f 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Avviso:</B> Sei sicuro di voler eliminare la stampante
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Elimina stampante"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Elimina stampante"></FORM></P>
 
 </DIV>
index b7a38278e67daff60c03e997cc94ff5aba020849..78fc08beae30bb7a03275597afe45dd7bd67c190 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?Not:{printer_is_shared=0?Not:}} Shared{default_name={printer_name}?, Server Default:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Maintenance</OPTION>
 <OPTION VALUE="print-test-page">Print Test Page</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administration</OPTION>
index 5ac76ddedb36ee241dc784ebda620c5ba453ceca..bce7469d0dd40a36286247a1fe514dc891bc4bdc 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Esporta stampanti a Samba</H2>
index 735341c1618ebbcaab21d0b0f0f6ad4da571463d..b0867cedbc2a8f10a4584ba01bea06e5cdf3d8b9 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Imposta opzioni predefinite per {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Interroga stampante per opzioni predefinite">:}
index f547e414a5bf6a42b8c579c89d65f6c47b19108a..34d8adb10fdadd17b5d6304151d9a1733e3150aa 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index b40954fa4aec95415e87cd3344633c659b10708d..11108ccfe40863a25e8b2346aeadb837865b772e 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">クラスの追加</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index c984246790febbc081df07cf4898680d83d3fc73..f054254aa412df14018199ef1f320efb1f5bc787 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">新しいプリンターの追加</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index a2ba7538be92c3baf687d4078fa8438da517c990..70203c1f9a6ee9a2c3cb5aabfb10b1bcb9488cd0 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">RSS 購読を追加</H2>
index f2904cb44b9479b0d572c3fc96525b117812bbde..e1e0229518ad091fbaaf4dc41900e525938d7157 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">プリンター</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="プリンターの追加"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="新しいプリンターの検索"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="プリンターの追加"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="新しいプリンターの検索"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="プリンターの管理"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="プリンターを Samba にエクスポート"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="プリンターを Samba にエクスポート"></FORM>:}
 </P>
 
 <H2 CLASS="title">クラス</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="クラスの追加"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="クラスの追加"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="クラスの管理"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">サーバー</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="設定ファイルの編集"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="設定ファイルの編集"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="アクセスログの表示"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="エラーログの表示"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="ページログの表示"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>サーバー設定\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">RSS 購読</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="RSS 購読の追加"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="RSS 購読の追加"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>名前</TH><TH>イベント</TH><TH>キュー名</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="RSS 購読のキャンセル"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:すべてのキュー}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="RSS 購読のキャンセル"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:すべてのキュー}</TD></TR>}
 </TBODY>
 </TABLE>:}
index a4a8efa516262149e2c9ad1e47e032c68b9ceae1..05700c3c7c02543966ae1e70d77db10a42c78613 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> プリンターを探しています...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 0a1eb79bc60ab527e7164fdc7820482057f705bd..c800d9818bce025316958eef3e7bfaca78bcae54 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name}の変更:プリンターの追加}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 90d5cf45b225bfc1ebe2d33c82423516cb825858..20011b4d51ee643d1cf7eff979fb8e88db74ddb8 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name}の追加:プリンターの追加}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index c8c4542f4f634865085a542f696cf0821be16bb4..924b84a74a75c7a441d7f1ab03bbc00b89bb2122 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name}の変更:プリンターの追加}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 893da3ec1684057f9d8ee808bf05537dc163d32a..bc8c0bc0344a780b66189b89f702ed01b55ffb89 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?{printer_name}の変更:プリンターの追加}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index 20ff73f38d24b3bc3541b303e52de720b054ccd0..e50b6a90aeacb3b613a98a4b7f08740fb2df817c 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>警告:</B> 本当にクラス 
 {printer_name} を削除しても良いですか?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="クラスの削除"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="クラスの削除"></FORM></P>
 
 </DIV>
index 82b753d32a3d5f5a495be6cd3d8363925d609ca4..2ee45eea1f5871768c19e7e9f89f42c11284aa90 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?非:{printer_is_shared=0?非:}}共有{default_name={printer_name}?, デフォルトプリンター:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">メンテナンス</OPTION>
 <OPTION VALUE="print-test-page">テストページの印刷</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">管理</OPTION>
index 45d4eb40777ac1b4e7353cda5513f6db780223df..a05a55479ab1d5ddd7979536d9eb24683f3873eb 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">設定ファイルの設定</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 2acd2c51f6cdc8a85dc1abcac542038992557d5c..54da7e0387f813ebdf54807a293fb6788bf4d2ec 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index e0d917c2589a7d77c3a09f402ae611331c08c1e6..bff543aea21e858a988d2ca5ac625bc368c1d257 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="ジョブの再印刷"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="ジョブを解放"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="ジョブを保留"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="ジョブをキャンセル"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="ジョブを移動"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="ジョブを移動"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 554270ad6762553b9471e6dbf0fa85b394c9ea15..f70b5aac0d1de543538bded60413077ec01fd124 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>プリンターが見つかりません。</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="このプリンターを追加"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="このプリンターを追加"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index c5fe07d5e01597b123f5933b985cb2c6db0130b5..a41010f3f31f31e318079559559c01d73d6ed40a 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">クラス {printer_name} の変更</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index ff14b400be4d6a94a3ee93e2281a039896d0b9fa..d8ef5f04b5d7d3c1a8a97e787a6d008ca9a239ad 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">プリンター {printer_name} の変更</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index e6430b2cb3ef63f0ada625f19df9cd013e041a04..6fdb52cabcf8394cb386c105dd1ecc49d6190e23 100644 (file)
@@ -4,6 +4,6 @@
 
 <P><B>警告:</B> 本当にプリンター {printer_name} を削除してよいですか?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="プリンターの削除"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="プリンターの削除"></FORM></P>
 
 </DIV>
index 209abaa3ca75a4a89406371166f1aec89031b5be..fbd9c5ad0c425549b1e3c849509ba15105b1716b 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?非:{printer_is_shared=0?非:}}共有{default_name={printer_name}?, デフォルトプリンター:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">メンテナンス</OPTION>
 <OPTION VALUE="print-test-page">テストページの印刷</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">管理</OPTION>
index 2ecd36594743ccaa15eec3304713c6b7cbe1a4e0..74b7991e36c95c4153f2a9703134896998ab3653 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">プリンターを Samba にエクスポート</H2>
index dd8746104a3e27e39866f4efcb0b8961da4c55b2..b5896f071eac6fb700400805abfc09eacf78ff37 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{printer_name} のデフォルトオプション変更</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="プリンターにデフォルトオプションを問い合わせる">:}
index 8097cdc7a54bafdd14dc0dc5875837d4777b59fe..b998c6b2b916643f823237f88a039ec3da01e56a 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index 96b309006a209ecf47706da1dad6575045e7aef7..6ef0ff12e1ed31a1e148c1536b18dffeabb34bf9 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index 9e77556bf6ba19abf1a7253a98714150eb41cf9a..9c56b3f94d6d422cccfaee68310e88e63df5a3df 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
-<INPUT TYPE="SUBMIT" VALUE="Reprint Job"></FORM>:}:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}"><INPUT TYPE="SUBMIT" VALUE="Reprint Job"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Release Job"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Hold Job"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Cancel Job"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Move Job"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Move Job"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 8b325fdac3d9def4630059ac35031dbdcc29dee6..a594439ee3b68e3cf4bc02c9830f6aa84e87af7b 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>No printers found.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Add This Printer"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Local Printer"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Add This Printer"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index 6d2655463f805223b19f11c8c7ec397b31b27f99..31f7b9ce3c9fd02506f0cb911f3e88aba7c18914 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modify Class {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index f0a8ea8742739501618f7fe6070d349ab0c1e3c7..bdf3df60421d5dd58f9a46c5c2c4b7c46cb327da 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modify {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index af5c69ff17dc788bf8236ea1e0580a2a02639595..d1f4b66bf6474515f0634b3bb75673d02b443cbb 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Dodawanie klasy</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 9fa76ca625cb782893ce6e3d187c77e4da7308dc..45b50a0d4c128449f1df0f13132ce605b5dbf1bc 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Dodawanie drukarki</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 0523454b6026fe34aa1578f3a3d215065ae961b1..bff170705ec3a8dddc80c04380d36b95f57562cf 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">Dodawanie subskrypcji RSS</H2>
index 387f053609a6366c68e5b987ef81921b77693075..16840361fda10424a0123f2f7a98511fa5715111 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Drukarki</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Dodawanie drukarki"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Wyszukiwanie nowych drukarek"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Dodawanie drukarki"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Wyszukiwanie nowych drukarek"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Zarządzanie drukarkami"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Eksportowanie drukarek do Samby"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Eksportowanie drukarek do Samby"></FORM>:}
 </P>
 
 <H2 CLASS="title">Klasy</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Dodawanie klasy"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Dodawanie klasy"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Zarządzanie klasami"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Serwery</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Modyfikowanie pliku konfiguracji"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Modyfikowanie pliku konfiguracji"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Przeglądanie dziennika dostępu"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Przeglądanie dziennika błędów"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Przeglądanie dziennika stron"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Ustawienia serwera\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">Subskrypcje RSS</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Dodawanie subskrypcji RSS"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Dodawanie subskrypcji RSS"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Name</TH><TH>Zdarzenia</TH><TH>Nazwa kolejki</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Anuluj subskrypcję RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Wszystkie kolejki}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Anuluj subskrypcję RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Wszystkie kolejki}</TD></TR>}
 </TBODY>
 </TABLE>:}
index 7fc06ded4d336799d50719e748326c5f79002eb1..44574562449bd68b2aaf0173421240a655541674 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Wyszukiwanie drukarek...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index d632619d0078ac74952d0b03edbd1f7c4bd29a68..c0ec622a7a703b7625c83616e73f40f2f98916f9 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modify {printer_name}:Dodawanie drukarki}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 6a7cbb6720814d67ce17150fff887e16c6cc17da..9438cee567e2201fed94ca206c3735cf5b3b713f 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modyfikowanie {printer_name}:Dodawanie drukarki}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index 5c42b243407e7c3ee28c9539e467bd7f1aa21056..8bbf8c8c2f10bfa675eee79a4ca283802976a760 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modyfikowanie {printer_name}:Dodawanie drukarki}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 5c87dbbb21cc62c7da3e88deed8b7d3a7f7834a9..8d06e103a958b6c68c2ba4475892da8242db10da 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Modyfikowanie {printer_name}:Dodawanie drukarki}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index 7c38b894b94b9904b539dbcbd13d52643bb5a776..55cb5ed4e81d7d8a811a3c1c5d2544c62955cf8b 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Ostrzeżenie:</B> Usunąć klasę
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Usuń klasę"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Usuń klasę"></FORM></P>
 
 </DIV>
index 9ba9ff43187cd65cd3baf16e0dc6680de87d61f9..6d83981d09785bf346e95933a1fa023bd17225bf 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?Nie:{printer_is_shared=0?Nie:}} Współdzielona{default_name={printer_name}?, Domyślne serwera:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Konserwacja</OPTION>
 <OPTION VALUE="print-test-page">Drukowanie strony próbnej</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administracja</OPTION>
index 84c4359bd6be7b6f72bebea59e1d361d5313814b..3688ee24c0c740d722d24d23e2a2438d6f968ed4 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Modyfikowanie pliku konfiguracji</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 666a1509a4c999c224bf2b64ff5ff08cdc9059b8..bd77beeb2d7563ca3da2c50d861c0e919174bc04 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index dbb7fd9bb1878a1ab1032a03a9ea387a37232eb6..665bdffbdb355ca6dc0e0eaa07775d3905ea256f 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Ponownie wydrukuj zadanie"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Zwolnij zadanie"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Wstrzymaj zadanie"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Anuluj zadanie"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Przenieś zadanie"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Przenieś zadanie"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index d5ba1aa1306ecb41f31dee68440aadf3ececa6d4..aad6a49fa5c849b1751f3cc5918ee2b4e46fc45e 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>Nie znaleziono drukarek.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Lokalna drukarka"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Dodaj tę drukarkę"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Lokalna drukarka"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Dodaj tę drukarkę"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index 483cd060318aec6f8ba6035075e1a306874d2fe8..b8a2130763a9838ab08c61ee72b53bdd29716d0f 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modyfikowanie klasy {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index 30b2c14eceb7224199929707c8381d8edb065a8e..a63f4781c92d3efb9c52be5c9d801ee496b393f5 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Modyfikowanie {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 2e9ab7e41b9dbdf54145882c4a658cdf85bbafa0..73f86012853b2469442d2e99ba6cfa25edcdf3be 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Ostrzeżenie:</B> usunąć drukarkę
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Usuń drukarkę"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Usuń drukarkę"></FORM></P>
 
 </DIV>
index 43d18ef2db38459e1c74cab787a7da92cbea364e..c62b857a0bb45aa462d754e96f7b6efc6b36ed67 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?Nie:{printer_is_shared=0?Nie:}} Współdzielona{default_name={printer_name}?, Domyślne serwera:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Konserwacja</OPTION>
 <OPTION VALUE="print-test-page">Wydrukuj stronę próbną</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administracja</OPTION>
index c927c3bb5354595ddc91ea0aaa4fec15fc520aa3..691a30bb03e2f0ad038b7b4389c27963687f51b3 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Eksportowanie drukarek do Samby</H2>
index 206a5bbe7903311711f80826ff2a1c12a6f70dc9..d128d7d50328d4fbbb4f8326d594bf2ae8db2c8a 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Ustawianie domyślnych opcji dla {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Zakolejkuj drukarkę do domyślnych opcji">:}
index 7907c7abb696ae488d90741e2c6c330a9656a732..5cb7549521a12695be8cdeb7df7d3291a2d21102 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index db16d691b3e75bfaca34e058663fd68221c2e9d6..fce9e3494bca56376292bf61073f8d815e300079 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Warning:</B> Are you sure you want to delete printer
 {printer_name}?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Delete Printer"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Delete Printer"></FORM></P>
 
 </DIV>
index b7a38278e67daff60c03e997cc94ff5aba020849..78fc08beae30bb7a03275597afe45dd7bd67c190 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?Not:{printer_is_shared=0?Not:}} Shared{default_name={printer_name}?, Server Default:})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Maintenance</OPTION>
 <OPTION VALUE="print-test-page">Print Test Page</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Administration</OPTION>
index e0cadc4e04f83efe96a74b4c9b55626d6b91ba68..41a7f9868c87d622d80f0328b1b6b2c895fe6d11 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Новая группа</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 
 <TABLE>
index 59d6e21932dda6ce4c111f614c145a7b72029802..2d040189cae6e1531df1ed3a5b0a1efae2455eaf 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Добавление принтера</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 90e2c80ec1fec3e6ea922e80cb365753e5265c97..4c9925fb76583218a4a09e80bf1e9426700c2473 100644 (file)
@@ -1,4 +1,5 @@
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription">
 
 <H2 CLASS="title">Добавление подписки по RSS</H2>
index 9362f428c00650d03d23c61b20343ab96eda276f..22d9de064937d8793a59add034fa5157368c29f1 100644 (file)
@@ -4,16 +4,16 @@
 <H2 CLASS="title">Принтеры</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Добавить принтер"></FORM>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Найти новый принтер"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="SUBMIT" VALUE="Добавить принтер"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="find-new-printers"><INPUT TYPE="SUBMIT" VALUE="Найти новый принтер"></FORM>
 <FORM ACTION="/printers/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Управление принтерами"></FORM>
-{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Экспортировать принтер в Samba"></FORM>:}
+{have_samba?<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba"><INPUT TYPE="SUBMIT" VALUE="Экспортировать принтер в Samba"></FORM>:}
 </P>
 
 <H2 CLASS="title">Группы</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Добавить группу"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-class"><INPUT TYPE="SUBMIT" VALUE="Добавить группу"></FORM>
 <FORM ACTION="/classes/" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Управление группами"></FORM>
 </P>
 
@@ -28,7 +28,7 @@
 <H2 CLASS="title">Сервер</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Редактировать конфигурационный файл"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server"><INPUT TYPE="SUBMIT" VALUE="Редактировать конфигурационный файл"></FORM>
 <FORM ACTION="/admin/log/access_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Показать журнал заданий"></FORM>
 <FORM ACTION="/admin/log/error_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Показать журнал ошибок"></FORM>
 <FORM ACTION="/admin/log/page_log" METHOD="GET"><INPUT TYPE="SUBMIT" VALUE="Показать журнал страниц"></FORM>
@@ -38,6 +38,7 @@
 <BLOCKQUOTE>{SETTINGS_ERROR}</BLOCKQUOTE>:
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 
 {ADVANCEDSETTINGS?<P><B>Параметры сервера\:</B></P>
 
@@ -95,7 +96,7 @@
 <H2 CLASS="title">Подписка по RSS</H2>
 
 <P>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Добавить подписку по RSS"></FORM>
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-rss-subscription"><INPUT TYPE="SUBMIT" VALUE="Добавить подписку по RSS"></FORM>
 </P>
 
 </DIV>
 <THEAD><TR><TH>Название</TH><TH>События</TH><TH>Очередь</TH></TR></THEAD>
 <TBODY>{[notify_subscription_id]
 <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR>
-<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Отменить подписку по RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Все очереди}</TD></TR>}
+<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Отменить подписку по RSS"></FORM>&nbsp;</TD><TD>{notify_events}</TD><TD NOWRAP>&nbsp;{notify_printer_name?{notify_printer_name}:Все очереди}</TD></TR>}
 </TBODY>
 </TABLE>:}
index 0aee24f1d06705a565bbaeb6aa7f25a7a63c7b0b..3df36db86ab9dba5e0c20c206c911dc3be0490c5 100644 (file)
@@ -6,6 +6,7 @@
 ALT="Busy Indicator"> Поиск принтеров...</P>}
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index d400356f03767907aceffbe8d660bd05b50aa9bc..a87d6bf2765694106bc43515b5dd5ceff4a98d90 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Изменение {printer_name}:Добавление принтера}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index a6e2e0ef65b84bb47038e30fe6d6d08fc4857c46..9d434f1c37a583a8e4520a7625cf6d607559b40a 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Изменение {printer_name}:Добавление принтера}</H2>
 
 <FORM METHOD="POST" ACTION="/admin" ENCTYPE="multipart/form-data">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
index cba02600ac4001f73df6860811c1e7ab55085006..21e4bf87fadcaeeb1e28c8b85c77cf37485ca8b0 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Изменение {printer_name}:Добавление принтера}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 
index 3672f4428abe59864a9518a75d99f28d6c5d236f..812f2db8870c4ee8ad299db9224f9d90a5b13ae2 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">{op=modify-printer?Изменение {printer_name}:Добавление принтера}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {printer_name?<INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">:}
 <INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
index c4337ecdcd321e183b3fcd52643a68feff62dc39..5bef5bf07c3052cf8c85adf09f1c5653de967ff7 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Предупреждение:</B> вы действительно хотите удалить группу
 «{printer_name}»?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Удалить группу"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="op" VALUE="delete-class"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Удалить группу"></FORM></P>
 
 </DIV>
index 36e674a687d2aae953e77714724dec5684d805d7..d486b43e2724cad900c75c86aec5d884f13489ef 100644 (file)
@@ -5,6 +5,7 @@
 {server_is_sharing_printers=0?нет совместного доступа:{printer_is_shared=0?нет совместного доступа:разрешен совместный доступ}})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Обслуживание</OPTION>
 <OPTION VALUE="print-test-page">Печать пробной страницы</OPTION>
@@ -17,6 +18,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="Администрирование">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Администрирование</OPTION>
index f96d32f22730b3b712321f11695d3394126b61af..d194059d88bc92dfb21f8ea533b178860ae7cf9e 100644 (file)
@@ -10,7 +10,7 @@ function reset_config()
 <H2 CLASS="title">Редактирование конфигурационного файла</H2>
 
 <FORM NAME="cups" METHOD="POST" ACTION="/admin/">
-
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 
 <TEXTAREA NAME="CUPSDCONF" COLS="80" ROWS="25">{CUPSDCONF}</TEXTAREA>
index 69bfdeb5a163ca409d2d3651056493dd20818da2..598e4db7469aa33c6a78cb76dd5b6271b3b266c9 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/{SECTION}/{job_id?:{printer_name}}">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {job_id?<INPUT TYPE="HIDDEN" NAME="JOB_ID" VALUE="{job_id}">:}
 
index a94b1429fd26f397d46bc3e26c51249b2e880046..c2226f67e04393ac752417df2b5d111c1cc93d01 100644 (file)
 <EM>"{job_printer_state_message}"</EM>:}</TD>
 <TD>
 {job_preserved>0?{job_state>5?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="restart-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Перезапустить"></FORM>:}:}
 {job_state=4?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="release-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Продолжить"></FORM>:}
 {job_state=3?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="hold-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Приостановить"></FORM>:}
 {job_state<7?
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="HIDDEN" NAME="job_printer_uri" VALUE="{job_printer_uri}">
 <INPUT TYPE="SUBMIT" VALUE="Отменить"></FORM>
-<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Переместить"></FORM>:}
+<FORM ACTION="/jobs/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="move-job"><INPUT TYPE="HIDDEN" NAME="job_id" VALUE="{job_id}"><INPUT TYPE="SUBMIT" VALUE="Переместить"></FORM>:}
 &nbsp;</TD>
 </TR>
 }
index 72b6d445aaccf0d14d5883bc85cccbb61c402865..161562845718b012e2718a9360474e585abb7b8c 100644 (file)
@@ -4,7 +4,7 @@
 
 {#device_uri=0?<P>Не обнаружено ни одного принтера.</P>
 :<UL>{[device_uri]
-<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Сетевой принтер"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Добавить этот принтер"></FORM>
+<LI><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="add-printer"><INPUT TYPE="HIDDEN" NAME="TEMPLATE_NAME" VALUE="{template_name}"><INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="Сетевой принтер"><INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{device_make_and_model}"><INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}"><INPUT TYPE="SUBMIT" VALUE="Добавить этот принтер"></FORM>
 {device_make_and_model} ({device_info})</LI>
 }</UL>}
 
index d596c9b3fdfa14119399df154b6cef5497752dd3..a85698a52c511f04646f1e2e8070111671e598c0 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Изменение группы {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 
index 74ea27c3b1c724ac8b13aaee25963c6bcb0a2335..6277b5d6f296db98139a28ea5677309579f96777 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Изменение принтера {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 <INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
 <INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
index 6776a5742bc36d8eb63ad1f80e3ba89b3b58a034..c57356d07578f9eb45b207f713855a04b11c81f6 100644 (file)
@@ -5,6 +5,6 @@
 <P><B>Предупреждение:</B> вы действительно хотите удалить принтер
 «{printer_name}»?</P>
 
-<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Удалить принтер"></FORM></P>
+<P ALIGN="CENTER"><FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="delete-printer"><INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}"><INPUT TYPE="SUBMIT" NAME="confirm" VALUE="Удалить принтер"></FORM></P>
 
 </DIV>
index da4a0898d79a6fb7d16ec4ee52689087b893eb8c..5128d004c231cf97727f63f9ce398a868afe0373 100644 (file)
@@ -6,6 +6,7 @@
 {server_is_sharing_printers=0?нет совместного доступа:{printer_is_shared=0?нет совместного доступа:разрешен совместный доступ}})</H2>
 
 <FORM METHOD="POST" ACTION="{printer_uri_supported}" NAME="maintenance">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <SELECT NAME="OP" ONCHANGE="document.maintenance.submit();">
 <OPTION VALUE="">Обслуживание</OPTION>
 <OPTION VALUE="print-test-page">Печать пробной страницы</OPTION>
@@ -20,6 +21,7 @@
 </FORM>
 
 <FORM METHOD="POST" ACTION="{admin_uri}" NAME="administration">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="printer_name" VALUE="{printer_name}">
 <SELECT NAME="OP" ONCHANGE="document.administration.submit();">
 <OPTION VALUE="">Администрирование</OPTION>
index e39b75c0f674814c8280c13537540fe6a6608718..22a3acb151115b82681a98cae446a9875271d859 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Экспорт принтеров в Samba</H2>
index a250a9f5287e0f49f61d9588a0db95b3cd8cdcce..e5c79dd44a78e0b3fe61df98a403ffaf71d2143c 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Установить параметры по умолчанию для {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Запрос принтера для параметров по умолчанию">:}
index 12672a250758436469f467b0693f6a8f0529cc92..c5b357501fc86422e4f37857e790b224950bda40 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index 92a291f1e4946e2ba2fef1ef85028de52b3bff61..6515a4d3aef0284ceb0944d42972846ed31d296b 100644 (file)
@@ -10,6 +10,7 @@ function select_printers() {
 --></SCRIPT>
 
 <FORM METHOD="POST" ACTION="/admin/" NAME="export_samba">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="export-samba">
 
 <H2 CLASS="title">Export Printers to Samba</H2>
index 462bccf20cdfde9bfe3827fff43a81e807ff67b6..3e7db4669c8effb54fb7f8fc09d1ee257a6efcf9 100644 (file)
@@ -3,6 +3,7 @@
 <H2 CLASS="title">Set Default Options for {printer_name}</H2>
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
 {HAVE_AUTOCONFIGURE?<INPUT TYPE="SUBMIT" NAME="AUTOCONFIGURE" VALUE="Query Printer for Default Options">:}
index 5f9f71f8dea2294c98abb8b3532fdf5210a543e1..0889f3f31ecd8e824081482b11157ecaa8439594 100644 (file)
@@ -1,6 +1,7 @@
 <DIV CLASS="indent">
 
 <FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}">
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="{OP}">
 <INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
 {IS_CLASS?<INPUT TYPE="HIDDEN" NAME="IS_CLASS" VALUE="{IS_CLASS}">:}
index a395277e9fc1d822fe7f90f5d128a9bb87d920b9..266f7f2fe66a220cc6a230bc2ffa32c0e50a79cf 100644 (file)
@@ -1,6 +1,7 @@
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
-ipptest.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
-ipptest.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h ../cups/array.h
-ipptest.o: ../cups/file.h ../cups/language.h ../cups/language.h
-ipptest.o: ../cups/http-private.h ../cups/md5.h ../cups/ipp-private.h
+ipptest.o: ../cups/globals.h ../cups/string.h ../config.h
+ipptest.o: ../cups/http-private.h ../cups/http.h ../cups/versioning.h
+ipptest.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
+ipptest.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+ipptest.o: ../cups/i18n.h ../cups/transcode.h
index dfb00880133569d308400c3c1fba880850f525d5..60d72fcd5a059ccff568f78b484c71f21f0757c9 100644 (file)
@@ -1,9 +1,9 @@
 #
 # "$Id: Makefile 7871 2008-08-27 21:12:43Z mike $"
 #
-#   IPP test makefile for the Common UNIX Printing System (CUPS).
+#   IPP test makefile for CUPS.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2010 by Apple Inc.
 #   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
 include ../Makedefs
 
 
+#
+# Sample test files.
+#
+
+TESTFILES      =       \
+                       ipp-1.1.test \
+                       ipp-2.0.test \
+                       ipp-2.1.test \
+                       testfile.jpg \
+                       testfile.pdf \
+                       testfile.ps \
+                       testfile.txt
+
+
 #
 # Make all targets...
 #
 
-all:   ipptest
+all:   ipptest ipptest-static
 
 
 #
@@ -42,7 +56,7 @@ unittests:
 #
 
 clean:
-       $(RM) ipptest ipptest.o
+       $(RM) ipptest ipptest.o ipptest-static
 
 
 #
@@ -65,6 +79,11 @@ install:     all install-data install-headers install-libs install-exec
 #
 
 install-data:
+       echo Installing sample ipptest files in $(DATADIR)/ipptest...
+       $(INSTALL_DIR) -m 755 $(DATADIR)/ipptest
+       for file in $(TESTFILES); do \
+               $(INSTALL_DATA) $$file $(DATADIR)/ipptest; \
+       done
 
 
 #
@@ -72,6 +91,13 @@ install-data:
 #
 
 install-exec:
+       echo Installing ipptest in $(BINDIR)...
+       $(INSTALL_DIR) -m 755 $(BINDIR)
+       $(INSTALL_BIN) ipptest $(BINDIR)
+       if test "x$(SYMROOT)" != "x"; then \
+               $(INSTALL_DIR) $(SYMROOT); \
+               cp ipptest $(SYMROOT); \
+       fi
 
 
 #
@@ -99,9 +125,18 @@ uninstall:
 # ipptest
 #
 
-ipptest:       ipptest.o ../cups/libcups.a
+ipptest:       ipptest.o ../cups/$(LIBCUPS)
+       echo Linking $@...
+       $(CC) $(LDFLAGS) -o $@ ipptest.o $(LIBS)
+
+
+#
+# ipptest-static
+#
+
+ipptest-static:        ipptest.o ../cups/$(LIBCUPSSTATIC)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o ipptest ipptest.o  ../cups/libcups.a \
+       $(CC) $(LDFLAGS) -o $@ ipptest.o  ../cups/$(LIBCUPSSTATIC) \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
 
 
diff --git a/test/ipp-1.1.test b/test/ipp-1.1.test
new file mode 100644 (file)
index 0000000..bdc1fd6
--- /dev/null
@@ -0,0 +1,742 @@
+#
+# "$Id$"
+#
+#   IPP/1.1 test suite.
+#
+#   Copyright 2007-2010 by Apple Inc.
+#   Copyright 2001-2006 by Easy Software Products. All rights reserved.
+#
+#   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/".
+#
+# Usage:
+#
+#   ./ipptest -f filename printer-uri ipp-1.1.test
+#
+
+# Test that a request-id value of 0 is not accepted.
+#
+# Required by: RFC 2911 section 3.1.1
+{
+       NAME "3.1.1: Bad request-id value 0"
+       REQUEST-ID 0
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR uri printer-uri $uri
+
+       STATUS client-error-bad-request
+       EXPECT !printer-uri-supported
+}
+
+
+# Test that the first two attributes must be attributes-charset and
+# attributes-natural-language.
+#
+# Required by: RFC 2911 section 3.1.4
+{
+       NAME "3.1.4: No Operation Attributes"
+       REQUEST-ID random
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+
+       STATUS client-error-bad-request
+       EXPECT !printer-uri-supported
+}
+{
+       NAME "3.1.4: attributes-charset"
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR uri printer-uri $uri
+
+       STATUS client-error-bad-request
+       EXPECT !printer-uri-supported
+}
+{
+       NAME "3.1.4: attributes-natural-language"
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR uri printer-uri $uri
+
+       STATUS client-error-bad-request
+       EXPECT !printer-uri-supported
+}
+{
+       NAME "3.1.4: attributes-natural-language + attributes-charset"
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR charset attributes-charset utf-8
+       ATTR uri printer-uri $uri
+
+       STATUS client-error-bad-request
+       EXPECT !printer-uri-supported
+}
+{
+       NAME "3.1.4: attributes-charset + attributes-natural-language"
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR uri printer-uri $uri
+
+       STATUS successful-ok
+       EXPECT printer-uri-supported OF-TYPE uri
+}
+
+
+# Test that bad IPP versions are not supported.
+#
+# Required by: RFC 2911 section 3.1.8
+{
+       # The name of the test...
+       NAME "3.1.8: Unsupported IPP version 0.0"
+       VERSION 0.0
+       OPERATION Get-Printer-Attributes
+       ATTR charset attributes-charset utf-8
+       ATTR naturalLanguage attributes-natural-language en
+       ATTR uri printer-uri $uri
+
+       STATUS server-error-version-not-supported
+       EXPECT !printer-uri-supported
+}
+
+
+# Test that printer operations require the printer-uri operation attribute.
+#
+# Required by: RFC 2911 section 3.2
+{
+       NAME "3.2: No printer-uri operation attribute"
+       OPERATION Get-Printer-Attributes
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR naturalLanguage attributes-natural-language en
+
+       STATUS client-error-bad-request
+       EXPECT !printer-uri-supported
+}
+
+
+# Test Print-Job operation
+#
+# Required by: RFC 2911 section 3.2.1
+{
+       NAME "3.2.1: Print-Job Operation"
+       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 $filename
+       ATTR boolean ipp-attribute-fidelity false
+       ATTR name document-name $filename
+       ATTR keyword compression none
+       ATTR mimeMediaType document-format application/octet-stream
+       FILE $filename
+
+       STATUS successful-ok
+       STATUS client-error-document-format-not-supported
+       EXPECT job-uri OF-TYPE uri COUNT 1 IN-GROUP job-attributes-tag
+       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
+}
+
+# Test Get-Printer-Attributes operation
+#
+# Required by: RFC 2911 section 3.2.5
+{
+       NAME "3.2.5: Get-Printer-Attributes Operation (default)"
+       OPERATION Get-Printer-Attributes
+       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 mimeMediaType document-format application/octet-stream
+
+       STATUS successful-ok
+
+       # 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
+       EXPECT ?finishings-default OF-TYPE enum IN-GROUP printer-attributes-tag
+       EXPECT ?finishings-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3
+       EXPECT ?job-hold-until-default OF-TYPE keyword|name IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-hold-until-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag WITH-VALUE no-hold
+       EXPECT ?job-priority-default OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0,<101
+       EXPECT ?job-priority-supported OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0,<101
+       EXPECT ?job-sheets-default OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?job-sheets-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag WITH-VALUE none
+       EXPECT ?media-default OF-TYPE keyword|name IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?media-ready OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?media-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?multiple-document-handling-default OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?multiple-document-handling-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?number-up-default OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?number-up-supported OF-TYPE integer|rangeOfInteger IN-GROUP printer-attributes-tag WITH-VALUE >0
+       EXPECT ?number-up-supported WITH-VALUE 1
+       EXPECT ?orientation-requested-default OF-TYPE enum,no-value IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE no-value,3,4,5,6
+       EXPECT ?orientation-requested-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5,6
+       EXPECT ?pages-ranges-supported OF-TYPE boolean IN-GROUP printer-attributes-tag
+       EXPECT ?print-quality-default OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT ?print-quality-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5
+       EXPECT ?printer-resolution-default OF-TYPE resolution IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-resolution-supported OF-TYPE resolution IN-GROUP printer-attributes-tag
+       EXPECT ?sides-default OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+       EXPECT ?sides-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+
+       # Printer description attributes
+       EXPECT ?color-supported OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-impressions-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-k-octets-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?multiple-document-jobs-supported OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?multiple-operation-time-out OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?pages-per-minute OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?pages-per-minute-color OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-driver-installer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-info OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-location OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-make-and-model OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-message-from-operator OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-more-info OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-more-info-manufacturer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-state-message OF-TYPE text IN-GROUP printer-attributes-tag
+       EXPECT ?reference-uri-schemes-supported OF-TYPE uriScheme IN-GROUP printer-attributes-tag
+       EXPECT charset-configured OF-TYPE charset IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT charset-supported OF-TYPE charset IN-GROUP printer-attributes-tag WITH-VALUE utf-8
+       EXPECT compression-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE none
+       EXPECT document-format-default OF-TYPE mimeMediaType IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT document-format-supported OF-TYPE mimeMediaType IN-GROUP printer-attributes-tag
+       EXPECT generated-natural-language-supported OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag
+       EXPECT ipp-versions-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE 1.1
+       EXPECT natural-language-configured OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT operations-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 0x0002 # Print-Job
+       # Not requiring 0x0004 Validate-Job since it is deprecated
+       EXPECT operations-supported WITH-VALUE 0x0008 # Cancel-Job
+       EXPECT operations-supported WITH-VALUE 0x0009 # Get-Job-Attributes
+       EXPECT operations-supported WITH-VALUE 0x000a # Get-Jobs
+       EXPECT operations-supported WITH-VALUE 0x000b # Get-Printer-Attributes
+       EXPECT pdl-override-supported OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT printer-is-accepting-jobs OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT printer-name OF-TYPE name IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{1,127}$$/"
+       EXPECT printer-state OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT printer-state-reasons OF-TYPE keyword IN-GROUP printer-attributes-tag
+       EXPECT printer-up-time OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-security-supported
+       EXPECT queued-job-count OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT uri-authentication-supported OF-TYPE keyword IN-GROUP printer-attributes-tag
+       EXPECT uri-security-supported OF-TYPE keyword IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-authentication-supported
+}
+
+
+# Test Get-Printer-Attributes operation with requested-attributes
+#
+# Required by: RFC 2911 section 3.2.5
+{
+       NAME "3.2.5: Get-Printer-Attributes Operation (requested-attributes)"
+       OPERATION Get-Printer-Attributes
+       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 mimeMediaType document-format application/octet-stream
+       ATTR keyword requested-attributes printer-uri-supported
+
+       STATUS successful-ok
+
+       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag
+       EXPECT !printer-name
+}
+
+
+# Test Get-Jobs operation
+#
+# Required by: RFC 2911 section 3.2.6
+{
+       NAME "3.2.6: Get-Jobs Operation (default)"
+       OPERATION Get-Jobs
+       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
+
+       STATUS successful-ok
+       EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT !job-printer-uri
+       EXPECT !job-more-info
+       EXPECT !job-name
+       EXPECT !job-originating-user-name
+       EXPECT !job-state
+       EXPECT !job-state-reasons
+       EXPECT !job-state-message
+       EXPECT !job-detailed-status-messages
+       EXPECT !number-of-documents
+       EXPECT !output-device-assigned
+       EXPECT !time-at-creation
+       EXPECT !time-at-processing
+       EXPECT !time-at-completed
+       EXPECT !job-printer-up-time
+       EXPECT !date-time-at-creation
+       EXPECT !date-time-at-processing
+       EXPECT !date-time-at-completed
+       EXPECT !number-of-intervening-jobs
+       EXPECT !job-message-from-operator
+       EXPECT !job-k-octets
+       EXPECT !job-impressions
+       EXPECT !job-media-sheets
+       EXPECT !job-k-octets-processed
+       EXPECT !job-impressions-completed
+       EXPECT !job-media-sheets-completed
+
+       EXPECT !copies
+       EXPECT !finishings
+       EXPECT !job-hold-until
+       EXPECT !job-priority
+       EXPECT !job-sheets
+       EXPECT !media
+       EXPECT !multiple-document-handling
+       EXPECT !number-up
+       EXPECT !orientation-requested
+       EXPECT !pages-ranges
+       EXPECT !print-quality
+       EXPECT !printer-resolution
+       EXPECT !sides
+}
+
+
+# Test Get-Jobs operation
+#
+# Required by: RFC 2911 section 3.2.6
+{
+       NAME "3.2.6: Get-Jobs Operation (requested-attributes)"
+       OPERATION Get-Jobs
+       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 keyword requested-attributes all
+
+       STATUS successful-ok
+       EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-printer-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-more-info OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-name OF-TYPE name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-originating-user-name OF-TYPE name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-state OF-TYPE enum IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >2,<10
+       EXPECT job-state-reasons OF-TYPE keyword IN-GROUP job-attributes-tag
+       EXPECT ?job-state-message OF-TYPE text IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-detailed-status-messages OF-TYPE text IN-GROUP job-attributes-tag
+       EXPECT ?number-of-documents OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?output-device-assigned OF-TYPE name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT time-at-creation OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE no-value,>-1
+       EXPECT time-at-processing OF-TYPE no-value,integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE no-value,>-1
+       EXPECT time-at-completed OF-TYPE no-value,integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE no-value,>-1
+       EXPECT job-printer-up-time OF-TYPE no-value,integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?date-time-at-creation OF-TYPE no-value,dateTime IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?date-time-at-processing OF-TYPE no-value,dateTime IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?date-time-at-completed OF-TYPE no-value,dateTime IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?number-of-intervening-jobs OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-message-from-operator OF-TYPE text IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-k-octets OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-impressions OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-k-octets-processed OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-impressions-completed OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets-completed OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+
+       EXPECT ?copies OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?finishings OF-TYPE enum IN-GROUP job-attributes-tag
+       EXPECT ?job-hold-until OF-TYPE keyword|name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-priority OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0,<101
+       EXPECT ?job-sheets OF-TYPE keyword|name IN-GROUP job-attributes-tag
+       EXPECT ?media OF-TYPE keyword|name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?multiple-document-handling OF-TYPE keyword IN-GROUP job-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?number-up OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?orientation-requested OF-TYPE enum IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE 3,4,5,6
+       EXPECT ?pages-ranges OF-TYPE rangeOfInteger IN-GROUP job-attributes-tag
+       EXPECT ?print-quality OF-TYPE enum IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT ?printer-resolution OF-TYPE resolution IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?sides OF-TYPE keyword IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+}
+
+
+# Test Get-Jobs operation
+#
+# Required by: RFC 2911 section 3.2.6
+{
+       NAME "3.2.6: Get-Jobs Operation (my-jobs)"
+       OPERATION Get-Jobs
+       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 boolean my-jobs true
+
+       STATUS successful-ok
+       EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT !job-printer-uri
+       EXPECT !job-more-info
+       EXPECT !job-name
+       EXPECT !job-originating-user-name
+       EXPECT !job-state
+       EXPECT !job-state-reasons
+       EXPECT !job-state-message
+       EXPECT !job-detailed-status-messages
+       EXPECT !number-of-documents
+       EXPECT !output-device-assigned
+       EXPECT !time-at-creation
+       EXPECT !time-at-processing
+       EXPECT !time-at-completed
+       EXPECT !job-printer-up-time
+       EXPECT !date-time-at-creation
+       EXPECT !date-time-at-processing
+       EXPECT !date-time-at-completed
+       EXPECT !number-of-intervening-jobs
+       EXPECT !job-message-from-operator
+       EXPECT !job-k-octets
+       EXPECT !job-impressions
+       EXPECT !job-media-sheets
+       EXPECT !job-k-octets-processed
+       EXPECT !job-impressions-completed
+       EXPECT !job-media-sheets-completed
+
+       EXPECT !copies
+       EXPECT !finishings
+       EXPECT !job-hold-until
+       EXPECT !job-priority
+       EXPECT !job-sheets
+       EXPECT !media
+       EXPECT !multiple-document-handling
+       EXPECT !number-up
+       EXPECT !orientation-requested
+       EXPECT !pages-ranges
+       EXPECT !print-quality
+       EXPECT !printer-resolution
+       EXPECT !sides
+}
+
+
+# Test Get-Jobs operation
+#
+# Required by: RFC 2911 section 3.2.6
+{
+       NAME "3.2.6: Get-Jobs Operation (my-jobs different user)"
+       OPERATION Get-Jobs
+       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 not-$user
+       ATTR boolean my-jobs true
+
+       STATUS successful-ok
+       EXPECT !job-id
+       EXPECT !job-uri
+       EXPECT !job-printer-uri
+       EXPECT !job-more-info
+       EXPECT !job-name
+       EXPECT !job-originating-user-name
+       EXPECT !job-state
+       EXPECT !job-state-reasons
+       EXPECT !job-state-message
+       EXPECT !job-detailed-status-messages
+       EXPECT !number-of-documents
+       EXPECT !output-device-assigned
+       EXPECT !time-at-creation
+       EXPECT !time-at-processing
+       EXPECT !time-at-completed
+       EXPECT !job-printer-up-time
+       EXPECT !date-time-at-creation
+       EXPECT !date-time-at-processing
+       EXPECT !date-time-at-completed
+       EXPECT !number-of-intervening-jobs
+       EXPECT !job-message-from-operator
+       EXPECT !job-k-octets
+       EXPECT !job-impressions
+       EXPECT !job-media-sheets
+       EXPECT !job-k-octets-processed
+       EXPECT !job-impressions-completed
+       EXPECT !job-media-sheets-completed
+
+       EXPECT !copies
+       EXPECT !finishings
+       EXPECT !job-hold-until
+       EXPECT !job-priority
+       EXPECT !job-sheets
+       EXPECT !media
+       EXPECT !multiple-document-handling
+       EXPECT !number-up
+       EXPECT !orientation-requested
+       EXPECT !pages-ranges
+       EXPECT !print-quality
+       EXPECT !printer-resolution
+       EXPECT !sides
+}
+
+
+# Test Get-Jobs operation
+#
+# Required by: RFC 2911 section 3.2.6
+{
+       NAME "3.2.6: Get-Jobs Operation (which-jobs=not-completed)"
+       OPERATION Get-Jobs
+       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 keyword which-jobs not-completed
+
+       STATUS successful-ok
+       EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT !job-printer-uri
+       EXPECT !job-more-info
+       EXPECT !job-name
+       EXPECT !job-originating-user-name
+       EXPECT !job-state
+       EXPECT !job-state-reasons
+       EXPECT !job-state-message
+       EXPECT !job-detailed-status-messages
+       EXPECT !number-of-documents
+       EXPECT !output-device-assigned
+       EXPECT !time-at-creation
+       EXPECT !time-at-processing
+       EXPECT !time-at-completed
+       EXPECT !job-printer-up-time
+       EXPECT !date-time-at-creation
+       EXPECT !date-time-at-processing
+       EXPECT !date-time-at-completed
+       EXPECT !number-of-intervening-jobs
+       EXPECT !job-message-from-operator
+       EXPECT !job-k-octets
+       EXPECT !job-impressions
+       EXPECT !job-media-sheets
+       EXPECT !job-k-octets-processed
+       EXPECT !job-impressions-completed
+       EXPECT !job-media-sheets-completed
+
+       EXPECT !copies
+       EXPECT !finishings
+       EXPECT !job-hold-until
+       EXPECT !job-priority
+       EXPECT !job-sheets
+       EXPECT !media
+       EXPECT !multiple-document-handling
+       EXPECT !number-up
+       EXPECT !orientation-requested
+       EXPECT !pages-ranges
+       EXPECT !print-quality
+       EXPECT !printer-resolution
+       EXPECT !sides
+}
+
+
+
+# Test Get-Jobs operation
+#
+# Required by: RFC 2911 section 3.2.6
+{
+       NAME "3.2.6: Get-Jobs Operation (which-jobs=completed)"
+       OPERATION Get-Jobs
+       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 keyword which-jobs completed
+       DELAY 10
+
+       STATUS successful-ok
+       EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT !job-printer-uri
+       EXPECT !job-more-info
+       EXPECT !job-name
+       EXPECT !job-originating-user-name
+       EXPECT !job-state
+       EXPECT !job-state-reasons
+       EXPECT !job-state-message
+       EXPECT !job-detailed-status-messages
+       EXPECT !number-of-documents
+       EXPECT !output-device-assigned
+       EXPECT !time-at-creation
+       EXPECT !time-at-processing
+       EXPECT !time-at-completed
+       EXPECT !job-printer-up-time
+       EXPECT !date-time-at-creation
+       EXPECT !date-time-at-processing
+       EXPECT !date-time-at-completed
+       EXPECT !number-of-intervening-jobs
+       EXPECT !job-message-from-operator
+       EXPECT !job-k-octets
+       EXPECT !job-impressions
+       EXPECT !job-media-sheets
+       EXPECT !job-k-octets-processed
+       EXPECT !job-impressions-completed
+       EXPECT !job-media-sheets-completed
+
+       EXPECT !copies
+       EXPECT !finishings
+       EXPECT !job-hold-until
+       EXPECT !job-priority
+       EXPECT !job-sheets
+       EXPECT !media
+       EXPECT !multiple-document-handling
+       EXPECT !number-up
+       EXPECT !orientation-requested
+       EXPECT !pages-ranges
+       EXPECT !print-quality
+       EXPECT !printer-resolution
+       EXPECT !sides
+}
+
+
+# Test Cancel-Job operation
+#
+# Required by: RFC 2911 section 3.3.3
+{
+       NAME "3.3.3: Cancel-Job Operation (completed job)"
+       OPERATION Cancel-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 client-error-not-possible
+}
+
+
+# Test Print-Job operation
+#
+# Required by: RFC 2911 section 3.2.1
+{
+       NAME "3.2.1: Print-Job Operation"
+       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 $filename
+       ATTR boolean ipp-attribute-fidelity false
+       ATTR name document-name $filename
+       ATTR keyword compression none
+       ATTR mimeMediaType document-format application/octet-stream
+       FILE $filename
+
+       STATUS successful-ok
+       STATUS client-error-document-format-not-supported
+       EXPECT job-uri OF-TYPE uri COUNT 1 IN-GROUP job-attributes-tag
+       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
+}
+
+
+# Test Cancel-Job operation
+#
+# Required by: RFC 2911 section 3.3.3
+{
+       NAME "3.3.3: Cancel-Job Operation (pending/processing job)"
+       OPERATION Cancel-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
+}
+
+
+# Test Get-Job-Attributes operation
+#
+# Required by: RFC 2911 section 3.3.4
+{
+       NAME "3.3.4: Get-Job-Attributes Operation"
+       OPERATION Get-Job-Attributes
+       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
+       EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-printer-uri OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-more-info OF-TYPE uri IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-name OF-TYPE name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-originating-user-name OF-TYPE name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT job-state OF-TYPE enum IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >2,<10
+       EXPECT job-state-reasons OF-TYPE keyword IN-GROUP job-attributes-tag
+       EXPECT ?job-state-message OF-TYPE text IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-detailed-status-messages OF-TYPE text IN-GROUP job-attributes-tag
+       EXPECT ?number-of-documents OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?output-device-assigned OF-TYPE name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT time-at-creation OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE no-value,>-1
+       EXPECT time-at-processing OF-TYPE no-value,integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE no-value,>-1
+       EXPECT time-at-completed OF-TYPE no-value,integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE no-value,>-1
+       EXPECT job-printer-up-time OF-TYPE no-value,integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?date-time-at-creation OF-TYPE no-value,dateTime IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?date-time-at-processing OF-TYPE no-value,dateTime IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?date-time-at-completed OF-TYPE no-value,dateTime IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?number-of-intervening-jobs OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-message-from-operator OF-TYPE text IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-k-octets OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-impressions OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-k-octets-processed OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-impressions-completed OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets-completed OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1
+
+       EXPECT ?copies OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?finishings OF-TYPE enum IN-GROUP job-attributes-tag
+       EXPECT ?job-hold-until OF-TYPE keyword|name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?job-priority OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0,<101
+       EXPECT ?job-sheets OF-TYPE keyword|name IN-GROUP job-attributes-tag
+       EXPECT ?media OF-TYPE keyword|name IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?multiple-document-handling OF-TYPE keyword IN-GROUP job-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?number-up OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?orientation-requested OF-TYPE enum IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE 3,4,5,6
+       EXPECT ?pages-ranges OF-TYPE rangeOfInteger IN-GROUP job-attributes-tag
+       EXPECT ?print-quality OF-TYPE enum IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT ?printer-resolution OF-TYPE resolution IN-GROUP job-attributes-tag COUNT 1
+       EXPECT ?sides OF-TYPE keyword IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+}
+
+
+#
+# End of "$Id$".
+#
diff --git a/test/ipp-2.0.test b/test/ipp-2.0.test
new file mode 100644 (file)
index 0000000..0c67788
--- /dev/null
@@ -0,0 +1,107 @@
+#
+# "$Id$"
+#
+#   IPP/2.0 test suite.
+#
+#   Copyright 2007-2010 by Apple Inc.
+#   Copyright 2001-2006 by Easy Software Products. All rights reserved.
+#
+#   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/".
+#
+# Usage:
+#
+#   ./ipptest -V 2.0 -f filename printer-uri ipp-2.0.test
+#
+
+# Do all of the IPP/1.1 tests as an IPP/2.0 client
+#
+# Required by: PWG 5100.10 section 4.3
+INCLUDE "ipp-1.1.test"
+
+
+# Test required printer description attribute support.
+#
+# Required by: PWG 5100.10 section 6.2
+{
+       NAME "PWG 5100.10 section 6.2 - Required Printer Description Attributes"
+       OPERATION Get-Printer-Attributes
+       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 mimeMediaType document-format application/octet-stream
+
+       STATUS successful-ok
+
+       # Job template attributes
+       EXPECT ?media-default OF-TYPE keyword|name IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?media-ready OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?media-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?multiple-document-handling-default OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?multiple-document-handling-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?number-up-default OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?number-up-supported OF-TYPE integer|rangeOfInteger IN-GROUP printer-attributes-tag WITH-VALUE >0
+       EXPECT ?number-up-supported WITH-VALUE 1
+       EXPECT ?orientation-requested-default OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5,6
+       EXPECT ?orientation-requested-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5,6
+       EXPECT ?pages-ranges-supported OF-TYPE boolean IN-GROUP printer-attributes-tag
+       EXPECT ?print-quality-default OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT ?print-quality-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5
+       EXPECT ?printer-resolution-default OF-TYPE resolution IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-resolution-supported OF-TYPE resolution IN-GROUP printer-attributes-tag
+       EXPECT ?sides-default OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+       EXPECT ?sides-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+
+       # Printer description attributes
+       EXPECT ?color-supported OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-impressions-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-k-octets-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?multiple-document-jobs-supported OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?multiple-operation-time-out OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?pages-per-minute OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?pages-per-minute-color OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-driver-installer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-info OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-location OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-make-and-model OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-message-from-operator OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-more-info OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-more-info-manufacturer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-state-message OF-TYPE text IN-GROUP printer-attributes-tag
+       EXPECT ?reference-uri-schemes-supported OF-TYPE uriScheme IN-GROUP printer-attributes-tag
+       EXPECT charset-configured OF-TYPE charset IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT charset-supported OF-TYPE charset IN-GROUP printer-attributes-tag WITH-VALUE utf-8
+       EXPECT compression-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE none
+       EXPECT document-format-default OF-TYPE mimeMediaType IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT document-format-supported OF-TYPE mimeMediaType IN-GROUP printer-attributes-tag
+       EXPECT generated-natural-language-supported OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag
+       EXPECT ipp-versions-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE 1.1
+       EXPECT natural-language-configured OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT operations-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 0x0002 # Print-Job
+       # Not requiring 0x0004 Validate-Job since it is deprecated
+       EXPECT operations-supported WITH-VALUE 0x0008 # Cancel-Job
+       EXPECT operations-supported WITH-VALUE 0x0009 # Get-Job-Attributes
+       EXPECT operations-supported WITH-VALUE 0x000A # Get-Jobs
+       EXPECT operations-supported WITH-VALUE 0x000B # Get-Printer-Attributes
+       EXPECT pdl-override-supported OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT printer-is-accepting-jobs OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT printer-name OF-TYPE name IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{1,127}$$/"
+       EXPECT printer-state OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT printer-state-reasons OF-TYPE keyword IN-GROUP printer-attributes-tag
+       EXPECT printer-up-time OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-security-supported
+       EXPECT queued-job-count OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT uri-authentication-supported OF-TYPE keyword IN-GROUP printer-attributes-tag
+       EXPECT uri-security-supported OF-TYPE keyword IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-authentication-supported
+}
+
+
+#
+# End of "$Id$".
+#
diff --git a/test/ipp-2.1.test b/test/ipp-2.1.test
new file mode 100644 (file)
index 0000000..d35eab0
--- /dev/null
@@ -0,0 +1,105 @@
+#
+# "$Id$"
+#
+#   IPP/2.1 test suite.
+#
+#   Copyright 2007-2010 by Apple Inc.
+#   Copyright 2001-2006 by Easy Software Products. All rights reserved.
+#
+#   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/".
+#
+# Usage:
+#
+#   ./ipptest -V 2.1 -f filename printer-uri ipp-2.0.test
+#
+
+# Do all of the IPP/1.1 and IPP/2.0 tests as an IPP/2.1 client
+INCLUDE "ipp-2.0.test"
+
+
+# Test required printer description attribute support.
+#
+# Required by: PWG 5100.10 section 6.3
+{
+       NAME "PWG 5100.10 section 6.3 - Required Printer Description Attributes"
+       OPERATION Get-Printer-Attributes
+       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 mimeMediaType document-format application/octet-stream
+
+       STATUS successful-ok
+
+       # Job template attributes
+       EXPECT ?media-default OF-TYPE keyword|name IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?media-ready OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?media-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag
+       EXPECT ?multiple-document-handling-default OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?multiple-document-handling-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(single-document|separate-documents-uncollated-copies|separate-documents-collated-copies|single-document-new-sheet)$$/"
+       EXPECT ?number-up-default OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?number-up-supported OF-TYPE integer|rangeOfInteger IN-GROUP printer-attributes-tag WITH-VALUE >0
+       EXPECT ?number-up-supported WITH-VALUE 1
+       EXPECT ?orientation-requested-default OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5,6
+       EXPECT ?orientation-requested-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5,6
+       EXPECT ?pages-ranges-supported OF-TYPE boolean IN-GROUP printer-attributes-tag
+       EXPECT ?print-quality-default OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT ?print-quality-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5
+       EXPECT ?printer-resolution-default OF-TYPE resolution IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-resolution-supported OF-TYPE resolution IN-GROUP printer-attributes-tag
+       EXPECT ?sides-default OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+       EXPECT ?sides-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+
+       # Printer description attributes
+       EXPECT ?color-supported OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-impressions-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-k-octets-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?job-media-sheets-supported OF-TYPE rangeOfInteger IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?multiple-document-jobs-supported OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?multiple-operation-time-out OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT ?pages-per-minute OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?pages-per-minute-color OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-driver-installer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-info OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-location OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-make-and-model OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-message-from-operator OF-TYPE text IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{0,127}$$/"
+       EXPECT ?printer-more-info OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-more-info-manufacturer OF-TYPE uri IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT ?printer-state-message OF-TYPE text IN-GROUP printer-attributes-tag
+       EXPECT ?reference-uri-schemes-supported OF-TYPE uriScheme IN-GROUP printer-attributes-tag
+       EXPECT charset-configured OF-TYPE charset IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT charset-supported OF-TYPE charset IN-GROUP printer-attributes-tag WITH-VALUE utf-8
+       EXPECT compression-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE none
+       EXPECT document-format-default OF-TYPE mimeMediaType IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT document-format-supported OF-TYPE mimeMediaType IN-GROUP printer-attributes-tag
+       EXPECT generated-natural-language-supported OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag
+       EXPECT ipp-versions-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE 1.1
+       EXPECT natural-language-configured OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT operations-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 0x0002 # Print-Job
+       # Not requiring 0x0004 Validate-Job since it is deprecated
+       EXPECT operations-supported WITH-VALUE 0x0008 # Cancel-Job
+       EXPECT operations-supported WITH-VALUE 0x0009 # Get-Job-Attributes
+       EXPECT operations-supported WITH-VALUE 0x000A # Get-Jobs
+       EXPECT operations-supported WITH-VALUE 0x000B # Get-Printer-Attributes
+       EXPECT pdl-override-supported OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT printer-is-accepting-jobs OF-TYPE boolean IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT printer-name OF-TYPE name IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^.{1,127}$$/"
+       EXPECT printer-state OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
+       EXPECT printer-state-reasons OF-TYPE keyword IN-GROUP printer-attributes-tag
+       EXPECT printer-up-time OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
+       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-security-supported
+       EXPECT queued-job-count OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
+       EXPECT uri-authentication-supported OF-TYPE keyword IN-GROUP printer-attributes-tag
+       EXPECT uri-security-supported OF-TYPE keyword IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-authentication-supported
+}
+
+
+#
+# End of "$Id$".
+#
index 28404388da93d9763fa1ead1dd91a81b3718aa85..e94f06f3601c4ad6afa6d3d713c0f569eb1b2e41 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: ipptest.c 7847 2008-08-19 04:22:14Z mike $"
+ * "$Id: ipptest.c 9000 2010-02-24 06:29:38Z mike $"
  *
  *   IPP test command for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  *
  * Contents:
  *
- *   main()           - Parse options and do tests.
- *   do_tests()       - Do tests as specified in the test file.
- *   expect_matches() - Return true if the tag matches the specification.
- *   get_token()      - Get a token from a file.
- *   print_attr()     - Print an attribute on the screen.
- *   print_col()      - Print a collection attribute on the screen.
- *   usage()          - Show program usage.
+ *   main()              - Parse options and do tests.
+ *   compare_vars()      - Compare two variables.
+ *   do_tests()          - Do tests as specified in the test file.
+ *   expand_variables()  - Expand variables in a string.
+ *   expect_matches()    - Return true if the tag matches the specification.
+ *   get_collection()    - Get a collection value from the current test file.
+ *   get_filename()      - Get a filename based on the current test file.
+ *   get_token()         - Get a token from a file.
+ *   get_variable()      - Get the value of a variable.
+ *   iso_date()          - Return an ISO 8601 date/time string for the given IPP
+ *                         dateTime value.
+ *   print_attr()        - Print an attribute on the screen.
+ *   print_col()         - Print a collection attribute on the screen.
+ *   print_fatal_error() - Print a fatal error message.
+ *   print_test_error()  - Print a test error message.
+ *   print_xml_header()  - Print a standard XML plist header.
+ *   print_xml_string()  - Print an XML string with escaping.
+ *   print_xml_trailer() - Print the XML trailer with success/fail value.
+ *   set_variable()      - Set a variable value.
+ *   usage()             - Show program usage.
+ *   validate_attr()     - Determine whether an attribute is valid.
+ *   with_value()        - Test a WITH-VALUE predicate.
  */
 
 /*
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <cups/string.h>
 #include <errno.h>
 #include <ctype.h>
+#include <regex.h>
 
-#include <cups/cups.h>
-#include <cups/language.h>
-#include <cups/http-private.h>
+#include <cups/globals.h>
 #ifndef O_BINARY
 #  define O_BINARY 0
 #endif /* !O_BINARY */
  * Types...
  */
 
+typedef enum                           /**** How to send request data ****/
+{
+  _CUPS_TRANSFER_AUTO,                 /* Chunk for files, length for static */
+  _CUPS_TRANSFER_CHUNKED,              /* Chunk always */
+  _CUPS_TRANSFER_LENGTH                        /* Length always */
+} _cups_transfer_t;
+
 typedef struct _cups_expect_s          /**** Expected attribute info ****/
 {
-  int  not_expect;                     /* Don't expect attribute? */
-  char *name,                          /* Attribute name */
-       *of_type,                       /* Type name */
-       *same_count_as,                 /* Parallel attribute name */
-       *if_defined;                    /* Only required if variable defined */
+  int          optional,               /* Optional attribute? */
+               not_expect;             /* Don't expect attribute? */
+  char         *name,                  /* Attribute name */
+               *of_type,               /* Type name */
+               *same_count_as,         /* Parallel attribute name */
+               *if_defined,            /* Only required if variable defined */
+               *if_undefined,          /* Only required if variable is not defined */
+               *with_value;            /* Attribute must include this value */
+  int          with_regex,             /* WITH-VALUE is a regular expression */
+               count;                  /* Expected count if > 0 */
+  ipp_tag_t    in_group;               /* IN-GROUP value */
 } _cups_expect_t;
 
+typedef struct _cups_status_s          /**** Status info ****/
+{
+  ipp_status_t status;                 /* Expected status code */
+  char         *if_defined,            /* Only if variable is defined */
+               *if_undefined;          /* Only if variable is not defined */
+} _cups_status_t;
+
+typedef struct _cups_var_s             /**** Variable ****/
+{
+  char         *name,                  /* Name of variable */
+               *value;                 /* Value of variable */
+} _cups_var_t;
+
+typedef struct _cups_vars_s            /**** Set of variables ****/
+{
+  const char   *uri,                   /* URI for printer */
+               *filename;              /* Filename */
+  char         scheme[64],             /* Scheme from URI */
+               userpass[256],          /* Username/password from URI */
+               hostname[256],          /* Hostname from URI */
+               resource[1024];         /* Resource path from URI */
+  int          port;                   /* Port number from URI */
+  http_encryption_t encryption;                /* Encryption for connection? */
+  cups_array_t *vars;                  /* Array of variables */
+} _cups_vars_t;
+
 
 /*
  * Globals...
  */
 
-int            Chunking = 0;           /* Use chunked requests */
-int            Verbosity = 0;          /* Show all attributes? */
+_cups_transfer_t Transfer = _CUPS_TRANSFER_AUTO;
+                                       /* How to transfer requests */
+int            Verbosity = 0,          /* Show all attributes? */
+               Version = 11,           /* Default IPP version */
+               XML = 0,                /* Produce XML output? */
+               XMLHeader = 0;          /* 1 if header is written */
+const char * const URIStatusStrings[] =        /* URI status strings */
+{
+  "URI too large",
+  "Bad arguments to function",
+  "Bad resource in URI",
+  "Bad port number in URI",
+  "Bad hostname/address in URI",
+  "Bad username in URI",
+  "Bad scheme in URI",
+  "Bad/empty URI",
+  "OK",
+  "Missing scheme in URI",
+  "Unknown scheme in URI",
+  "Missing resource in URI"
+};
 
 
 /*
  * Local functions...
  */
 
-static int     do_tests(const char *uri, const char *testfile);
+static int     compare_vars(_cups_var_t *a, _cups_var_t *b);
+static int     do_tests(_cups_vars_t *vars, const char *testfile);
+static void    expand_variables(_cups_vars_t *vars, char *dst, const char *src,
+                                size_t dstsize)
+#ifdef __GNUC__
+__attribute((nonnull(1,2,3)))
+#endif /* __GNUC__ */
+;
 static int      expect_matches(_cups_expect_t *expect, ipp_tag_t value_tag);
+static ipp_t   *get_collection(_cups_vars_t *vars, FILE *fp, int *linenum);
+static char    *get_filename(const char *testfile, char *dst, const char *src,
+                             size_t dstsize);
 static char    *get_token(FILE *fp, char *buf, int buflen,
                           int *linenum);
+static char    *get_variable(_cups_vars_t *vars, const char *name);
+static char    *iso_date(ipp_uchar_t *date);
 static void    print_attr(ipp_attribute_t *attr);
 static void    print_col(ipp_t *col);
+static void    print_fatal_error(const char *s, ...)
+#ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 1, 2)))
+#endif /* __GNUC__ */
+;
+static void    print_test_error(const char *s, ...)
+#ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 1, 2)))
+#endif /* __GNUC__ */
+;
+static void    print_xml_header(void);
+static void    print_xml_string(const char *element, const char *s);
+static void    print_xml_trailer(int success, const char *message);
+static void    set_variable(_cups_vars_t *vars, const char *name,
+                            const char *value);
 static void    usage(void);
+static int     validate_attr(ipp_attribute_t *attr, int print);
+static int      with_value(char *value, int regex, ipp_attribute_t *attr);
 
 
 /*
@@ -84,21 +184,32 @@ int                                        /* O - Exit status */
 main(int  argc,                                /* I - Number of command-line args */
      char *argv[])                     /* I - Command-line arguments */
 {
-  int          i;                      /* Looping var */
-  int          status;                 /* Status of tests... */
-  char         *opt;                   /* Current option */
-  const char   *uri,                   /* URI to use */
-               *testfile;              /* Test file to use */
-  int          interval;               /* Test interval */
+  int                  i;              /* Looping var */
+  int                  status;         /* Status of tests... */
+  char                 *opt,           /* Current option */
+                       name[1024],     /* Name/value buffer */
+                       *value;         /* Pointer to value */
+  const char           *testfile;      /* Test file to use */
+  int                  interval;       /* Test interval */
+  _cups_vars_t         vars;           /* Variables */
+  http_uri_status_t    uri_status;     /* URI separation status */
+
+
+ /*
+  * Initialize the locale and variables...
+  */
+
+  _cupsSetLocale(argv);
 
+  memset(&vars, 0, sizeof(vars));
+  vars.vars = cupsArrayNew((cups_array_func_t)compare_vars, NULL);
 
  /*
   * We need at least:
   *
-  *     testipp URL testfile
+  *     ipptest URI testfile
   */
 
-  uri      = NULL;
   testfile = NULL;
   status   = 0;
   interval = 0;
@@ -111,8 +222,58 @@ main(int  argc,                            /* I - Number of command-line args */
       {
         switch (*opt)
         {
+         case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+             vars.encryption = HTTP_ENCRYPT_REQUIRED;
+#else
+             _cupsLangPrintf(stderr,
+                             _("%s: Sorry, no encryption support compiled in\n"),
+                             argv[0]);
+#endif /* HAVE_SSL */
+             break;
+
+         case 'V' : /* Set IPP version */
+             i ++;
+
+             if (i >= argc)
+             {
+               _cupsLangPuts(stderr,
+                             _("ipptest: Missing version for \"-V\".\n"));
+               usage();
+              }
+
+             if (!strcmp(argv[i], "1.0"))
+               Version = 10;
+             else if (!strcmp(argv[i], "1.1"))
+               Version = 11;
+             else if (!strcmp(argv[i], "2.0"))
+               Version = 20;
+             else if (!strcmp(argv[i], "2.1"))
+               Version = 21;
+             else if (!strcmp(argv[i], "2.2"))
+               Version = 22;
+             else
+             {
+               _cupsLangPrintf(stderr,
+                               _("ipptest: Bad version %s for \"-V\".\n"),
+                               argv[i]);
+               usage();
+             }
+             break;
+
+          case 'X' : /* Produce XML output */
+             XML = 1;
+
+              if (interval)
+             {
+               _cupsLangPuts(stderr, _("ipptest: \"-i\" is incompatible with "
+                                       "\"-x\".\n"));
+               usage();
+             }
+             break;
+
           case 'c' : /* Enable HTTP chunking */
-              Chunking = 1;
+              Transfer = _CUPS_TRANSFER_CHUNKED;
               break;
 
           case 'd' : /* Define a variable */
@@ -120,11 +281,31 @@ main(int  argc,                           /* I - Number of command-line args */
 
              if (i >= argc)
              {
-               fputs("ipptest: Missing name=value for \"-d\"!\n", stderr);
+               _cupsLangPuts(stderr,
+                             _("ipptest: Missing name=value for \"-d\".\n"));
                usage();
               }
+
+              strlcpy(name, argv[i], sizeof(name));
+             if ((value = strchr(name, '=')) != NULL)
+               *value++ = '\0';
              else
-               putenv(argv[i]);
+               value = name + strlen(name);
+
+             set_variable(&vars, name, value);
+             break;
+
+          case 'f' : /* Set the default test filename */
+             i ++;
+
+             if (i >= argc)
+             {
+               _cupsLangPuts(stderr,
+                             _("ipptest: Missing filename for \"-f\".\n"));
+               usage();
+              }
+
+             vars.filename = argv[i];
              break;
 
           case 'i' : /* Test every N seconds */
@@ -132,19 +313,32 @@ main(int  argc,                           /* I - Number of command-line args */
 
              if (i >= argc)
              {
-               fputs("ipptest: Missing seconds for \"-i\"!\n", stderr);
+               _cupsLangPuts(stderr,
+                             _("ipptest: Missing seconds for \"-i\".\n"));
                usage();
               }
              else
                interval = atoi(argv[i]);
+
+              if (XML && interval)
+             {
+               _cupsLangPuts(stderr, _("ipptest: \"-i\" is incompatible with "
+                                       "\"-x\".\n"));
+               usage();
+             }
              break;
 
+          case 'l' : /* Disable HTTP chunking */
+              Transfer = _CUPS_TRANSFER_LENGTH;
+              break;
+
           case 'v' : /* Be verbose */
              Verbosity ++;
              break;
 
          default :
-             fprintf(stderr, "ipptest: Unknown option \"-%c\"!\n", *opt);
+             _cupsLangPrintf(stderr, _("ipptest: Unknown option \"-%c\".\n"),
+                             *opt);
              usage();
              break;
        }
@@ -158,15 +352,34 @@ main(int  argc,                           /* I - Number of command-line args */
       * Set URI...
       */
 
-      if (!testfile && uri)
+      if (vars.uri)
       {
-        fputs("ipptest: May only specify a single URI before a test!\n",
-              stderr);
+        _cupsLangPuts(stderr, _("ipptest: May only specify a single URI.\n"));
         usage();
       }
 
-      uri      = argv[i];
-      testfile = NULL;
+      vars.uri   = argv[i];
+      uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, vars.uri,
+                                   vars.scheme, sizeof(vars.scheme),
+                                   vars.userpass, sizeof(vars.userpass),
+                                  vars.hostname, sizeof(vars.hostname),
+                                  &(vars.port),
+                                  vars.resource, sizeof(vars.resource));
+
+      if (uri_status != HTTP_URI_OK)
+      {
+        _cupsLangPrintf(stderr, _("ipptest: Bad URI - %s.\n"),
+                       URIStatusStrings[uri_status - HTTP_URI_OVERFLOW]);
+        return (1);
+      }
+
+      if (strcmp(vars.scheme, "http") && strcmp(vars.scheme, "https") &&
+          strcmp(vars.scheme, "ipp"))
+      {
+        _cupsLangPuts(stderr, _("ipptest: Only http, https, and ipp URIs are "
+                               "supported."));
+       return (1);
+      }
     }
     else
     {
@@ -174,26 +387,34 @@ main(int  argc,                           /* I - Number of command-line args */
       * Run test...
       */
 
+      if (!vars.uri)
+      {
+        _cupsLangPuts(stderr, _("ipptest: URI required before test file."));
+       usage();
+      }
+
       testfile = argv[i];
 
-      if (!do_tests(uri, testfile))
-        status ++;
+      if (!do_tests(&vars, testfile))
+        status = 1;
     }
   }
 
-  if (!uri || !testfile)
+  if (!vars.uri || !testfile)
     usage();
 
  /*
   * Loop if the interval is set...
   */
 
-  if (interval)
+  if (XML)
+    print_xml_trailer(!status, NULL);
+  else if (interval)
   {
     for (;;)
     {
       sleep(interval);
-      do_tests(uri, testfile);
+      do_tests(&vars, testfile);
     }
   }
 
@@ -204,50 +425,59 @@ main(int  argc,                           /* I - Number of command-line args */
   return (status);
 }
 
-        
+
+/*
+ * 'compare_vars()' - Compare two variables.
+ */
+
+static int                             /* O - Result of comparison */
+compare_vars(_cups_var_t *a,           /* I - First variable */
+             _cups_var_t *b)           /* I - Second variable */
+{
+  return (strcasecmp(a->name, b->name));
+}
+
+
 /*
  * 'do_tests()' - Do tests as specified in the test file.
  */
 
 static int                             /* 1 = success, 0 = failure */
-do_tests(const char *uri,              /* I - URI to connect on */
-         const char *testfile)         /* I - Test file to use */
+do_tests(_cups_vars_t *vars,           /* I - Variables */
+         const char   *testfile)       /* I - Test file to use */
 {
-  int          i;                      /* Looping var */
-  int          linenum;                /* Current line number */
-  int          version;                /* IPP version number to use */
-  http_t       *http;                  /* HTTP connection to server */
-  char         scheme[HTTP_MAX_URI],   /* URI scheme */
-               userpass[HTTP_MAX_URI], /* username:password */
-               server[HTTP_MAX_URI],   /* Server */
-               resource[HTTP_MAX_URI]; /* Resource path */
-  int          port;                   /* Port number */
-  FILE         *fp;                    /* Test file */
-  char         token[1024],            /* Token from file */
+  int          i,                      /* Looping var */
+               linenum,                /* Current line number */
+               pass,                   /* Did we pass the test? */
+               request_id;             /* Current request ID */
+  http_t       *http = NULL;           /* HTTP connection to server */
+  FILE         *fp = NULL;             /* Test file */
+  char         resource[512],          /* Resource for request */
+               token[1024],            /* Token from file */
                *tokenptr,              /* Pointer into token */
-               temp[1024],             /* Temporary string */
-               *tempptr;               /* Pointer into temp string */
-  ipp_t                *request;               /* IPP request */
-  ipp_t                *response;              /* IPP response */
+               temp[1024];             /* Temporary string */
+  ipp_t                *request = NULL;        /* IPP request */
+  ipp_t                *response = NULL;       /* IPP response */
+  char         attr[128];              /* Attribute name */
   ipp_op_t     op;                     /* Operation */
   ipp_tag_t    group;                  /* Current group */
   ipp_tag_t    value;                  /* Current value type */
   ipp_attribute_t *attrptr,            /* Attribute pointer */
-               *found;                 /* Found attribute */
-  char         attr[128];              /* Attribute name */
-  int          num_statuses;           /* Number of valid status codes */
-  ipp_status_t statuses[100];          /* Valid status codes */
-  int          num_expects;            /* Number of expected attributes */
-  _cups_expect_t expects[100],         /* Expected attributes */
+               *found,                 /* Found attribute */
+               *lastcol = NULL;        /* Last collection attribute */
+  char         name[1024];             /* Name of test */
+  char         filename[1024];         /* Filename */
+  _cups_transfer_t transfer;           /* To chunk or not to chunk */
+  int          version;                /* IPP version number to use */
+  int          num_statuses = 0;       /* Number of valid status codes */
+  _cups_status_t statuses[100],                /* Valid status codes */
+               *last_status;           /* Last STATUS (for predicates) */
+  int          num_expects = 0;        /* Number of expected attributes */
+  _cups_expect_t expects[200],         /* Expected attributes */
                *expect,                /* Current expected attribute */
                *last_expect;           /* Last EXPECT (for predicates) */
-  int          num_displayed;          /* Number of displayed attributes */
+  int          num_displayed = 0;      /* Number of displayed attributes */
   char         *displayed[100];        /* Displayed attributes */
-  char         name[1024];             /* Name of test */
-  char         filename[1024];         /* Filename */
-  int          pass;                   /* Did we pass the test? */
-  int          job_id;                 /* Job ID from last operation */
-  int          subscription_id;        /* Subscription ID from last operation */
 
 
  /*
@@ -256,35 +486,37 @@ do_tests(const char *uri,         /* I - URI to connect on */
 
   if ((fp = fopen(testfile, "r")) == NULL)
   {
-    printf("Unable to open test file %s - %s\n", testfile, strerror(errno));
-    return (0);
+    print_fatal_error("Unable to open test file %s - %s", testfile,
+                      strerror(errno));
+    goto test_error;
   }
 
  /*
   * Connect to the server...
   */
 
-  httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass,
-                  sizeof(userpass), server, sizeof(server), &port, resource,
-                 sizeof(resource));
-  if ((http = httpConnect(server, port)) == NULL)
+  if ((http = httpConnectEncrypt(vars->hostname, vars->port,
+                                 vars->encryption)) == NULL)
   {
-    printf("Unable to connect to %s on port %d - %s\n", server, port,
-           strerror(errno));
-    fclose(fp);
-    return (0);
+    print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
+                      vars->port, strerror(errno));
+    goto test_error;
   }
 
  /*
   * Loop on tests...
   */
 
-  printf("\"%s\":\n", testfile);
-  pass            = 1;
-  job_id          = 0;
-  subscription_id = 0;
-  version         = 11;
-  linenum         = 1;
+  if (XML)
+    print_xml_header();
+  else
+    printf("\"%s\":\n", testfile);
+
+  CUPS_SRAND(time(NULL));
+
+  pass       = 1;
+  linenum    = 1;
+  request_id = (CUPS_RAND() % 1000) * 137 + 1;
 
   while (get_token(fp, token, sizeof(token), &linenum) != NULL)
   {
@@ -292,32 +524,134 @@ do_tests(const char *uri,                /* I - URI to connect on */
     * Expect an open brace...
     */
 
-    if (strcmp(token, "{"))
+    if (!strcmp(token, "DEFINE"))
+    {
+     /*
+      * DEFINE name value
+      */
+
+      if (get_token(fp, attr, sizeof(attr), &linenum) &&
+          get_token(fp, temp, sizeof(temp), &linenum))
+      {
+        expand_variables(vars, token, temp, sizeof(token));
+       set_variable(vars, attr, token);
+      }
+      else
+      {
+        print_fatal_error("Missing DEFINE name and/or value on line %d.",
+                         linenum);
+        goto test_error;
+      }
+
+      continue;
+    }
+    else if (!strcmp(token, "INCLUDE"))
+    {
+     /*
+      * INCLUDE "filename"
+      * INCLUDE <filename>
+      */
+
+      if (get_token(fp, temp, sizeof(temp), &linenum))
+      {
+       /*
+        * Map the filename to and then run the tests...
+       */
+
+        if (!do_tests(vars, get_filename(testfile, filename, temp,
+                                        sizeof(filename))))
+         goto test_error;
+      }
+      else
+      {
+        print_fatal_error("Missing INCLUDE filename on line %d.", linenum);
+        goto test_error;
+      }
+
+      continue;
+    }
+    else if (!strcmp(token, "TRANSFER"))
+    {
+     /*
+      * TRANSFER auto
+      * TRANSFER chunked
+      * TRANSFER length
+      */
+
+      if (get_token(fp, temp, sizeof(temp), &linenum))
+      {
+        if (!strcmp(temp, "auto"))
+         Transfer = _CUPS_TRANSFER_AUTO;
+       else if (!strcmp(temp, "chunked"))
+         Transfer = _CUPS_TRANSFER_CHUNKED;
+       else if (!strcmp(temp, "length"))
+         Transfer = _CUPS_TRANSFER_LENGTH;
+       else
+       {
+         print_fatal_error("Bad TRANSFER value \"%s\" on line %d.", temp,
+                           linenum);
+         goto test_error;
+       }
+      }
+      else
+      {
+        print_fatal_error("Missing TRANSFER value on line %d.", linenum);
+        goto test_error;
+      }
+
+      continue;
+    }
+    else if (!strcmp(token, "VERSION"))
+    {
+      if (get_token(fp, temp, sizeof(temp), &linenum))
+      {
+        if (!strcmp(temp, "1.0"))
+         Version = 10;
+       else if (!strcmp(temp, "1.1"))
+         Version = 11;
+       else if (!strcmp(temp, "2.0"))
+         Version = 20;
+       else if (!strcmp(temp, "2.1"))
+         Version = 21;
+       else if (!strcmp(temp, "2.2"))
+         Version = 22;
+       else
+       {
+         print_fatal_error("Bad VERSION \"%s\" on line %d.", temp, linenum);
+         goto test_error;
+       }
+      }
+      else
+      {
+        print_fatal_error("Missing VERSION number on line %d.", linenum);
+        goto test_error;
+      }
+
+      continue;
+    }
+    else if (strcmp(token, "{"))
     {
-      printf("Unexpected token %s seen on line %d - aborting test!\n", token,
-             linenum);
-      httpClose(http);
-      return (0);
+      print_fatal_error("Unexpected token %s seen on line %d.", token, linenum);
+      goto test_error;
     }
 
    /*
     * Initialize things...
     */
 
-    httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass,
-                    sizeof(userpass), server, sizeof(server), &port, resource,
-                   sizeof(resource));
+    strlcpy(resource, vars->resource, sizeof(resource));
 
+    request_id ++;
     request       = ippNew();
     op            = (ipp_op_t)0;
     group         = IPP_TAG_ZERO;
-    num_statuses  = 0;
-    num_expects   = 0;
-    num_displayed = 0;
     last_expect   = NULL;
+    last_status   = NULL;
     filename[0]   = '\0';
+    version       = Version;
+    transfer      = Transfer;
 
-    strcpy(name, testfile);
+    strlcpy(name, testfile, sizeof(name));
     if (strrchr(name, '.') != NULL)
       *strrchr(name, '.') = '\0';
 
@@ -327,14 +661,86 @@ do_tests(const char *uri,         /* I - URI to connect on */
 
     while (get_token(fp, token, sizeof(token), &linenum) != NULL)
     {
-      if (strcasecmp(token, "EXPECT") &&
+      if (strcasecmp(token, "COUNT") &&
           strcasecmp(token, "IF-DEFINED") &&
+          strcasecmp(token, "IF-UNDEFINED") &&
+          strcasecmp(token, "IN-GROUP") &&
           strcasecmp(token, "OF-TYPE") &&
-          strcasecmp(token, "SAME-COUNT-AS"))
+          strcasecmp(token, "SAME-COUNT-AS") &&
+          strcasecmp(token, "WITH-VALUE"))
         last_expect = NULL;
 
+      if (strcasecmp(token, "IF-DEFINED") &&
+          strcasecmp(token, "IF-UNDEFINED"))
+        last_status = NULL;
+
       if (!strcmp(token, "}"))
         break;
+      else if (!strcmp(token, "{") && lastcol)
+      {
+       /*
+       * Another collection value
+       */
+
+       ipp_t   *col = get_collection(vars, fp, &linenum);
+                                       /* Collection value */
+
+       if (col)
+       {
+         ipp_attribute_t *tempcol;     /* Pointer to new buffer */
+
+
+        /*
+         * Reallocate memory...
+         */
+
+         if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) +
+                                         (lastcol->num_values + 1) *
+                                         sizeof(ipp_value_t))) == NULL)
+         {
+           print_fatal_error("Unable to allocate memory on line %d.", linenum);
+           goto test_error;
+         }
+
+         if (tempcol != lastcol)
+         {
+          /*
+           * Reset pointers in the list...
+           */
+
+           if (request->prev)
+             request->prev->next = tempcol;
+           else
+             request->attrs = tempcol;
+
+           lastcol = request->current = request->last = tempcol;
+         }
+
+         lastcol->values[lastcol->num_values].collection = col;
+         lastcol->num_values ++;
+       }
+       else
+         goto test_error;
+      }
+      else if (!strcmp(token, "DEFINE"))
+      {
+       /*
+       * DEFINE name value
+       */
+
+       if (get_token(fp, attr, sizeof(attr), &linenum) &&
+           get_token(fp, temp, sizeof(temp), &linenum))
+       {
+         expand_variables(vars, token, temp, sizeof(token));
+         set_variable(vars, attr, token);
+       }
+       else
+       {
+         print_fatal_error("Missing DEFINE name and/or value on line %d.",
+                           linenum);
+         goto test_error;
+       }
+      }
       else if (!strcasecmp(token, "NAME"))
       {
        /*
@@ -343,26 +749,87 @@ do_tests(const char *uri,         /* I - URI to connect on */
 
        get_token(fp, name, sizeof(name), &linenum);
       }
-      else if (!strcasecmp(token, "VERSION"))
+      else if (!strcmp(token, "REQUEST-ID"))
       {
        /*
-        * IPP version number for test...
+       * REQUEST-ID #
+       * REQUEST-ID random
        */
 
-        int major, minor;              /* Major/minor IPP version */
-
+       if (get_token(fp, temp, sizeof(temp), &linenum))
+       {
+         if (isdigit(temp[0] & 255))
+           request_id = atoi(temp);
+         else if (!strcasecmp(temp, "random"))
+           request_id = (CUPS_RAND() % 1000) * 137 + 1;
+         else
+         {
+           print_fatal_error("Bad REQUEST-ID value \"%s\" on line %d.", temp,
+                             linenum);
+           goto test_error;
+         }
+       }
+       else
+       {
+         print_fatal_error("Missing REQUEST-ID value on line %d.", linenum);
+         goto test_error;
+       }
+      }
+      else if (!strcmp(token, "TRANSFER"))
+      {
+       /*
+       * TRANSFER auto
+       * TRANSFER chunked
+       * TRANSFER length
+       */
 
-       get_token(fp, temp, sizeof(temp), &linenum);
-       if (sscanf(temp, "%d.%d", &major, &minor) == 2 &&
-           major >= 0 && minor >= 0 && minor < 10)
-         version = major * 10 + minor;
+       if (get_token(fp, temp, sizeof(temp), &linenum))
+       {
+         if (!strcmp(temp, "auto"))
+           transfer = _CUPS_TRANSFER_AUTO;
+         else if (!strcmp(temp, "chunked"))
+           transfer = _CUPS_TRANSFER_CHUNKED;
+         else if (!strcmp(temp, "length"))
+           transfer = _CUPS_TRANSFER_LENGTH;
+         else
+         {
+           print_fatal_error("Bad TRANSFER value \"%s\" on line %d.", temp,
+                             linenum);
+           goto test_error;
+         }
+       }
+       else
+       {
+         print_fatal_error("Missing TRANSFER value on line %d.", linenum);
+         goto test_error;
+       }
+      }
+      else if (!strcasecmp(token, "VERSION"))
+      {
+       if (get_token(fp, temp, sizeof(temp), &linenum))
+       {
+         if (!strcmp(temp, "0.0"))
+           version = 0;
+         else if (!strcmp(temp, "1.0"))
+           version = 10;
+         else if (!strcmp(temp, "1.1"))
+           version = 11;
+         else if (!strcmp(temp, "2.0"))
+           version = 20;
+         else if (!strcmp(temp, "2.1"))
+           version = 21;
+         else if (!strcmp(temp, "2.2"))
+           version = 22;
+         else
+         {
+           print_fatal_error("Bad VERSION \"%s\" on line %d.", temp, linenum);
+           goto test_error;
+         }
+       }
        else
        {
-         printf("Bad version %s seen on line %d - aborting test!\n", token,
-                linenum);
-         httpClose(http);
-         ippDelete(request);
-         return (0);
+         print_fatal_error("Missing VERSION number on line %d.", linenum);
+         goto test_error;
        }
       }
       else if (!strcasecmp(token, "RESOURCE"))
@@ -371,7 +838,11 @@ do_tests(const char *uri,          /* I - URI to connect on */
         * Resource name...
        */
 
-       get_token(fp, resource, sizeof(resource), &linenum);
+       if (!get_token(fp, resource, sizeof(resource), &linenum))
+       {
+         print_fatal_error("Missing RESOURCE path on line %d.", linenum);
+         goto test_error;
+       }
       }
       else if (!strcasecmp(token, "OPERATION"))
       {
@@ -379,8 +850,18 @@ do_tests(const char *uri,          /* I - URI to connect on */
         * Operation...
        */
 
-       get_token(fp, token, sizeof(token), &linenum);
-       op = ippOpValue(token);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing OPERATION code on line %d.", linenum);
+         goto test_error;
+       }
+
+       if ((op = ippOpValue(token)) < 0)
+       {
+         print_fatal_error("Bad OPERATION code \"%s\" on line %d.", token,
+                           linenum);
+         goto test_error;
+       }
       }
       else if (!strcasecmp(token, "GROUP"))
       {
@@ -388,8 +869,17 @@ do_tests(const char *uri,          /* I - URI to connect on */
         * Attribute group...
        */
 
-       get_token(fp, token, sizeof(token), &linenum);
-       value = ippTagValue(token);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing GROUP tag on line %d.", linenum);
+         goto test_error;
+       }
+
+       if ((value = ippTagValue(token)) < 0)
+       {
+         print_fatal_error("Bad GROUP tag \"%s\" on line %d.", token, linenum);
+         goto test_error;
+       }
 
        if (value == group)
          ippAddSeparator(request);
@@ -404,8 +894,19 @@ do_tests(const char *uri,          /* I - URI to connect on */
 
         int delay;
 
-       get_token(fp, token, sizeof(token), &linenum);
-       if ((delay = atoi(token)) > 0)
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing DELAY value on line %d.", linenum);
+         goto test_error;
+       }
+
+       if ((delay = atoi(token)) <= 0)
+       {
+         print_fatal_error("Bad DELAY value \"%s\" on line %d.", token,
+                           linenum);
+         goto test_error;
+       }
+       else
          sleep(delay);
       }
       else if (!strcasecmp(token, "ATTR"))
@@ -414,102 +915,34 @@ do_tests(const char *uri,                /* I - URI to connect on */
         * Attribute...
        */
 
-       get_token(fp, token, sizeof(token), &linenum);
-       value = ippTagValue(token);
-       get_token(fp, attr, sizeof(attr), &linenum);
-       get_token(fp, temp, sizeof(temp), &linenum);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing ATTR value tag on line %d.", linenum);
+         goto test_error;
+       }
 
-        token[sizeof(token) - 1] = '\0';
+       if ((value = ippTagValue(token)) < 0)
+       {
+         print_fatal_error("Bad ATTR value tag \"%s\" on line %d.", token,
+                           linenum);
+         goto test_error;
+       }
 
-        for (tempptr = temp, tokenptr = token;
-            *tempptr && tokenptr < (token + sizeof(token) - 1);)
-         if (*tempptr == '$')
-         {
-          /*
-           * Substitute a string/number...
-           */
+       printf("%d: value=%s\n", linenum, ippTagString(value));
 
-            if (!strncasecmp(tempptr + 1, "uri", 3))
-           {
-             strlcpy(tokenptr, uri, sizeof(token) - (tokenptr - token));
-             tempptr += 4;
-           }
-           else if (!strncasecmp(tempptr + 1, "scheme", 6) ||
-                    !strncasecmp(tempptr + 1, "method", 6))
-           {
-             strlcpy(tokenptr, scheme, sizeof(token) - (tokenptr - token));
-             tempptr += 7;
-           }
-           else if (!strncasecmp(tempptr + 1, "username", 8))
-           {
-             strlcpy(tokenptr, userpass, sizeof(token) - (tokenptr - token));
-             tempptr += 9;
-           }
-           else if (!strncasecmp(tempptr + 1, "hostname", 8))
-           {
-             strlcpy(tokenptr, server, sizeof(token) - (tokenptr - token));
-             tempptr += 9;
-           }
-           else if (!strncasecmp(tempptr + 1, "port", 4))
-           {
-             snprintf(tokenptr, sizeof(token) - (tokenptr - token),
-                      "%d", port);
-             tempptr += 5;
-           }
-           else if (!strncasecmp(tempptr + 1, "resource", 8))
-           {
-             strlcpy(tokenptr, resource, sizeof(token) - (tokenptr - token));
-             tempptr += 9;
-           }
-           else if (!strncasecmp(tempptr + 1, "job-id", 6))
-           {
-             snprintf(tokenptr, sizeof(token) - (tokenptr - token),
-                      "%d", job_id);
-             tempptr += 7;
-           }
-           else if (!strncasecmp(tempptr + 1, "notify-subscription-id", 22))
-           {
-             snprintf(tokenptr, sizeof(token) - (tokenptr - token),
-                      "%d", subscription_id);
-             tempptr += 23;
-           }
-           else if (!strncasecmp(tempptr + 1, "user", 4))
-           {
-             strlcpy(tokenptr, cupsUser(), sizeof(token) - (tokenptr - token));
-             tempptr += 5;
-           }
-           else if (!strncasecmp(tempptr + 1, "ENV[", 4))
-           {
-             char *end;                /* End of $ENV[name] */
+       if (!get_token(fp, attr, sizeof(attr), &linenum))
+       {
+         print_fatal_error("Missing ATTR name on line %d.", linenum);
+         goto test_error;
+       }
 
+       if (!get_token(fp, temp, sizeof(temp), &linenum))
+       {
+         print_fatal_error("Missing ATTR value on line %d.", linenum);
+         goto test_error;
+       }
 
-             if ((end = strchr(tempptr + 5, ']')) != NULL)
-             {
-               *end++ = '\0';
-               strlcpy(tokenptr,
-                       getenv(tempptr + 5) ? getenv(tempptr + 5) : tempptr + 5,
-                       sizeof(token) - (tokenptr - token));
-               tempptr = end;
-             }
-             else
-             {
-               *tokenptr++ = *tempptr++;
-               *tokenptr   = '\0';
-             }
-           }
-            else
-           {
-             *tokenptr++ = *tempptr++;
-             *tokenptr   = '\0';
-           }
-
-            tokenptr += strlen(tokenptr);
-         }
-         else
-         {
-           *tokenptr++ = *tempptr++;
-           *tokenptr   = '\0';
-         }
+        expand_variables(vars, token, temp, sizeof(token));
 
         switch (value)
        {
@@ -526,11 +959,74 @@ do_tests(const char *uri,         /* I - URI to connect on */
              break;
 
          case IPP_TAG_RESOLUTION :
-             puts("    ERROR: resolution tag not yet supported!");
+             {
+               int     xres,           /* X resolution */
+                       yres;           /* Y resolution */
+               char    units[6];       /* Units */
+
+                if (sscanf(token, "%dx%d%5s", &xres, &yres, units) != 3 ||
+                   (strcasecmp(units, "dpi") && strcasecmp(units, "dpc") &&
+                    strcasecmp(units, "other")))
+               {
+                 print_fatal_error("Bad resolution value \"%s\" on line %d.",
+                                   token, linenum);
+                 goto test_error;
+               }
+
+               if (!strcasecmp(units, "dpi"))
+                 ippAddResolution(request, group, attr, xres, yres,
+                                  IPP_RES_PER_INCH);
+               else if (!strcasecmp(units, "dpc"))
+                 ippAddResolution(request, group, attr, xres, yres,
+                                  IPP_RES_PER_CM);
+               else
+                 ippAddResolution(request, group, attr, xres, yres,
+                                  (ipp_res_t)0);
+             }
              break;
 
          case IPP_TAG_RANGE :
-             puts("    ERROR: range tag not yet supported!");
+             {
+               int     lowers[4],      /* Lower value */
+                       uppers[4],      /* Upper values */
+                       num_vals;       /* Number of values */
+
+
+               num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d",
+                                 lowers + 0, uppers + 0,
+                                 lowers + 1, uppers + 1,
+                                 lowers + 2, uppers + 2,
+                                 lowers + 3, uppers + 3);
+
+                if ((num_vals & 1) || num_vals == 0)
+               {
+                 print_fatal_error("Bad rangeOfInteger value \"%s\" on line "
+                                   "%d.", token, linenum);
+                 goto test_error;
+               }
+
+               ippAddRanges(request, group, attr, num_vals / 2, lowers,
+                            uppers);
+             }
+             break;
+
+          case IPP_TAG_BEGIN_COLLECTION :
+             if (!strcmp(token, "{"))
+             {
+               ipp_t   *col = get_collection(vars, fp, &linenum);
+                                       /* Collection value */
+
+                if (col)
+                 lastcol = ippAddCollection(request, group, attr, col);
+               else
+                 goto test_error;
+              }
+             else
+             {
+               print_fatal_error("Bad ATTR collection value on line %d.",
+                                 linenum);
+               goto test_error;
+             }
              break;
 
          default :
@@ -569,18 +1065,45 @@ do_tests(const char *uri,                /* I - URI to connect on */
         * File...
        */
 
-       get_token(fp, filename, sizeof(filename), &linenum);
+       if (!get_token(fp, temp, sizeof(temp), &linenum))
+       {
+         print_fatal_error("Missing FILE filename on line %d.", linenum);
+         goto test_error;
+       }
+
+        expand_variables(vars, token, temp, sizeof(token));    
+       get_filename(testfile, filename, token, sizeof(filename));
       }
-      else if (!strcasecmp(token, "STATUS") &&
-               num_statuses < (int)(sizeof(statuses) / sizeof(statuses[0])))
+      else if (!strcasecmp(token, "STATUS"))
       {
        /*
         * Status...
        */
 
-       get_token(fp, token, sizeof(token), &linenum);
-       statuses[num_statuses] = ippErrorValue(token);
+        if (num_statuses >= (int)(sizeof(statuses) / sizeof(statuses[0])))
+       {
+         print_fatal_error("Too many STATUS's on line %d.", linenum);
+         goto test_error;
+       }
+
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing STATUS code on line %d.", linenum);
+         goto test_error;
+       }
+
+       if ((statuses[num_statuses].status = ippErrorValue(token)) < 0)
+       {
+         print_fatal_error("Bad STATUS code \"%s\" on line %d.", token,
+                           linenum);
+         goto test_error;
+       }
+
+        last_status = statuses + num_statuses;
        num_statuses ++;
+
+       last_status->if_defined   = NULL;
+       last_status->if_undefined = NULL;
       }
       else if (!strcasecmp(token, "EXPECT"))
       {
@@ -590,99 +1113,218 @@ do_tests(const char *uri,               /* I - URI to connect on */
 
         if (num_expects >= (int)(sizeof(expects) / sizeof(expects[0])))
         {
-         fprintf(stderr, "ipptest: Too many EXPECT's on line %d\n", linenum);
-         httpClose(http);
-         ippDelete(request);
-         return (0);
+         print_fatal_error("Too many EXPECT's on line %d.", linenum);
+         goto test_error;
         }
 
-       get_token(fp, token, sizeof(token), &linenum);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing EXPECT name on line %d.", linenum);
+         goto test_error;
+       }
 
         last_expect = expects + num_expects;
        num_expects ++;
 
+       memset(last_expect, 0, sizeof(_cups_expect_t));
+
         if (token[0] == '!')
         {
           last_expect->not_expect = 1;
           last_expect->name       = strdup(token + 1);
         }
-        else
+        else if (token[0] == '?')
         {
-          last_expect->not_expect = 0;
-         last_expect->name       = strdup(token);
+          last_expect->optional = 1;
+          last_expect->name     = strdup(token + 1);
+        }
+        else
+         last_expect->name = strdup(token);
+      }
+      else if (!strcasecmp(token, "COUNT"))
+      {
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing COUNT number on line %d.", linenum);
+         goto test_error;
+       }
+
+        if ((i = atoi(token)) <= 0)
+       {
+         print_fatal_error("Bad COUNT \"%s\" on line %d.", token, linenum);
+         goto test_error;
        }
 
-        last_expect->of_type       = NULL;
-        last_expect->same_count_as = NULL;
-        last_expect->if_defined    = NULL;
+       if (last_expect)
+         last_expect->count = i;
+       else
+       {
+         print_fatal_error("COUNT without a preceding EXPECT on line %d.",
+                           linenum);
+         goto test_error;
+       }
       }
       else if (!strcasecmp(token, "OF-TYPE"))
       {
-       get_token(fp, token, sizeof(token), &linenum);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing OF-TYPE value tag(s) on line %d.",
+                           linenum);
+         goto test_error;
+       }
 
        if (last_expect)
          last_expect->of_type = strdup(token);
        else
        {
-         fprintf(stderr,
-                 "ipptest: OF-TYPE without a preceding EXPECT on line %d\n",
-                 linenum);
-         httpClose(http);
-         ippDelete(request);
-         return (0);
+         print_fatal_error("OF-TYPE without a preceding EXPECT on line %d.",
+                           linenum);
+         goto test_error;
+       }
+      }
+      else if (!strcasecmp(token, "IN-GROUP"))
+      {
+        ipp_tag_t      in_group;       /* IN-GROUP value */
+
+
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing IN-GROUP group tag on line %d.", linenum);
+         goto test_error;
+       }
+
+        if ((in_group = ippTagValue(token)) == (ipp_tag_t)-1)
+       {
+       }
+       else if (last_expect)
+         last_expect->in_group = in_group;
+       else
+       {
+         print_fatal_error("IN-GROUP without a preceding EXPECT on line %d.",
+                           linenum);
+         goto test_error;
        }
       }
       else if (!strcasecmp(token, "SAME-COUNT-AS"))
       {
-       get_token(fp, token, sizeof(token), &linenum);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing SAME-COUNT-AS name on line %d.", linenum);
+         goto test_error;
+       }
 
        if (last_expect)
          last_expect->same_count_as = strdup(token);
        else
        {
-         fprintf(stderr,
-                 "ipptest: SAME-COUNT-AS without a preceding EXPECT on line "
-                 "%d\n", linenum);
-         httpClose(http);
-         ippDelete(request);
-         return (0);
+         print_fatal_error("SAME-COUNT-AS without a preceding EXPECT on line "
+                           "%d.", linenum);
+         goto test_error;
        }
       }
       else if (!strcasecmp(token, "IF-DEFINED"))
       {
-       get_token(fp, token, sizeof(token), &linenum);
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing IF-DEFINED name on line %d.", linenum);
+         goto test_error;
+       }
 
        if (last_expect)
          last_expect->if_defined = strdup(token);
+       else if (last_status)
+         last_status->if_defined = strdup(token);
+       else
+       {
+         print_fatal_error("IF-DEFINED without a preceding EXPECT or STATUS "
+                           "on line %d.", linenum);
+         goto test_error;
+       }
+      }
+      else if (!strcasecmp(token, "IF-UNDEFINED"))
+      {
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing IF-UNDEFINED name on line %d.", linenum);
+         goto test_error;
+       }
+
+       if (last_expect)
+         last_expect->if_undefined = strdup(token);
+       else if (last_status)
+         last_status->if_undefined = strdup(token);
+       else
+       {
+         print_fatal_error("IF-UNDEFINED without a preceding EXPECT or STATUS "
+                           "on line %d.", linenum);
+         goto test_error;
+       }
+      }
+      else if (!strcasecmp(token, "WITH-VALUE"))
+      {
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing WITH-VALUE value on line %d.", linenum);
+         goto test_error;
+       }
+
+        if (last_expect)
+       {
+         tokenptr = token + strlen(token) - 1;
+         if (token[0] == '/' && tokenptr > token && *tokenptr == '/')
+         {
+          /*
+           * WITH-VALUE is a POSIX extended regular expression.
+           */
+
+           last_expect->with_value = calloc(1, tokenptr - token);
+           last_expect->with_regex = 1;
+
+           if (last_expect->with_value)
+             memcpy(last_expect->with_value, token + 1, tokenptr - token - 1);
+         }
+         else
+         {
+          /*
+           * WITH-VALUE is a literal value...
+           */
+
+           last_expect->with_value = strdup(token);
+         }
+       }
        else
        {
-         fprintf(stderr,
-                 "ipptest: IF-DEFINED without a preceding EXPECT on line %d\n",
-                 linenum);
-         httpClose(http);
-         ippDelete(request);
-         return (0);
+         print_fatal_error("WITH-VALUE without a preceding EXPECT on line %d.",
+                           linenum);
+         goto test_error;
        }
       }
-      else if (!strcasecmp(token, "DISPLAY") &&
-               num_displayed < (int)(sizeof(displayed) / sizeof(displayed[0])))
+      else if (!strcasecmp(token, "DISPLAY"))
       {
        /*
         * Display attributes...
        */
 
-       get_token(fp, token, sizeof(token), &linenum);
+        if (num_displayed >= (int)(sizeof(displayed) / sizeof(displayed[0])))
+       {
+         print_fatal_error("Too many DISPLAY's on line %d", linenum);
+         goto test_error;
+       }
+
+       if (!get_token(fp, token, sizeof(token), &linenum))
+       {
+         print_fatal_error("Missing DISPLAY name on line %d.", linenum);
+         goto test_error;
+       }
+
        displayed[num_displayed] = strdup(token);
        num_displayed ++;
       }
       else
       {
-       fprintf(stderr,
-               "ipptest: Unexpected token %s seen on line %d - aborting "
-               "test!\n", token, linenum);
-       httpClose(http);
-       ippDelete(request);
-       return (0);
+       print_fatal_error("Unexpected token %s seen on line %d.", token,
+                         linenum);
+       goto test_error;
       }
     }
 
@@ -693,21 +1335,42 @@ do_tests(const char *uri,                /* I - URI to connect on */
     request->request.op.version[0]   = version / 10;
     request->request.op.version[1]   = version % 10;
     request->request.op.operation_id = op;
-    request->request.op.request_id   = 1;
+    request->request.op.request_id   = request_id;
 
-    if (Verbosity)
+    if (XML)
     {
-      printf("    %s:\n", ippOpString(op));
-
+      puts("<dict>");
+      puts("<key>Name</key>");
+      print_xml_string("string", name);
+      puts("<key>Operation</key>");
+      print_xml_string("string", ippOpString(op));
+      puts("<key>RequestAttributes</key>");
+      puts("<dict>");
       for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
        print_attr(attrptr);
+      puts("</dict>");
     }
+    else
+    {
+      if (Verbosity)
+      {
+        printf("    %s:\n", ippOpString(op));
+
+        for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
+          print_attr(attrptr);
+      }
 
-    printf("    %-60.60s [", name);
-    fflush(stdout);
+      printf("    %-69.69s [", name);
+      fflush(stdout);
+    }
 
-    if (Chunking)
+    if (transfer == _CUPS_TRANSFER_CHUNKED ||
+        (transfer == _CUPS_TRANSFER_AUTO && filename[0]))
     {
+     /*
+      * Send request using chunking...
+      */
+
       http_status_t status = cupsSendRequest(http, request, resource, 0);
 
       if (status == HTTP_CONTINUE && filename[0])
@@ -716,7 +1379,6 @@ do_tests(const char *uri,          /* I - URI to connect on */
         char   buffer[8192];           /* Copy buffer */
         ssize_t        bytes;                  /* Bytes read/written */
 
-
         if ((fd = open(filename, O_RDONLY | O_BINARY)) >= 0)
         {
           while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
@@ -725,7 +1387,12 @@ do_tests(const char *uri,         /* I - URI to connect on */
               break;
         }
         else
+       {
+         snprintf(buffer, sizeof(buffer), "%s: %s", filename, strerror(errno));
+         _cupsSetError(IPP_INTERNAL_ERROR, buffer, 0);
+
           status = HTTP_ERROR;
+       }
       }
 
       ippDelete(request);
@@ -738,36 +1405,107 @@ do_tests(const char *uri,               /* I - URI to connect on */
     else if (filename[0])
       response = cupsDoFileRequest(http, request, resource, filename);
     else
-      response = cupsDoIORequest(http, request, resource, -1,
-                                 Verbosity ? 1 : -1);
-
-    if (response == NULL)
-    {
-      time_t curtime;
+      response = cupsDoRequest(http, request, resource);
 
-      curtime = time(NULL);
+    request = NULL;
 
-      puts("FAIL]");
-      printf("        ERROR %04x (%s) @ %s\n", cupsLastError(),
-            cupsLastErrorString(), ctime(&curtime));
+    if (!response)
       pass = 0;
-    }
     else
     {
       if (http->version != HTTP_1_1)
         pass = 0;
 
+      if (response->request.status.version[0] != (version / 10) ||
+         response->request.status.version[1] != (version % 10) ||
+         response->request.status.request_id != request_id)
+        pass = 0;
+
       if ((attrptr = ippFindAttribute(response, "job-id",
                                       IPP_TAG_INTEGER)) != NULL)
-        job_id = attrptr->values[0].integer;
+      {
+        snprintf(temp, sizeof(temp), "%d", attrptr->values[0].integer);
+       set_variable(vars, "job-id", temp);
+      }
+
+      if ((attrptr = ippFindAttribute(response, "job-uri",
+                                      IPP_TAG_URI)) != NULL)
+       set_variable(vars, "job-uri", attrptr->values[0].string.text);
 
       if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
                                       IPP_TAG_INTEGER)) != NULL)
-        subscription_id = attrptr->values[0].integer;
+      {
+        snprintf(temp, sizeof(temp), "%d", attrptr->values[0].integer);
+       set_variable(vars, "notify-subscription-id", temp);
+      }
+
+      attrptr = response->attrs;
+      if (!attrptr || !attrptr->name ||
+         attrptr->value_tag != IPP_TAG_CHARSET ||
+         attrptr->group_tag != IPP_TAG_OPERATION ||
+         attrptr->num_values != 1 ||
+          strcmp(attrptr->name, "attributes-charset"))
+        pass = 0;
+
+      if (attrptr)
+      {
+        attrptr = attrptr->next;
+       if (!attrptr || !attrptr->name ||
+           attrptr->value_tag != IPP_TAG_LANGUAGE ||
+           attrptr->group_tag != IPP_TAG_OPERATION ||
+           attrptr->num_values != 1 ||
+           strcmp(attrptr->name, "attributes-natural-language"))
+         pass = 0;
+      }
+
+      if ((attrptr = ippFindAttribute(response, "status-message",
+                                      IPP_TAG_ZERO)) != NULL &&
+          (attrptr->value_tag != IPP_TAG_TEXT ||
+          attrptr->group_tag != IPP_TAG_OPERATION ||
+          attrptr->num_values != 1 ||
+          (attrptr->value_tag == IPP_TAG_TEXT &&
+           strlen(attrptr->values[0].string.text) > 255)))
+       pass = 0;
+
+      if ((attrptr = ippFindAttribute(response, "detailed-status-message",
+                                      IPP_TAG_ZERO)) != NULL &&
+          (attrptr->value_tag != IPP_TAG_TEXT ||
+          attrptr->group_tag != IPP_TAG_OPERATION ||
+          attrptr->num_values != 1 ||
+          (attrptr->value_tag == IPP_TAG_TEXT &&
+           strlen(attrptr->values[0].string.text) > 1023)))
+       pass = 0;
+
+      for (attrptr = response->attrs, group = attrptr->group_tag;
+           attrptr;
+          attrptr = attrptr->next)
+      {
+        if (attrptr->group_tag < group && attrptr->group_tag != IPP_TAG_ZERO)
+       {
+         pass = 0;
+         break;
+       }
+
+        if (!validate_attr(attrptr, 0))
+       {
+         pass = 0;
+         break;
+       }
+      }
 
       for (i = 0; i < num_statuses; i ++)
-        if (response->request.status.status_code == statuses[i])
+      {
+        if (statuses[i].if_defined &&
+           !get_variable(vars, statuses[i].if_defined))
+         continue;
+
+        if (statuses[i].if_undefined &&
+           get_variable(vars, statuses[i].if_undefined))
+         continue;
+
+        if (response->request.status.status_code == statuses[i].status)
          break;
+      }
 
       if (i == num_statuses && num_statuses > 0)
        pass = 0;
@@ -775,18 +1513,37 @@ do_tests(const char *uri,                /* I - URI to connect on */
       {
         for (i = num_expects, expect = expects; i > 0; i --, expect ++)
         {
-          if (expect->if_defined && !getenv(expect->if_defined))
+          if (expect->if_defined && !get_variable(vars, expect->if_defined))
+            continue;
+
+          if (expect->if_undefined && get_variable(vars, expect->if_undefined))
             continue;
 
           found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
 
-          if ((found == NULL) != expect->not_expect ||
-              (found && !expect_matches(expect, found->value_tag)))
+          if ((found && expect->not_expect) ||
+             (!found && !(expect->not_expect || expect->optional)) ||
+             (found && !expect_matches(expect, found->value_tag)) ||
+             (found && expect->in_group &&
+              found->group_tag != expect->in_group))
           {
            pass = 0;
            break;          
           }
 
+          if (found &&
+             !with_value(expect->with_value, expect->with_regex, found))
+          {
+            pass = 0;
+            break;
+          }
+
+          if (found && expect->count > 0 && found->num_values != expect->count)
+         {
+            pass = 0;
+            break;
+         }
+
           if (found && expect->same_count_as)
           {
             attrptr = ippFindAttribute(response, expect->same_count_as,
@@ -800,106 +1557,284 @@ do_tests(const char *uri,              /* I - URI to connect on */
           }
         }
       }
+    }
+
+    if (XML)
+    {
+      puts("<key>Successful</key>");
+      puts(pass ? "<true />" : "<false />");
+      puts("<key>StatusCode</key>");
+      print_xml_string("string", ippErrorString(cupsLastError()));
+      puts("<key>ResponseAttributes</key>");
+      puts("<dict>");
+      for (attrptr = response ? response->attrs : NULL;
+          attrptr;
+          attrptr = attrptr->next)
+       print_attr(attrptr);
+      puts("</dict>");
+    }
+    else
+    {
+      puts(pass ? "PASS]" : "FAIL]");
 
-      if (pass)
+      if (Verbosity && response)
       {
-       puts("PASS]");
        printf("        RECEIVED: %lu bytes in response\n",
               (unsigned long)ippLength(response));
+       printf("        status-code = %x (%s)\n", cupsLastError(),
+              ippErrorString(cupsLastError()));
 
-        if (Verbosity)
-       {
-         for (attrptr = response->attrs;
-              attrptr != NULL;
-              attrptr = attrptr->next)
-         {
-           print_attr(attrptr);
-          }
-        }
-        else if (num_displayed > 0)
+       for (attrptr = response->attrs;
+            attrptr != NULL;
+            attrptr = attrptr->next)
        {
-         for (attrptr = response->attrs;
-              attrptr != NULL;
-              attrptr = attrptr->next)
-         {
-           if (attrptr->name)
+         print_attr(attrptr);
+       }
+      }
+    }
+
+    if (pass && !XML && !Verbosity && num_displayed > 0)
+    {
+      for (attrptr = response->attrs;
+          attrptr != NULL;
+          attrptr = attrptr->next)
+       if (attrptr->name)
+         for (i = 0; i < num_displayed; i ++)
+           if (!strcmp(displayed[i], attrptr->name))
            {
-             for (i = 0; i < num_displayed; i ++)
-             {
-               if (!strcmp(displayed[i], attrptr->name))
-               {
-                 print_attr(attrptr);
-                 break;
-               }
-             }
+             print_attr(attrptr);
+             break;
            }
-         }
-        }
+    }
+    else if (!pass)
+    {
+      if (XML)
+      {
+       puts("<key>Errors</key>");
+       puts("<array>");
       }
+
+      if (http->version != HTTP_1_1)
+       print_test_error("Bad HTTP version (%d.%d)", http->version / 100,
+                        http->version % 100);
+
+      if (!response)
+       print_test_error("IPP request failed with status %s (%s)",
+                        ippErrorString(cupsLastError()),
+                        cupsLastErrorString());
       else
       {
-       puts("FAIL]");
-       printf("        RECEIVED: %lu bytes in response\n",
-              (unsigned long)ippLength(response));
+       if (response->request.status.version[0] != (version / 10) ||
+           response->request.status.version[1] != (version % 10))
+          print_test_error("Bad version %d.%d in response - expected %d.%d "
+                          "(RFC 2911 section 3.1.8).",
+                          response->request.status.version[0],
+                          response->request.status.version[1],
+                          version / 10, version % 10);
+
+       if (response->request.status.request_id != request_id)
+         print_test_error("Bad request ID %d in response - expected %d "
+                          "(RFC 2911 section 3.1.1)",
+                          response->request.status.request_id, request_id);
+
+       attrptr = response->attrs;
+       if (!attrptr)
+         print_test_error("Missing first attribute \"attributes-charset "
+                          "(charset)\" in group operation-attributes-tag "
+                          "(RFC 2911 section 3.1.4).");
+       else
+       {
+         if (!attrptr->name ||
+             attrptr->value_tag != IPP_TAG_CHARSET ||
+             attrptr->group_tag != IPP_TAG_OPERATION ||
+             attrptr->num_values != 1 ||
+             strcmp(attrptr->name, "attributes-charset"))
+           print_test_error("Bad first attribute \"%s (%s%s)\" in group %s, "
+                            "expected \"attributes-charset (charset)\" in "
+                            "group operation-attributes-tag (RFC 2911 section "
+                            "3.1.4).",
+                            attrptr->name ? attrptr->name : "(null)",
+                            attrptr->num_values > 1 ? "1setOf " : "",
+                            ippTagString(attrptr->value_tag),
+                            ippTagString(attrptr->group_tag));
+
+         attrptr = attrptr->next;
+         if (!attrptr)
+           print_test_error("Missing second attribute \"attributes-natural-"
+                            "language (naturalLanguage)\" in group "
+                            "operation-attributes-tag (RFC 2911 section "
+                            "3.1.4).");
+         else if (!attrptr->name ||
+                  attrptr->value_tag != IPP_TAG_LANGUAGE ||
+                  attrptr->group_tag != IPP_TAG_OPERATION ||
+                  attrptr->num_values != 1 ||
+                  strcmp(attrptr->name, "attributes-natural-language"))
+           print_test_error("Bad first attribute \"%s (%s%s)\" in group %s, "
+                            "expected \"attributes-natural-language "
+                            "(naturalLanguage)\" in group "
+                            "operation-attributes-tag (RFC 2911 section "
+                            "3.1.4).",
+                            attrptr->name ? attrptr->name : "(null)",
+                            attrptr->num_values > 1 ? "1setOf " : "",
+                            ippTagString(attrptr->value_tag),
+                            ippTagString(attrptr->group_tag));
+        }
+
+       if ((attrptr = ippFindAttribute(response, "status-message",
+                                        IPP_TAG_ZERO)) != NULL)
+       {
+         if (attrptr->value_tag != IPP_TAG_TEXT)
+           print_test_error("status-message (text(255)) has wrong value tag "
+                            "%s (RFC 2911 section 3.1.6.2).",
+                            ippTagString(attrptr->value_tag));
+         if (attrptr->group_tag != IPP_TAG_OPERATION)
+           print_test_error("status-message (text(255)) has wrong group tag "
+                            "%s (RFC 2911 section 3.1.6.2).",
+                            ippTagString(attrptr->group_tag));
+         if (attrptr->num_values != 1)
+           print_test_error("status-message (text(255)) has %d values "
+                            "(RFC 2911 section 3.1.6.2).",
+                            attrptr->num_values);
+         if (attrptr->value_tag == IPP_TAG_TEXT &&
+             strlen(attrptr->values[0].string.text) > 255)
+           print_test_error("status-message (text(255)) has bad length %d"
+                            " (RFC 2911 section 3.1.6.2).",
+                            (int)strlen(attrptr->values[0].string.text));
+        }
 
-        if (http->version != HTTP_1_1)
-          printf("        BAD HTTP VERSION (%d.%d)\n", http->version / 100,
-                 http->version % 100);
+       if ((attrptr = ippFindAttribute(response, "detailed-status-message",
+                                        IPP_TAG_ZERO)) != NULL)
+       {
+         if (attrptr->value_tag != IPP_TAG_TEXT)
+           print_test_error("detailed-status-message (text(MAX)) has wrong "
+                            "value tag %s (RFC 2911 section 3.1.6.3).",
+                            ippTagString(attrptr->value_tag));
+         if (attrptr->group_tag != IPP_TAG_OPERATION)
+           print_test_error("detailed-status-message (text(MAX)) has wrong "
+                            "group tag %s (RFC 2911 section 3.1.6.3).",
+                            ippTagString(attrptr->group_tag));
+         if (attrptr->num_values != 1)
+           print_test_error("detailed-status-message (text(MAX)) has %d values"
+                            " (RFC 2911 section 3.1.6.3).",
+                            attrptr->num_values);
+         if (attrptr->value_tag == IPP_TAG_TEXT &&
+             strlen(attrptr->values[0].string.text) > 1023)
+           print_test_error("detailed-status-message (text(MAX)) has bad "
+                            "length %d (RFC 2911 section 3.1.6.3).",
+                            (int)strlen(attrptr->values[0].string.text));
+        }
+
+       for (attrptr = response->attrs, group = attrptr->group_tag;
+            attrptr;
+            attrptr = attrptr->next)
+       {
+         if (attrptr->group_tag < group && attrptr->group_tag != IPP_TAG_ZERO)
+           print_test_error("Attribute groups out of order (%s < %s)",
+                            ippTagString(attrptr->group_tag),
+                            ippTagString(group));
+
+         validate_attr(attrptr, 1);
+       }
 
        for (i = 0; i < num_statuses; i ++)
-          if (response->request.status.status_code == statuses[i])
+       {
+         if (statuses[i].if_defined &&
+             !get_variable(vars, statuses[i].if_defined))
+           continue;
+
+         if (statuses[i].if_undefined &&
+             get_variable(vars, statuses[i].if_undefined))
+           continue;
+
+         if (response->request.status.status_code == statuses[i].status)
            break;
+        }
 
        if (i == num_statuses && num_statuses > 0)
-         puts("        BAD STATUS");
+       {
+         print_test_error("Bad status-code (%s)",
+                          ippErrorString(cupsLastError()));
+         print_test_error("status-message=\"%s\"", cupsLastErrorString());
+        }
 
-       printf("        status-code = %04x (%s)\n",
-              cupsLastError(), ippErrorString(cupsLastError()));
+       for (i = num_expects, expect = expects; i > 0; i --, expect ++)
+       {
+         if (expect->if_defined && !get_variable(vars, expect->if_defined))
+           continue;
+
+         if (expect->if_undefined && get_variable(vars, expect->if_undefined))
+           continue;
+      
+         found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
+
+         if (found && expect->not_expect)
+            print_test_error("NOT EXPECTED: %s", expect->name);
+         else if (!found && !(expect->not_expect || expect->optional))
+           print_test_error("EXPECTED: %s", expect->name);
+         else if (found)
+         {
+           if (!expect_matches(expect, found->value_tag))
+             print_test_error("EXPECTED: %s OF-TYPE %s (got %s)", 
+                              expect->name, expect->of_type,
+                              ippTagString(found->value_tag));
 
-        for (i = num_expects, expect = expects; i > 0; i --, expect ++)
-        {
-          if (expect->if_defined && !getenv(expect->if_defined))
-            continue;
+           if (expect->in_group && found->group_tag != expect->in_group)
+             print_test_error("EXPECTED: %s IN-GROUP %s (got %s).",
+                              expect->name, ippTagString(expect->in_group),
+                              ippTagString(found->group_tag));
 
-          found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
+           if (!with_value(expect->with_value, expect->with_regex, found))
+           {
+             if (expect->with_regex)
+               print_test_error("EXPECTED: %s WITH-VALUE /%s/",
+                                expect->name, expect->with_value);         
+             else
+               print_test_error("EXPECTED: %s WITH-VALUE \"%s\"",
+                                expect->name, expect->with_value);         
+           }
 
-          if ((found == NULL) != expect->not_expect)
-          {
-            if (expect->not_expect)
-             printf("        NOT EXPECTED: %s\n", expect->name);
-           else
-             printf("        EXPECTED: %s\n", expect->name);
-         }
-          else if (found)
-          {
-            if (!expect_matches(expect, found->value_tag))
-              printf("        EXPECTED: %s of type %s but got %s\n", 
-                     expect->name, expect->of_type,
-                     ippTagString(found->value_tag));
-           else if (expect->same_count_as)
+           if (expect->count > 0 && found->num_values != expect->count)
+           {
+             print_test_error("EXPECTED: %s COUNT %d (got %d)", expect->name,
+                              expect->count, found->num_values);
+           }
+
+           if (expect->same_count_as)
            {
              attrptr = ippFindAttribute(response, expect->same_count_as,
                                         IPP_TAG_ZERO);
-  
+
              if (!attrptr)
-               printf("        EXPECTED: %s (%d values) same count as %s "
-                      "(not returned)\n", 
-                      expect->name, found->num_values, expect->same_count_as);
+               print_test_error("EXPECTED: %s (%d values) SAME-COUNT-AS %s "
+                                "(not returned)", expect->name,
+                                found->num_values, expect->same_count_as);
              else if (attrptr->num_values != found->num_values)
-               printf("        EXPECTED: %s (%d values) same count as %s "
-                      "(%d values)\n", 
-                      expect->name, found->num_values, expect->same_count_as,
-                      attrptr->num_values);
+               print_test_error("EXPECTED: %s (%d values) SAME-COUNT-AS %s "
+                                "(%d values)", expect->name, found->num_values,
+                                expect->same_count_as, attrptr->num_values);
            }
          }
-        }
-
-       for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
-         print_attr(attrptr);
+       }
       }
 
-      ippDelete(response);
+      if (XML)
+       puts("</array>");
+    }
+
+    if (XML)
+      puts("</dict>");
+
+    ippDelete(response);
+    response = NULL;
+
+    for (i = 0; i < num_statuses; i ++)
+    {
+      if (statuses[i].if_defined)
+        free(statuses[i].if_defined);
+      if (statuses[i].if_undefined)
+        free(statuses[i].if_undefined);
     }
+    num_statuses = 0;
 
     for (i = num_expects, expect = expects; i > 0; i --, expect ++)
     {
@@ -910,7 +1845,17 @@ do_tests(const char *uri,         /* I - URI to connect on */
         free(expect->same_count_as);
       if (expect->if_defined)
         free(expect->if_defined);
+      if (expect->if_undefined)
+        free(expect->if_undefined);  
+      if (expect->with_value)
+        free(expect->with_value);
     }
+    num_expects = 0;
+
+    for (i = 0; i < num_displayed; i ++)
+      free(displayed[i]);
+    num_displayed = 0;
+
     if (!pass)
       break;
   }
@@ -919,12 +1864,155 @@ do_tests(const char *uri,               /* I - URI to connect on */
   httpClose(http);
 
   return (pass);
-}
 
+ /*
+  * If we get here there was a fatal test error...
+  */
 
-/*
- * 'expect_matches()' - Return true if the tag matches the specification.
- */
+  test_error:
+
+  if (fp)
+    fclose(fp);
+
+  httpClose(http);
+  ippDelete(request);
+  ippDelete(response);
+
+  for (i = 0; i < num_statuses; i ++)
+  {
+    if (statuses[i].if_defined)
+      free(statuses[i].if_defined);
+    if (statuses[i].if_undefined)
+      free(statuses[i].if_undefined);
+  }
+
+  for (i = num_expects, expect = expects; i > 0; i --, expect ++)
+  {
+    free(expect->name);
+    if (expect->of_type)
+      free(expect->of_type);
+    if (expect->same_count_as)
+      free(expect->same_count_as);
+    if (expect->if_defined)
+      free(expect->if_defined);
+    if (expect->if_undefined)
+      free(expect->if_undefined);  
+    if (expect->with_value)
+      free(expect->with_value);
+  }
+
+  for (i = 0; i < num_displayed; i ++)
+    free(displayed[i]);
+
+  return (0);
+}
+
+
+/*
+ * 'expand_variables()' - Expand variables in a string.
+ */
+
+static void
+expand_variables(_cups_vars_t *vars,   /* I - Variables */
+                 char         *dst,    /* I - Destination string buffer */
+                const char   *src,     /* I - Source string */
+                size_t       dstsize)  /* I - Size of destination buffer */
+{
+  char         *dstptr,                /* Pointer into destination */
+               *dstend,                /* End of destination */
+               temp[256],              /* Temporary string */
+               *tempptr;               /* Pointer into temporary string */
+  const char   *value;                 /* Value to substitute */
+
+
+  dstptr = dst;
+  dstend = dst + dstsize - 1;
+
+  while (*src && dstptr < dstend)
+  {
+    if (*src == '$')
+    {
+     /*
+      * Substitute a string/number...
+      */
+
+      if (!strncmp(src, "$$", 2))
+      {
+        value = "$";
+       src   += 2;
+      }
+      else if (!strncmp(src, "$ENV[", 5))
+      {
+       strlcpy(temp, src + 5, sizeof(temp));
+
+       for (tempptr = temp; *tempptr; tempptr ++)
+         if (*tempptr == ']')
+           break;
+
+        if (*tempptr)
+         *tempptr++ = '\0';
+
+       value = getenv(temp);
+        src   += tempptr - temp + 5;
+      }
+      else if (vars)
+      {
+       strlcpy(temp, src + 1, sizeof(temp));
+
+       for (tempptr = temp; *tempptr; tempptr ++)
+         if (!isalnum(*tempptr & 255) && *tempptr != '-' && *tempptr != '_')
+           break;
+
+        if (*tempptr)
+         *tempptr = '\0';
+
+       if (!strcmp(temp, "uri"))
+         value = vars->uri;
+       else if (!strcmp(temp, "filename"))
+         value = vars->filename;
+       else if (!strcmp(temp, "scheme") || !strcmp(temp, "method"))
+         value = vars->scheme;
+       else if (!strcmp(temp, "username"))
+         value = vars->userpass;
+       else if (!strcmp(temp, "hostname"))
+         value = vars->hostname;
+       else if (!strcmp(temp, "port"))
+       {
+         snprintf(temp, sizeof(temp), "%d", vars->port);
+         value = temp;
+       }
+       else if (!strcmp(temp, "resource"))
+         value = vars->resource;
+       else if (!strcmp(temp, "user"))
+         value = cupsUser();
+       else
+         value = get_variable(vars, temp);
+
+        src += tempptr - temp + 1;
+      }
+      else
+      {
+        value = "$";
+       src ++;
+      }
+
+      if (value)
+      {
+        strlcpy(dstptr, value, dstend - dstptr + 1);
+       dstptr += strlen(dstptr);
+      }
+    }
+    else
+      *dstptr++ = *src++;
+  }
+
+  *dstptr = '\0';
+}
+
+
+/*
+ * 'expect_matches()' - Return true if the tag matches the specification.
+ */
  
 static int                             /* O - 1 if matches, 0 otherwise */
 expect_matches(
@@ -933,7 +2021,8 @@ expect_matches(
 {
   int  match;                          /* Match? */
   char *of_type,                       /* Type name to match */
-       *next;                          /* Next name to match */
+       *next,                          /* Next name to match */
+       sep;                            /* Separator character */
 
 
  /*
@@ -945,7 +2034,7 @@ expect_matches(
 
  /*
   * Parse the "of_type" value since the string can contain multiple attribute
-  * types separated by "|"...
+  * types separated by "," or "|"...
   */
 
   for (of_type = expect->of_type, match = 0; !match && of_type; of_type = next)
@@ -954,7 +2043,9 @@ expect_matches(
     * Find the next separator, and set it (temporarily) to nul if present.
     */
 
-    if ((next = strchr(of_type, '|')) != NULL)
+    for (next = of_type; *next && *next != '|' && *next != ','; next ++);
+
+    if ((sep = *next) != '\0')
       *next = '\0';
   
    /*
@@ -974,14 +2065,299 @@ expect_matches(
     * Restore the separator if we have one...
     */
 
-    if (next)
-      *next++ = '|';
+    if (sep)
+      *next++ = sep;
   }
 
   return (match);
 }
 
 
+/*
+ * 'get_collection()' - Get a collection value from the current test file.
+ */
+
+static ipp_t *                         /* O  - Collection value */
+get_collection(_cups_vars_t *vars,     /* I  - Variables */
+               FILE         *fp,       /* I  - File to read from */
+              int          *linenum)   /* IO - Line number */
+{
+  char         token[1024],            /* Token from file */
+               temp[1024],             /* Temporary string */
+               attr[128];              /* Attribute name */
+  ipp_tag_t    value;                  /* Current value type */
+  ipp_t                *col = ippNew();        /* Collection value */
+  ipp_attribute_t *lastcol = NULL;     /* Last collection attribute */
+
+
+  while (get_token(fp, token, sizeof(token), linenum) != NULL)
+  {
+    if (!strcmp(token, "}"))
+      break;
+    else if (!strcmp(token, "{") && lastcol)
+    {
+     /*
+      * Another collection value
+      */
+
+      ipp_t    *subcol = get_collection(vars, fp, linenum);
+                                       /* Collection value */
+
+      if (subcol)
+      {
+       ipp_attribute_t *tempcol;       /* Pointer to new buffer */
+
+
+       /*
+       * Reallocate memory...
+       */
+
+       if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) +
+                                       (lastcol->num_values + 1) *
+                                       sizeof(ipp_value_t))) == NULL)
+       {
+         print_fatal_error("Unable to allocate memory on line %d.", *linenum);
+         goto col_error;
+       }
+
+       if (tempcol != lastcol)
+       {
+        /*
+         * Reset pointers in the list...
+         */
+
+         if (col->prev)
+           col->prev->next = tempcol;
+         else
+           col->attrs = tempcol;
+
+         lastcol = col->current = col->last = tempcol;
+       }
+
+       lastcol->values[lastcol->num_values].collection = subcol;
+       lastcol->num_values ++;
+      }
+      else
+       goto col_error;
+    }
+    else if (!strcasecmp(token, "MEMBER"))
+    {
+     /*
+      * Attribute...
+      */
+
+      lastcol = NULL;
+
+      if (!get_token(fp, token, sizeof(token), linenum))
+      {
+       print_fatal_error("Missing MEMBER value tag on line %d.", *linenum);
+       goto col_error;
+      }
+
+      if ((value = ippTagValue(token)) < 0)
+      {
+       print_fatal_error("Bad MEMBER value tag \"%s\" on line %d.", token,
+                         *linenum);
+       goto col_error;
+      }
+
+      if (!get_token(fp, attr, sizeof(attr), linenum))
+      {
+       print_fatal_error("Missing MEMBER name on line %d.", *linenum);
+       goto col_error;
+      }
+
+      if (!get_token(fp, temp, sizeof(temp), linenum))
+      {
+       print_fatal_error("Missing MEMBER value on line %d.", *linenum);
+       goto col_error;
+      }
+
+      expand_variables(vars, token, temp, sizeof(token));
+
+      switch (value)
+      {
+       case IPP_TAG_BOOLEAN :
+           if (!strcasecmp(token, "true"))
+             ippAddBoolean(col, IPP_TAG_ZERO, attr, 1);
+           else
+             ippAddBoolean(col, IPP_TAG_ZERO, attr, atoi(token));
+           break;
+
+       case IPP_TAG_INTEGER :
+       case IPP_TAG_ENUM :
+           ippAddInteger(col, IPP_TAG_ZERO, value, attr, atoi(token));
+           break;
+
+       case IPP_TAG_RESOLUTION :
+           {
+             int       xres,           /* X resolution */
+                       yres;           /* Y resolution */
+             char      units[6];       /* Units */
+
+             if (sscanf(token, "%dx%d%5s", &xres, &yres, units) != 3 ||
+                 (strcasecmp(units, "dpi") && strcasecmp(units, "dpc") &&
+                  strcasecmp(units, "other")))
+             {
+               print_fatal_error("Bad resolution value \"%s\" on line %d.",
+                                 token, *linenum);
+               goto col_error;
+             }
+
+             if (!strcasecmp(units, "dpi"))
+               ippAddResolution(col, IPP_TAG_ZERO, attr, xres, yres,
+                                IPP_RES_PER_INCH);
+             else if (!strcasecmp(units, "dpc"))
+               ippAddResolution(col, IPP_TAG_ZERO, attr, xres, yres,
+                                IPP_RES_PER_CM);
+             else
+               ippAddResolution(col, IPP_TAG_ZERO, attr, xres, yres,
+                                (ipp_res_t)0);
+           }
+           break;
+
+       case IPP_TAG_RANGE :
+           {
+             int       lowers[4],      /* Lower value */
+                       uppers[4],      /* Upper values */
+                       num_vals;       /* Number of values */
+
+
+             num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d",
+                               lowers + 0, uppers + 0,
+                               lowers + 1, uppers + 1,
+                               lowers + 2, uppers + 2,
+                               lowers + 3, uppers + 3);
+
+             if ((num_vals & 1) || num_vals == 0)
+             {
+               print_fatal_error("Bad rangeOfInteger value \"%s\" on line %d.",
+                                 token, *linenum);
+               goto col_error;
+             }
+
+             ippAddRanges(col, IPP_TAG_ZERO, attr, num_vals / 2, lowers,
+                          uppers);
+           }
+           break;
+
+       case IPP_TAG_BEGIN_COLLECTION :
+           if (!strcmp(token, "{"))
+           {
+             ipp_t     *subcol = get_collection(vars, fp, linenum);
+                                     /* Collection value */
+
+             if (subcol)
+               lastcol = ippAddCollection(col, IPP_TAG_ZERO, attr, subcol);
+             else
+               goto col_error;
+           }
+           else
+           {
+             print_fatal_error("Bad collection value on line %d.", *linenum);
+             goto col_error;
+           }
+           break;
+
+       default :
+           if (!strchr(token, ','))
+             ippAddString(col, IPP_TAG_ZERO, value, attr, NULL, token);
+           else
+           {
+            /*
+             * Multiple string values...
+             */
+
+             int       num_values;     /* Number of values */
+             char      *values[100],   /* Values */
+                       *ptr;           /* Pointer to next value */
+
+
+             values[0]  = token;
+             num_values = 1;
+
+             for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
+             {
+               *ptr++ = '\0';
+               values[num_values] = ptr;
+               num_values ++;
+             }
+
+             ippAddStrings(col, IPP_TAG_ZERO, value, attr, num_values,
+                           NULL, (const char **)values);
+           }
+           break;
+      }
+    }
+  }
+
+  return (col);
+
+ /*
+  * If we get here there was a parse error; free memory and return.
+  */
+
+  col_error:
+
+  ippDelete(col);
+
+  return (NULL);
+}
+
+
+/*
+ * 'get_filename()' - Get a filename based on the current test file.
+ */
+
+static char *                          /* O - Filename */
+get_filename(const char *testfile,     /* I - Current test file */
+             char       *dst,          /* I - Destination filename */
+            const char *src,           /* I - Source filename */
+             size_t     dstsize)       /* I - Size of destination buffer */
+{
+  char                 *dstptr;        /* Pointer into destination */
+  _cups_globals_t      *cg = _cupsGlobals();
+                                       /* Global data */
+
+
+  if (*src == '<' && src[strlen(src) - 1] == '>')
+  {
+   /*
+    * Map <filename> to CUPS_DATADIR/ipptest/filename...
+    */
+
+    snprintf(dst, dstsize, "%s/ipptest/%s", cg->cups_datadir, src + 1);
+    dstptr = dst + strlen(dst) - 1;
+    if (*dstptr == '>')
+      *dstptr = '\0';
+  }
+  else if (*src == '/' || !strchr(testfile, '/'))
+  {
+   /*
+    * Use the path as-is...
+    */
+
+    strlcpy(dst, src, dstsize);
+  }
+  else
+  {
+   /*
+    * Make path relative to testfile...
+    */
+
+    strlcpy(dst, testfile, dstsize);
+    if ((dstptr = strrchr(dst, '/')) != NULL)
+      dstptr ++;
+    else
+      dstptr = dst; /* Should never happen */
+
+    strlcpy(dstptr, src, dstsize - (dstptr - dst));
+  }
+
+  return (dst);
+}
+
+
 /*
  * 'get_token()' - Get a token from a file.
  */
@@ -1019,7 +2395,7 @@ get_token(FILE *fp,                       /* I  - File to read from */
     else if (ch == '\'' || ch == '\"')
     {
      /*
-      * Quoted text...
+      * Quoted text or regular expression...
       */
 
       quote  = ch;
@@ -1027,12 +2403,27 @@ get_token(FILE *fp,                     /* I  - File to read from */
       bufend = buf + buflen - 1;
 
       while ((ch = getc(fp)) != EOF)
-       if (ch == quote)
+      {
+        if (ch == '\\')
+       {
+        /*
+         * Escape next character...
+         */
+
+         if (bufptr < bufend)
+           *bufptr++ = ch;
+
+         if ((ch = getc(fp)) != EOF && bufptr < bufend)
+           *bufptr++ = ch;
+       }
+       else if (ch == quote)
           break;
        else if (bufptr < bufend)
           *bufptr++ = ch;
+      }
 
       *bufptr = '\0';
+
       return (buf);
     }
     else if (ch == '#')
@@ -1066,14 +2457,61 @@ get_token(FILE *fp,                     /* I  - File to read from */
 
       if (ch == '#')
         ungetc(ch, fp);
-
+      else if (ch == '\n')
+        (*linenum) ++;
+        
       *bufptr = '\0';
+
       return (buf);
     }
   }
 }
 
 
+/*
+ * 'get_variable()' - Get the value of a variable.
+ */
+
+static char *                          /* O - Value or NULL */
+get_variable(_cups_vars_t *vars,       /* I - Variables */
+             const char   *name)       /* I - Variable name */
+{
+  _cups_var_t  key,                    /* Search key */
+               *match;                 /* Matching variable, if any */
+
+
+  key.name = (char *)name;
+  match    = cupsArrayFind(vars->vars, &key);
+
+  return (match ? match->value : NULL);
+}
+
+
+/*
+ * 'iso_date()' - Return an ISO 8601 date/time string for the given IPP dateTime
+ *                value.
+ */
+
+static char *                          /* O - ISO 8601 date/time string */
+iso_date(ipp_uchar_t *date)            /* I - IPP (RFC 1903) date/time value */
+{
+  unsigned     year = (date[0] << 8) + date[1];
+                                       /* Year */
+  static char  buffer[255];            /* String buffer */
+
+
+  if (date[9] == 0 && date[10] == 0)
+    snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02uZ",
+            year, date[2], date[3], date[4], date[5], date[6]);
+  else
+    snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
+            year, date[2], date[3], date[4], date[5], date[6],
+            date[8], date[9], date[10]);
+
+  return (buffer);
+}
+
+
 /*
  * 'print_attr()' - Print an attribute on the screen.
  */
@@ -1081,87 +2519,161 @@ get_token(FILE *fp,                    /* I  - File to read from */
 static void
 print_attr(ipp_attribute_t *attr)      /* I - Attribute to print */
 {
-  int          i;                      /* Looping var */
+  int                  i;              /* Looping var */
+  ipp_attribute_t      *colattr;       /* Collection attribute */
 
 
-  if (attr->name == NULL)
+  if (XML)
   {
-    puts("        -- separator --");
-    return;
+    if (!attr->name)
+    {
+      printf("<key>%s</key>\n<true />\n", ippTagString(attr->group_tag));
+      return;
+    }
+
+    print_xml_string("key", attr->name);
+    if (attr->num_values > 1)
+      puts("<array>");
   }
+  else
+  {
+    if (!attr->name)
+    {
+      puts("        -- separator --");
+      return;
+    }
 
-  printf("        %s (%s%s) = ", attr->name,
-         attr->num_values > 1 ? "1setOf " : "",
-        ippTagString(attr->value_tag));
+    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 ++)
-         printf("%d ", attr->values[i].integer);
+         if (XML)
+           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 (attr->values[i].boolean)
-           printf("true ");
+         if (XML)
+           puts(attr->values[i].boolean ? "<true />" : "<false />");
+         else if (attr->values[i].boolean)
+           fputs("true ", stdout);
          else
-           printf("false ");
-       break;
-
-    case IPP_TAG_NOVALUE :
-       printf("novalue");
+           fputs("false ", stdout);
        break;
 
     case IPP_TAG_RANGE :
        for (i = 0; i < attr->num_values; i ++)
-         printf("%d-%d ", attr->values[i].range.lower,
-                attr->values[i].range.upper);
+         if (XML)
+           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 ++)
-         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_STRING :
-    case IPP_TAG_TEXT :
-    case IPP_TAG_NAME :
-    case IPP_TAG_KEYWORD :
-    case IPP_TAG_CHARSET :
+         if (XML)
+           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 (XML)
+            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 ++)
-         printf("\"%s\" ", attr->values[i].string.text);
+         if (XML)
+           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 ++)
-         printf("\"%s\",%s ", attr->values[i].string.text,
-                attr->values[i].string.charset);
+         if (XML)
+         {
+           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_BEGIN_COLLECTION :
        for (i = 0; i < attr->num_values; i ++)
        {
-         if (i)
-           putchar(' ');
+         if (XML)
+         {
+           puts("<dict>");
+           for (colattr = attr->values[i].collection->attrs;
+                colattr;
+                colattr = colattr->next)
+             print_attr(colattr);
+           puts("</dict>");
+         }
+         else
+         {
+           if (i)
+             putchar(' ');
 
-         print_col(attr->values[i].collection);
+           print_col(attr->values[i].collection);
+          }
        }
        break;
 
     default :
-       break; /* anti-compiler-warning-code */
+       if (XML)
+         printf("<string>&lt;&lt;%s&gt;&gt;</string>\n",
+                ippTagString(attr->value_tag));
+       else
+         fputs(ippTagString(attr->value_tag), stdout);
+       break;
   }
 
-  putchar('\n');
+  if (XML)
+  {
+    if (attr->num_values > 1)
+      puts("</array>");
+  }
+  else
+    putchar('\n');
 }
 
 
@@ -1176,10 +2688,10 @@ print_col(ipp_t *col)                   /* I - Collection attribute to print */
   ipp_attribute_t      *attr;          /* Current attribute in collection */
 
 
-  putchar('{');
+  fputs("{ ", stdout);
   for (attr = col->attrs; attr; attr = attr->next)
   {
-    printf("%s(%s%s)=", attr->name, attr->num_values > 1 ? "1setOf " : "",
+    printf("%s (%s%s) = ", attr->name, attr->num_values > 1 ? "1setOf " : "",
           ippTagString(attr->value_tag));
 
     switch (attr->value_tag)
@@ -1252,6 +2764,187 @@ print_col(ipp_t *col)                   /* I - Collection attribute to print */
 }
 
 
+/*
+ * 'print_fatal_error()' - Print a fatal error message.
+ */
+
+static void
+print_fatal_error(const char *s,       /* I - Printf-style format string */
+                  ...)                 /* I - Additional arguments as needed */
+{
+  char         buffer[10240];          /* Format buffer */
+  va_list      ap;                     /* Pointer to arguments */
+
+
+ /*
+  * Format the error message...
+  */
+
+  va_start(ap, s);
+  vsnprintf(buffer, sizeof(buffer), s, ap);
+  va_end(ap);
+
+ /*
+  * Then output it...
+  */
+
+  if (XML)
+  {
+    print_xml_header();
+    print_xml_trailer(0, buffer);
+  }
+  else
+    _cupsLangPrintf(stderr, "ipptest: %s\n", buffer);
+}
+
+
+/*
+ * 'print_test_error()' - Print a test error message.
+ */
+
+static void
+print_test_error(const char *s,                /* I - Printf-style format string */
+                 ...)                  /* I - Additional arguments as needed */
+{
+  char         buffer[10240];          /* Format buffer */
+  va_list      ap;                     /* Pointer to arguments */
+
+
+ /*
+  * Format the error message...
+  */
+
+  va_start(ap, s);
+  vsnprintf(buffer, sizeof(buffer), s, ap);
+  va_end(ap);
+
+ /*
+  * Then output it...
+  */
+
+  if (XML)
+    print_xml_string("string", buffer);
+  else
+    printf("        %s\n", buffer);
+}
+
+
+/*
+ * 'print_xml_header()' - Print a standard XML plist header.
+ */
+
+static void
+print_xml_header(void)
+{
+  if (!XMLHeader)
+  {
+    puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    puts("<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
+         "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+    puts("<plist version=\"1.0\">");
+    puts("<dict>");
+    puts("<key>Transfer</key>");
+    printf("<string>%s</string>\n",
+           Transfer == _CUPS_TRANSFER_AUTO ? "auto" :
+              Transfer == _CUPS_TRANSFER_CHUNKED ? "chunked" : "length");
+    puts("<key>Tests</key>");
+    puts("<array>");
+
+    XMLHeader = 1;
+  }
+}
+
+
+/*
+ * 'print_xml_string()' - Print an XML string with escaping.
+ */
+
+static void
+print_xml_string(const char *element,  /* I - Element name or NULL */
+                const char *s)         /* I - String to print */
+{
+  if (element)
+    printf("<%s>", element);
+
+  while (*s)
+  {
+    if (*s == '&')
+      fputs("&amp;", stdout);
+    else if (*s == '<')
+      fputs("&lt;", stdout);
+    else if (*s == '>')
+      fputs("&gt;", stdout);
+    else
+      putchar(*s);
+
+    s ++;
+  }
+
+  if (element)
+    printf("</%s>\n", element);
+}
+
+
+/*
+ * 'print_xml_trailer()' - Print the XML trailer with success/fail value.
+ */
+
+static void
+print_xml_trailer(int        success,  /* I - 1 on success, 0 on failure */
+                  const char *message) /* I - Error message or NULL */
+{
+  if (XMLHeader)
+  {
+    puts("</array>");
+    puts("<key>Successful</key>");
+    puts(success ? "<true />" : "<false />");
+    if (message)
+    {
+      puts("<key>ErrorMessage</key>");
+      print_xml_string("string", message);
+    }
+    puts("</dict>");
+    puts("</plist>");
+
+    XMLHeader = 0;
+  }
+}
+
+
+/*
+ * 'set_variable()' - Set a variable value.
+ */
+
+static void
+set_variable(_cups_vars_t *vars,       /* I - Variables */
+             const char   *name,       /* I - Variable name */
+             const char   *value)      /* I - Value string */
+{
+  _cups_var_t  key,                    /* Search key */
+               *var;                   /* New variable */
+
+
+  key.name = (char *)name;
+  if ((var = cupsArrayFind(vars->vars, &key)) != NULL)
+  {
+    free(var->value);
+    var->value = strdup(value);
+  }
+  else if ((var = malloc(sizeof(_cups_var_t))) == NULL)
+  {
+    print_fatal_error("Unable to allocate memory for variable \"%s\".", name);
+    exit(1);
+  }
+  else
+  {
+    var->name  = strdup(name);
+    var->value = strdup(value);
+
+    cupsArrayAdd(vars->vars, var);
+  }
+}
+
+
 /*
  * 'usage()' - Show program usage.
  */
@@ -1259,20 +2952,902 @@ print_col(ipp_t *col)                  /* I - Collection attribute to print */
 static void
 usage(void)
 {
-  fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr);
-  fputs("Options:\n", stderr);
-  fputs("\n", stderr);
-  fputs("-c             Send requests using chunking.\n", stderr);
-  fputs("-d name=value  Define variable.\n", stderr);
-  fputs("-i seconds     Repeat the last test file with the given interval.\n",
-        stderr);
-  fputs("-v             Show all attributes in response, even on success.\n",
-        stderr);
+  _cupsLangPuts(stderr,
+                _("Usage: ipptest [options] URI filename.test [ ... "
+                 "filenameN.test ]\n"
+                 "\n"
+                 "Options:\n"
+                 "\n"
+                 "-E             Test with encryption.\n"
+                 "-V version     Set default IPP version.\n"
+                 "-X             Produce XML instead of plain text.\n"
+                 "-c             Send requests using chunking (default)\n"
+                 "-d name=value  Define variable.\n"
+                 "-f filename    Set default test file.\n"
+                 "-i seconds     Repeat the last test file with the given "
+                 "interval.\n"
+                 "-l             Send requests using content-length\n"
+                 "-v             Show all attributes sent and received.\n"));
 
   exit(1);
 }
 
 
 /*
- * End of "$Id: ipptest.c 7847 2008-08-19 04:22:14Z mike $".
+ * 'validate_attr()' - Determine whether an attribute is valid.
+ */
+
+static int                             /* O - 1 if valid, 0 otherwise */
+validate_attr(ipp_attribute_t *attr,   /* I - Attribute to validate */
+              int             print)   /* I - 1 = report issues to stdout */
+{
+  int          i;                      /* Looping var */
+  char         scheme[64],             /* Scheme from URI */
+               userpass[256],          /* Username/password from URI */
+               hostname[256],          /* Hostname from URI */
+               resource[1024];         /* Resource from URI */
+  int          port,                   /* Port number from URI */
+               uri_status,             /* URI separation status */
+               valid = 1;              /* Is the attribute valid? */
+  const char   *ptr;                   /* Pointer into string */
+  ipp_attribute_t *colattr;            /* Collection attribute */
+  regex_t      re;                     /* Regular expression */
+  ipp_uchar_t  *date;                  /* Current date value */
+
+
+ /*
+  * Skip separators.
+  */
+
+  if (!attr->name)
+    return (1);
+
+ /*
+  * Validate the attribute name.
+  */
+
+  for (ptr = attr->name; *ptr; ptr ++)
+    if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' && *ptr != '_')
+      break;
+
+  if (*ptr || ptr == attr->name)
+  {
+    valid = 0;
+
+    if (print)
+      print_test_error("\"%s\": Bad attribute name - invalid character (RFC "
+                      "2911 section 4.1.3).", attr->name);
+  }
+
+  if ((ptr - attr->name) > 255)
+  {
+    valid = 0;
+
+    if (print)
+      print_test_error("\"%s\": Bad attribute name - bad length (RFC 2911 "
+                      "section 4.1.3).", attr->name);
+  }
+
+  switch (attr->value_tag)
+  {
+    case IPP_TAG_INTEGER :
+        break;
+
+    case IPP_TAG_BOOLEAN :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].boolean != 0 &&
+             attr->values[i].boolean != 1)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad boolen value %d (RFC 2911 section "
+                              "4.1.10).", attr->name, attr->values[i].boolean);
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_ENUM :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].integer < 1)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad enum value %d - out of range "
+                              "(RFC 2911 section 4.1.4).", attr->name,
+                              attr->values[i].integer);
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_STRING :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].unknown.length > 1023)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad octetString value - bad length %d "
+                              "(RFC 2911 section 4.1.10).", attr->name,
+                              attr->values[i].unknown.length);
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_DATE :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         date = attr->values[i].date;
+
+          if (date[2] < 1 || date[2] > 12)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime month %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[2]);
+            else
+             break;
+         }
+
+          if (date[3] < 1 || date[3] > 31)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime day %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[3]);
+            else
+             break;
+         }
+
+          if (date[4] > 23)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime hours %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[4]);
+            else
+             break;
+         }
+
+          if (date[5] > 59)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime minutes %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[5]);
+            else
+             break;
+         }
+
+          if (date[6] > 60)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime seconds %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[6]);
+            else
+             break;
+         }
+
+          if (date[7] > 9)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime deciseconds %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[7]);
+            else
+             break;
+         }
+
+          if (date[8] != '-' && date[8] != '+')
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime UTC sign '%c' (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[8]);
+            else
+             break;
+         }
+
+          if (date[9] > 11)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime UTC hours %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[9]);
+            else
+             break;
+         }
+
+          if (date[10] > 59)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad dateTime UTC minutes %u (RFC 2911 "
+                              "section 4.1.13).", attr->name, date[10]);
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_RESOLUTION :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].resolution.xres <= 0)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad resolution value %dx%d%s - cross "
+                              "feed resolution must be positive (RFC 2911 "
+                              "section 4.1.13).", attr->name,
+                              attr->values[i].resolution.xres,
+                              attr->values[i].resolution.yres,
+                              attr->values[i].resolution.units ==
+                                  IPP_RES_PER_INCH ? "dpi" :
+                                  attr->values[i].resolution.units ==
+                                      IPP_RES_PER_CM ? "dpc" : "unknown");
+            else
+             break;
+         }
+
+         if (attr->values[i].resolution.yres <= 0)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad resolution value %dx%d%s - feed "
+                              "resolution must be positive (RFC 2911 section "
+                              "4.1.13).", attr->name,
+                              attr->values[i].resolution.xres,
+                              attr->values[i].resolution.yres,
+                              attr->values[i].resolution.units ==
+                                  IPP_RES_PER_INCH ? "dpi" :
+                                  attr->values[i].resolution.units ==
+                                      IPP_RES_PER_CM ? "dpc" : "unknown");
+            else
+             break;
+         }
+
+         if (attr->values[i].resolution.units != IPP_RES_PER_INCH &&
+             attr->values[i].resolution.units != IPP_RES_PER_CM)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad resolution value %dx%d%s - bad "
+                              "units value (RFC 2911 section 4.1.13).",
+                              attr->name, attr->values[i].resolution.xres,
+                              attr->values[i].resolution.yres,
+                              attr->values[i].resolution.units ==
+                                  IPP_RES_PER_INCH ? "dpi" :
+                                  attr->values[i].resolution.units ==
+                                      IPP_RES_PER_CM ? "dpc" : "unknown");
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_RANGE :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].range.lower > attr->values[i].range.upper)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad rangeOfInteger value %d-%d - lower "
+                              "greater than upper (RFC 2911 section 4.1.13).",
+                              attr->name, attr->values[i].range.lower,
+                              attr->values[i].range.upper);
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_BEGIN_COLLECTION :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (colattr = attr->values[i].collection->attrs;
+              colattr;
+              colattr = colattr->next)
+         {
+           if (!validate_attr(colattr, 0))
+           {
+             valid = 0;
+             break;
+           }
+         }
+
+         if (colattr && print)
+         {
+            print_test_error("\"%s\": Bad collection value.", attr->name);
+
+           while (colattr)
+           {
+             validate_attr(colattr, print);
+             colattr = colattr->next;
+           }
+         }
+       }
+        break;
+
+    case IPP_TAG_TEXT :
+    case IPP_TAG_TEXTLANG :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+         {
+           if ((*ptr & 0xe0) == 0xc0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf0) == 0xe0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf8) == 0xf0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if (*ptr & 0x80)
+             break;
+         }
+
+         if (*ptr)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad text value \"%s\" - bad UTF-8 "
+                              "sequence (RFC 2911 section 4.1.1).", attr->name,
+                              attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if ((ptr - attr->values[i].string.text) > 1023)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad text value \"%s\" - bad length %d "
+                              "(RFC 2911 section 4.1.1).", attr->name,
+                              attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_NAME :
+    case IPP_TAG_NAMELANG :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+         {
+           if ((*ptr & 0xe0) == 0xc0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf0) == 0xe0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf8) == 0xf0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if (*ptr & 0x80)
+             break;
+         }
+
+         if (*ptr)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad name value \"%s\" - bad UTF-8 "
+                              "sequence (RFC 2911 section 4.1.2).", attr->name,
+                              attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if ((ptr - attr->values[i].string.text) > 1023)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad name value \"%s\" - bad length %d "
+                              "(RFC 2911 section 4.1.2).", attr->name,
+                              attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_KEYWORD :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+           if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' &&
+               *ptr != '_')
+             break;
+
+         if (*ptr || ptr == attr->values[i].string.text)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad keyword value \"%s\" - invalid "
+                              "character (RFC 2911 section 4.1.3).",
+                              attr->name, attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if ((ptr - attr->values[i].string.text) > 255)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad keyword value \"%s\" - bad "
+                              "length %d (RFC 2911 section 4.1.3).",
+                              attr->name, attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_URI :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         uri_status = httpSeparateURI(HTTP_URI_CODING_ALL,
+                                      attr->values[i].string.text,
+                                      scheme, sizeof(scheme),
+                                      userpass, sizeof(userpass),
+                                      hostname, sizeof(hostname),
+                                      &port, resource, sizeof(resource));
+
+         if (uri_status < HTTP_URI_OK)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad URI value \"%s\" - %s "
+                              "(RFC 2911 section 4.1.5).", attr->name,
+                              attr->values[i].string.text,
+                              URIStatusStrings[uri_status -
+                                               HTTP_URI_OVERFLOW]);
+            else
+             break;
+         }
+
+         if (strlen(attr->values[i].string.text) > 1023)
+         {
+           valid = 0;
+
+           if (print)
+             print_test_error("\"%s\": Bad URI value \"%s\" - bad length %d "
+                              "(RFC 2911 section 4.1.5).", attr->name,
+                              attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_URISCHEME :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         ptr = attr->values[i].string.text;
+         if (islower(*ptr & 255))
+         {
+           for (ptr ++; *ptr; ptr ++)
+             if (!islower(*ptr & 255) && !isdigit(*ptr & 255) &&
+                 *ptr != '+' && *ptr != '-' && *ptr != '.')
+                break;
+         }
+
+         if (*ptr || ptr == attr->values[i].string.text)
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad uriScheme value \"%s\" - bad "
+                              "characters (RFC 2911 section 4.1.6).",
+                              attr->name, attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if ((ptr - attr->values[i].string.text) > 63)
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad uriScheme value \"%s\" - bad "
+                              "length %d (RFC 2911 section 4.1.6).",
+                              attr->name, attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_CHARSET :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+           if (!isprint(*ptr & 255) || isupper(*ptr & 255) ||
+               isspace(*ptr & 255))
+             break;
+
+         if (*ptr || ptr == attr->values[i].string.text)
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad charset value \"%s\" - bad "
+                              "characters (RFC 2911 section 4.1.7).",
+                              attr->name, attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if ((ptr - attr->values[i].string.text) > 40)
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad charset value \"%s\" - bad "
+                              "length %d (RFC 2911 section 4.1.7).",
+                              attr->name, attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    case IPP_TAG_LANGUAGE :
+       /*
+        * The following regular expression is derived from the ABNF for
+       * language tags in RFC 4646.  All I can say is that this is the
+       * easiest way to check the values...
+       */
+
+        if ((i = regcomp(&re,
+                        "^("
+                        "(([a-z]{2,3}(-[a-z][a-z][a-z]){0,3})|[a-z]{4,8})"
+                                                               /* language */
+                        "(-[a-z][a-z][a-z][a-z]){0,1}"         /* script */
+                        "(-([a-z][a-z]|[0-9][0-9][0-9])){0,1}" /* region */
+                        "(-([a-z]{5,8}|[0-9][0-9][0-9]))*"     /* variant */
+                        "(-[a-wy-z](-[a-z0-9]{2,8})+)*"        /* extension */
+                        "(-x(-[a-z0-9]{1,8})+)*"               /* privateuse */
+                        "|"
+                        "x(-[a-z0-9]{1,8})+"                   /* privateuse */
+                        "|"
+                        "[a-z]{1,3}(-[a-z][0-9]{2,8}){1,2}"    /* grandfathered */
+                        ")$",
+                        REG_NOSUB | REG_EXTENDED)) != 0)
+        {
+          char temp[256];              /* Temporary error string */
+
+          regerror(i, &re, temp, sizeof(temp));
+         print_fatal_error("Unable to compile naturalLanguage regular "
+                           "expression: %s.", temp);
+        }
+
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad naturalLanguage value \"%s\" - bad "
+                              "characters (RFC 2911 section 4.1.8).",
+                              attr->name, attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if (strlen(attr->values[i].string.text) > 63)
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad naturalLanguage value \"%s\" - bad "
+                              "length %d (RFC 2911 section 4.1.8).",
+                              attr->name, attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+
+       regfree(&re);
+        break;
+
+    case IPP_TAG_MIMETYPE :
+       /*
+        * The following regular expression is derived from the ABNF for
+       * language tags in RFC 2045 and 4288.  All I can say is that this is
+       * the easiest way to check the values...
+       */
+
+        if ((i = regcomp(&re,
+                        "^"
+                        "[-a-zA-Z0-9!#$&.+^_]{1,127}"          /* type-name */
+                        "/"
+                        "[-a-zA-Z0-9!#$&.+^_]{1,127}"          /* subtype-name */
+                        "(;[-a-zA-Z0-9!#$&.+^_]{1,127}="       /* parameter= */
+                        "([-a-zA-Z0-9!#$&.+^_]{1,127}|\"[^\"]*\"))*"
+                                                               /* value */
+                        "$",
+                        REG_NOSUB | REG_EXTENDED)) != 0)
+        {
+          char temp[256];              /* Temporary error string */
+
+          regerror(i, &re, temp, sizeof(temp));
+         print_fatal_error("Unable to compile mimeMediaType regular "
+                           "expression: %s.", temp);
+        }
+
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad mimeMediaType value \"%s\" - bad "
+                              "characters (RFC 2911 section 4.1.9).",
+                              attr->name, attr->values[i].string.text);
+            else
+             break;
+         }
+
+         if (strlen(attr->values[i].string.text) > 255)
+         {
+           valid = 0;
+
+            if (print)
+             print_test_error("\"%s\": Bad mimeMediaType value \"%s\" - bad "
+                              "length %d (RFC 2911 section 4.1.9).",
+                              attr->name, attr->values[i].string.text,
+                              (int)strlen(attr->values[i].string.text));
+            else
+             break;
+         }
+       }
+        break;
+
+    default :
+        break;
+  }
+
+  return (valid);
+}
+
+
+/*
+ * 'with_value()' - Test a WITH-VALUE predicate.
+ */
+
+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  i;                              /* Looping var */
+  char *valptr;                        /* Pointer into value */
+
+
+ /*
+  * NULL matches everything.
+  */
+
+  if (!value || !*value)
+    return (1);
+
+ /*
+  * Compare the value string to the attribute value.
+  */
+
+  switch (attr->value_tag)
+  {
+    case IPP_TAG_INTEGER :
+    case IPP_TAG_ENUM :
+        for (i = 0; i < attr->num_values; i ++)
+        {
+         char  op,                     /* Comparison operator */
+               *nextptr;               /* Next pointer */
+         int   intvalue;               /* Integer value */
+
+
+          valptr = value;
+         if (!strncmp(valptr, "no-value,", 9))
+           valptr += 9;
+
+         while (isspace(*valptr & 255) || isdigit(*valptr & 255) ||
+                *valptr == '-' || *valptr == ',' || *valptr == '<' ||
+                *valptr == '=' || *valptr == '>')
+         {
+           op = '=';
+           while (*valptr && !isdigit(*valptr & 255) && *valptr != '-')
+           {
+             if (*valptr == '<' || *valptr == '>' || *valptr == '=')
+               op = *valptr;
+             valptr ++;
+           }
+
+            if (!*valptr)
+             break;
+
+           intvalue = strtol(valptr, &nextptr, 0);
+           if (nextptr == valptr)
+             break;
+           valptr = nextptr;
+
+           switch (op)
+           {
+             case '=' :
+                 if (attr->values[i].integer == intvalue)
+                   return (1);
+                 break;
+             case '<' :
+                 if (attr->values[i].integer < intvalue)
+                   return (1);
+                 break;
+             case '>' :
+                 if (attr->values[i].integer > intvalue)
+                   return (1);
+                 break;
+           }
+         }
+        }
+       break;
+
+    case IPP_TAG_BOOLEAN :
+       for (i = 0; i < attr->num_values; i ++)
+       {
+          if (!strcmp(value, "true") == attr->values[i].boolean)
+           return (1);
+       }
+       break;
+
+    case IPP_TAG_NOVALUE :
+        return (!strcmp(value, "no-value") || !strncmp(value, "no-value,", 9));
+
+    case IPP_TAG_CHARSET :
+    case IPP_TAG_KEYWORD :
+    case IPP_TAG_LANGUAGE :
+    case IPP_TAG_MIMETYPE :
+    case IPP_TAG_NAME :
+    case IPP_TAG_NAMELANG :
+    case IPP_TAG_TEXT :
+    case IPP_TAG_TEXTLANG :
+    case IPP_TAG_URI :
+    case IPP_TAG_URISCHEME :
+        if (regex)
+       {
+        /*
+         * Value is an extended, case-sensitive POSIX regular expression...
+         */
+
+         regex_t       re;             /* Regular expression */
+
+          if ((i = regcomp(&re, value, REG_EXTENDED | REG_NOSUB)) != 0)
+         {
+           char temp[256];             /* Temporary string */
+
+            regerror(i, &re, temp, sizeof(temp));
+
+           print_fatal_error("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 < attr->num_values; i ++)
+         {
+           if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+             break;
+         }
+
+         regfree(&re);
+
+          return (i == attr->num_values);
+       }
+       else
+       {
+        /*
+         * Value is a literal string, see if at least one value matches the
+         * literal string...
+         */
+
+         for (i = 0; i < attr->num_values; i ++)
+         {
+           if (!strcmp(value, attr->values[i].string.text))
+             return (1);
+         }
+       }
+       break;
+
+    default :
+        break;
+  }
+
+  return (0);
+}
+
+
+/*
+ * End of "$Id: ipptest.c 9000 2010-02-24 06:29:38Z mike $".
  */
diff --git a/test/print-job-media-col.test b/test/print-job-media-col.test
new file mode 100644 (file)
index 0000000..6c27197
--- /dev/null
@@ -0,0 +1,39 @@
+# Print a test page using Print-Job + media-col
+#
+# Usage:
+#
+#    ./ipptest -f filename ipp://... print-job-media-col.test
+{
+       # The name of the test...
+       NAME "Print test page using Print-Job + media-col"
+
+       # The operation to use
+       OPERATION Print-Job
+
+       # Attributes, starting in the operation group...
+       GROUP operation-attributes-tag
+       ATTR charset attributes-charset utf-8
+       ATTR language attributes-natural-language en
+       ATTR uri printer-uri $uri
+       ATTR name requesting-user-name $user
+       ATTR mimetype document-format application/octet-stream
+
+       GROUP job-attributes-tag
+       ATTR collection media-col {
+               MEMBER collection media-size {
+                       # 4x6
+                       MEMBER integer media-x-dimension 10160
+                       MEMBER integer media-y-dimension 15240
+               }
+       }
+
+       FILE $filename
+
+       # What statuses are OK?
+       STATUS successful-ok
+       STATUS successful-ok-ignored-or-substituted-attributes
+
+       # What attributes do we expect?
+       EXPECT job-id OF-TYPE integer WITH-VALUE >0
+       EXPECT job-uri OF-TYPE uri
+}
index a584063e8564e1400561e87697638c47dd86439c..84f0d9b73efcaf3e4db8ef55f174b1881f7515c2 100644 (file)
@@ -1,10 +1,10 @@
 <HTML>
 <HEAD>
-       <META NAME="Description" CONTENT="Common UNIX Printing System Software Test Report">
-       <META NAME="COPYRIGHT" CONTENT="Copyright 2007-2008, All Rights Reserved">
-       <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.4">
+       <META NAME="Description" CONTENT="CUPS Test Report">
+       <META NAME="COPYRIGHT" CONTENT="Copyright 2007-2010, All Rights Reserved">
+       <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.5">
        <META NAME="Author" CONTENT="Apple Inc.">
-       <TITLE>CUPS 1.4 Software Test Report</TITLE>
+       <TITLE>CUPS 1.5 Software Test Report</TITLE>
        <STYLE TYPE="text/css"><!--
        PRE {
          font-size: 80%;
 </HEAD>
 <BODY>
 
-<H1>CUPS 1.4 Software Test Report</H1>
+<H1>CUPS 1.5 Software Test Report</H1>
 
 <P>This software test report provides detailed test results that
-are used to evaluate the stability and compliance of the Common
-UNIX Printing System ("CUPS") Version 1.4.
+are used to evaluate the stability and compliance of CUPS Version 1.5.
 
 <H2>Document Overview</H2>
 
diff --git a/vc2005/ipptest.vcproj b/vc2005/ipptest.vcproj
new file mode 100644 (file)
index 0000000..d01d7ef
--- /dev/null
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8.00"\r
+       Name="cupstestppd"\r
+       ProjectGUID="{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"\r
+       RootNamespace="ipptest"\r
+       Keyword="Win32Proj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\vcnet;.."\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="1"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="..\vcnet;.."\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="1"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\test\ipptest.c"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
index d482aecafbb2d774528c4064b94901e691bef33b..ab2d920e9788f8277573d395a9540e7f99c0148a 100644 (file)
@@ -63,8 +63,8 @@
  * Version of software...
  */
 
-#define CUPS_SVERSION "CUPS v1.4.0"
-#define CUPS_MINIMAL "CUPS/1.4.0"
+#define CUPS_SVERSION "CUPS v1.5svn"
+#define CUPS_MINIMAL "CUPS/1.5svn"
 
 
 /*
 /* #undef HAVE_CRYPT_H */
 
 
+/*
+ * Do we have <scsi/sg.h>?
+ */
+
+/* #undef HAVE_SCSI_SG_H */
+
+
 /*
  * Use <string.h>, <strings.h>, and/or <bstring.h>?
  */
  * Default GSS service name...
  */
 
-#define CUPS_DEFAULT_GSSSERVICENAME "ipp"
+#define CUPS_DEFAULT_GSSSERVICENAME "host"
 
 
 /*
  * Which random number generator function to use...
  */
 
+/* #undef HAVE_ARC4RANDOM */
 /* #undef HAVE_RANDOM */
-/* #undef HAVE_MRAND48 */
 /* #undef HAVE_LRAND48 */
 
+#ifdef HAVE_ARC4RANDOM
+#  define CUPS_RAND() arc4random()
+#  define CUPS_SRAND(v) arc4random_stir()
+#elif defined(HAVE_RANDOM)
+#  define CUPS_RAND() random()
+#  define CUPS_SRAND(v) srandom(v)
+#elif defined(HAVE_LRAND48)
+#  define CUPS_RAND() lrand48()
+#  define CUPS_SRAND(v) srand48(v)
+#else
+#  define CUPS_RAND() rand()
+#  define CUPS_SRAND(v) srand(v)
+#endif /* HAVE_ARC4RANDOM */
+
 
 /*
  * Do we have vproc_transaction_begin/end?
index ccf6cbf65702b403d05c346e5786b6bf97386653..0e950a33b064a258fc583591d5e94c77381ea5df 100644 (file)
@@ -1,5 +1,5 @@
 Microsoft Visual Studio Solution File, Format Version 10.00\r
-# Visual C++ Express 2008\r
+# Visual Studio 2008\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcups2", "libcups2.vcproj", "{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}"\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testfile", "testfile.vcproj", "{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}"\r
@@ -17,6 +17,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cupstestppd", "cupstestppd.
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipptest", "ipptest.vcproj", "{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
+       EndProjectSection\r
+EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                Debug|Win32 = Debug|Win32\r
@@ -29,24 +34,24 @@ Global
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|Win32.Build.0 = Debug|Win32\r
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|x64.ActiveCfg = Debug|x64\r
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|x64.Build.0 = Debug|x64\r
-               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.ActiveCfg = Debug|Win32\r
-               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.Build.0 = Debug|Win32\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.ActiveCfg = Release|Win32\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.Build.0 = Release|Win32\r
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|x64.ActiveCfg = Debug|x64\r
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|x64.Build.0 = Debug|x64\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|Win32.ActiveCfg = Debug|Win32\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|Win32.Build.0 = Debug|Win32\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|x64.ActiveCfg = Debug|x64\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|x64.Build.0 = Debug|x64\r
-               {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.ActiveCfg = Debug|Win32\r
-               {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.Build.0 = Debug|Win32\r
+               {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.ActiveCfg = Release|Win32\r
+               {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.Build.0 = Release|Win32\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|x64.ActiveCfg = Debug|x64\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|x64.Build.0 = Debug|x64\r
                {90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|Win32.ActiveCfg = Debug|Win32\r
                {90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|Win32.Build.0 = Debug|Win32\r
                {90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|x64.ActiveCfg = Debug|x64\r
                {90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|x64.Build.0 = Debug|x64\r
-               {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.ActiveCfg = Debug|Win32\r
-               {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.Build.0 = Debug|Win32\r
+               {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.ActiveCfg = Release|Win32\r
+               {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.Build.0 = Release|Win32\r
                {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|x64.ActiveCfg = Debug|x64\r
                {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|x64.Build.0 = Debug|x64\r
                {6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Debug|Win32.ActiveCfg = Debug|Win32\r
@@ -55,6 +60,14 @@ Global
                {6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|Win32.ActiveCfg = Release|Win32\r
                {6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|Win32.Build.0 = Release|Win32\r
                {6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|x64.ActiveCfg = Release|Win32\r
+               {6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|x64.Build.0 = Release|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Debug|Win32.Build.0 = Debug|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Debug|x64.ActiveCfg = Debug|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|Win32.ActiveCfg = Release|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|Win32.Build.0 = Release|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.ActiveCfg = Release|Win32\r
+               {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.Build.0 = Release|Win32\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
diff --git a/vcnet/ipptest.vcproj b/vcnet/ipptest.vcproj
new file mode 100644 (file)
index 0000000..9de93f3
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9.00"\r
+       Name="ipptest"\r
+       ProjectGUID="{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"\r
+       RootNamespace="ipptest"\r
+       Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\vcnet;..;..\vcnet\regex"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="1"\r
+                               Detect64BitPortabilityProblems="false"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="..\vcnet;..;..\vcnet\regex"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="1"\r
+                               Detect64BitPortabilityProblems="false"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\regex\debug.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\test\ipptest.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\regex\regcomp.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\regex\regerror.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\regex\regexec.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\regex\regfree.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\regex\split.c"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\regex\regex.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\regex\regex2.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/vcnet/regex/COPYRIGHT b/vcnet/regex/COPYRIGHT
new file mode 100644 (file)
index 0000000..30c1f7a
--- /dev/null
@@ -0,0 +1,20 @@
+Copyright 1992, 1993, 1994, 1997 Henry Spencer.  All rights reserved.
+This software is not subject to any license of the American Telephone
+and Telegraph Company or of the Regents of the University of California.
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it, subject
+to the following restrictions:
+
+1. The author is not responsible for the consequences of use of this
+   software, no matter how awful, even if they arise from flaws in it.
+
+2. The origin of this software must not be misrepresented, either by
+   explicit claim or by omission.  Since few users ever read sources,
+   credits must appear in the documentation.
+
+3. Altered versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.  Since few users
+   ever read sources, credits must appear in the documentation.
+
+4. This notice may not be removed or altered.
diff --git a/vcnet/regex/Makefile b/vcnet/regex/Makefile
new file mode 100644 (file)
index 0000000..3882b37
--- /dev/null
@@ -0,0 +1,130 @@
+# You probably want to take -DREDEBUG out of CFLAGS, and put something like
+# -O in, *after* testing (-DREDEBUG strengthens testing by enabling a lot of
+# internal assertion checking and some debugging facilities).
+# Put -Dconst= in for a pre-ANSI compiler.
+# Do not take -DPOSIX_MISTAKE out.
+# REGCFLAGS isn't important to you (it's for my use in some special contexts).
+CFLAGS=-I. -DPOSIX_MISTAKE -DREDEBUG $(REGCFLAGS)
+
+# If you have a pre-ANSI compiler, put -o into MKHFLAGS.  If you want
+# the Berkeley __P macro, put -b in.
+MKHFLAGS=
+
+# Flags for linking but not compiling, if any.
+LDFLAGS=
+
+# Extra libraries for linking, if any.
+LIBS=
+
+# Internal stuff, should not need changing.
+OBJPRODN=regcomp.o regexec.o regerror.o regfree.o
+OBJS=$(OBJPRODN) split.o debug.o main.o
+H=cclass.h cname.h regex2.h utils.h
+REGSRC=regcomp.c regerror.c regexec.c regfree.c
+ALLSRC=$(REGSRC) engine.c debug.c main.c split.c
+
+# Stuff that matters only if you're trying to lint the package.
+LINTFLAGS=-I. -Dstatic= -Dconst= -DREDEBUG
+LINTC=regcomp.c regexec.c regerror.c regfree.c debug.c main.c
+JUNKLINT=possible pointer alignment|null effect
+
+# arrangements to build forward-reference header files
+.SUFFIXES:     .ih .h
+.c.ih:
+       sh ./mkh $(MKHFLAGS) -p $< >$@
+
+default:       r
+
+lib:   purge $(OBJPRODN)
+       rm -f libregex.a
+       ar crv libregex.a $(OBJPRODN)
+
+purge:
+       rm -f *.o
+
+# stuff to build regex.h
+REGEXH=regex.h
+REGEXHSRC=regex2.h $(REGSRC)
+$(REGEXH):     $(REGEXHSRC) mkh
+       sh ./mkh $(MKHFLAGS) -i _REGEX_H_ $(REGEXHSRC) >regex.tmp
+       cmp -s regex.tmp regex.h 2>/dev/null || cp regex.tmp regex.h
+       rm -f regex.tmp
+
+# dependencies
+$(OBJPRODN) debug.o:   utils.h regex.h regex2.h
+regcomp.o:     cclass.h cname.h regcomp.ih
+regexec.o:     engine.c engine.ih
+regerror.o:    regerror.ih
+debug.o:       debug.ih
+main.o:        main.ih
+
+# tester
+re:    $(OBJS)
+       $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+
+# regression test
+r:     re tests
+       ./re <tests
+       ./re -el <tests
+       ./re -er <tests
+
+# 57 variants, and other stuff, for development use -- not useful to you
+ra:    ./re tests
+       -./re <tests
+       -./re -el <tests
+       -./re -er <tests
+
+rx:    ./re tests
+       ./re -x <tests
+       ./re -x -el <tests
+       ./re -x -er <tests
+
+t:     ./re tests
+       -time ./re <tests
+       -time ./re -cs <tests
+       -time ./re -el <tests
+       -time ./re -cs -el <tests
+
+l:     $(LINTC)
+       lint $(LINTFLAGS) -h $(LINTC) 2>&1 | egrep -v '$(JUNKLINT)' | tee lint
+
+fullprint:
+       ti README WHATSNEW notes todo | list
+       ti *.h | list
+       list *.c
+       list regex.3 regex.7
+
+print:
+       ti README WHATSNEW notes todo | list
+       ti *.h | list
+       list reg*.c engine.c
+
+
+mf.tmp:        Makefile
+       sed '/^REGEXH=/s/=.*/=regex.h/' Makefile | sed '/#DEL$$/d' >$@
+
+DTRH=cclass.h cname.h regex2.h utils.h
+PRE=COPYRIGHT README WHATSNEW
+POST=mkh regex.3 regex.7 tests $(DTRH) $(ALLSRC) fake/*.[ch]
+FILES=$(PRE) Makefile $(POST)
+DTR=$(PRE) Makefile=mf.tmp $(POST)
+dtr:   $(FILES) mf.tmp
+       makedtr $(DTR) >$@
+       rm mf.tmp
+
+cio:   $(FILES)
+       cio $(FILES)
+
+rdf:   $(FILES)
+       rcsdiff -c $(FILES) 2>&1 | p
+
+# various forms of cleanup
+tidy:
+       rm -f junk* core core.* *.core dtr *.tmp lint
+
+clean: tidy
+       rm -f *.o *.s *.ih re libregex.a
+
+# don't do this one unless you know what you're doing
+spotless:      clean
+       rm -f mkh regex.h
diff --git a/vcnet/regex/README b/vcnet/regex/README
new file mode 100644 (file)
index 0000000..e6ce373
--- /dev/null
@@ -0,0 +1,32 @@
+alpha3.8 release.
+Tue Aug 10 15:51:48 EDT 1999
+henry@spsystems.net  (formerly henry@zoo.toronto.edu)
+
+See WHATSNEW for change listing.
+
+installation notes:
+--------
+Read the comments at the beginning of Makefile before running.
+
+Utils.h contains some things that just might have to be modified on
+some systems, as well as a nested include (ugh) of <assert.h>.
+
+The "fake" directory contains quick-and-dirty fakes for some header
+files and routines that old systems may not have.  Note also that
+-DUSEBCOPY will make utils.h substitute bcopy() for memmove().
+
+After that, "make r" will build regcomp.o, regexec.o, regfree.o,
+and regerror.o (the actual routines), bundle them together into a test
+program, and run regression tests on them.  No output is good output.
+
+"make lib" builds just the .o files for the actual routines (when
+you're happy with testing and have adjusted CFLAGS for production),
+and puts them together into libregex.a.  You can pick up either the
+library or *.o ("make lib" makes sure there are no other .o files left
+around to confuse things).
+
+Main.c, debug.c, split.c are used for regression testing but are not part
+of the RE routines themselves.
+
+Regex.h goes in /usr/include.  All other .h files are internal only.
+--------
diff --git a/vcnet/regex/WHATSNEW b/vcnet/regex/WHATSNEW
new file mode 100644 (file)
index 0000000..1295343
--- /dev/null
@@ -0,0 +1,108 @@
+New in alpha3.8:  Bug fix for signed/unsigned mixup, found and fixed
+by the FreeBSD folks.
+
+New in alpha3.7:  A bit of cleanup aimed at maximizing portability,
+possibly at slight cost in efficiency.  "ul" suffixes and "unsigned long"
+no longer appear, in particular.
+
+New in alpha3.6:  A couple more portability glitches fixed.
+
+New in alpha3.5:  Active development of this code has been stopped --
+I'm working on a complete reimplementation -- but folks have found some
+minor portability glitches and the like, hence this release to fix them.
+One penalty:  slightly reduced compatibility with old compilers, because
+the ANSI C `unsigned long' type and `ul' constant suffix are used in a
+few places (I could avoid this but it would be considerably more work).
+
+New in alpha3.4:  The complex bug alluded to below has been fixed (in a
+slightly kludgey temporary way that may hurt efficiency a bit; this is
+another "get it out the door for 4.4" release).  The tests at the end of
+the tests file have accordingly been uncommented.  The primary sign of
+the bug was that something like a?b matching ab matched b rather than ab.
+(The bug was essentially specific to this exact situation, else it would
+have shown up earlier.)
+
+New in alpha3.3:  The definition of word boundaries has been altered
+slightly, to more closely match the usual programming notion that "_"
+is an alphabetic.  Stuff used for pre-ANSI systems is now in a subdir,
+and the makefile no longer alludes to it in mysterious ways.  The
+makefile has generally been cleaned up some.  Fixes have been made
+(again!) so that the regression test will run without -DREDEBUG, at
+the cost of weaker checking.  A workaround for a bug in some folks'
+<assert.h> has been added.  And some more things have been added to
+tests, including a couple right at the end which are commented out
+because the code currently flunks them (complex bug; fix coming).
+Plus the usual minor cleanup.
+
+New in alpha3.2:  Assorted bits of cleanup and portability improvement
+(the development base is now a BSDI system using GCC instead of an ancient
+Sun system, and the newer compiler exposed some glitches).  Fix for a
+serious bug that affected REs using many [] (including REG_ICASE REs
+because of the way they are implemented), *sometimes*, depending on
+memory-allocation patterns.  The header-file prototypes no longer name
+the parameters, avoiding possible name conflicts.  The possibility that
+some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is
+now handled gracefully.  "uchar" is no longer used as an internal type
+name (too many people have the same idea).  Still the same old lousy
+performance, alas.
+
+New in alpha3.1:  Basically nothing, this release is just a bookkeeping
+convenience.  Stay tuned.
+
+New in alpha3.0:  Performance is no better, alas, but some fixes have been
+made and some functionality has been added.  (This is basically the "get
+it out the door in time for 4.4" release.)  One bug fix:  regfree() didn't
+free the main internal structure (how embarrassing).  It is now possible
+to put NULs in either the RE or the target string, using (resp.) a new
+REG_PEND flag and the old REG_STARTEND flag.  The REG_NOSPEC flag to
+regcomp() makes all characters ordinary, so you can match a literal
+string easily (this will become more useful when performance improves!).
+There are now primitives to match beginnings and ends of words, although
+the syntax is disgusting and so is the implementation.  The REG_ATOI
+debugging interface has changed a bit.  And there has been considerable
+internal cleanup of various kinds.
+
+New in alpha2.3:  Split change list out of README, and moved flags notes
+into Makefile.  Macro-ized the name of regex(7) in regex(3), since it has
+to change for 4.4BSD.  Cleanup work in engine.c, and some new regression
+tests to catch tricky cases thereof.
+
+New in alpha2.2:  Out-of-date manpages updated.  Regerror() acquires two
+small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges
+in my own test program and might be useful to others for similar purposes.
+The regression test will now compile (and run) without REDEBUG.  The
+BRE \$ bug is fixed.  Most uses of "uchar" are gone; it's all chars now.
+Char/uchar parameters are now written int/unsigned, to avoid possible
+portability problems with unpromoted parameters.  Some unsigned casts have
+been introduced to minimize portability problems with shifting into sign
+bits.
+
+New in alpha2.1:  Lots of little stuff, cleanup and fixes.  The one big
+thing is that regex.h is now generated, using mkh, rather than being
+supplied in the distribution; due to circularities in dependencies,
+you have to build regex.h explicitly by "make h".  The two known bugs
+have been fixed (and the regression test now checks for them), as has a
+problem with assertions not being suppressed in the absence of REDEBUG.
+No performance work yet.
+
+New in alpha2:  Backslash-anything is an ordinary character, not an
+error (except, of course, for the handful of backslashed metacharacters
+in BREs), which should reduce script breakage.  The regression test
+checks *where* null strings are supposed to match, and has generally
+been tightened up somewhat.  Small bug fixes in parameter passing (not
+harmful, but technically errors) and some other areas.  Debugging
+invoked by defining REDEBUG rather than not defining NDEBUG.
+
+New in alpha+3:  full prototyping for internal routines, using a little
+helper program, mkh, which extracts prototypes given in stylized comments.
+More minor cleanup.  Buglet fix:  it's CHAR_BIT, not CHAR_BITS.  Simple
+pre-screening of input when a literal string is known to be part of the
+RE; this does wonders for performance.
+
+New in alpha+2:  minor bits of cleanup.  Notably, the number "32" for the
+word width isn't hardwired into regexec.c any more, the public header
+file prototypes the functions if __STDC__ is defined, and some small typos
+in the manpages have been fixed.
+
+New in alpha+1:  improvements to the manual pages, and an important
+extension, the REG_STARTEND option to regexec().
diff --git a/vcnet/regex/cclass.h b/vcnet/regex/cclass.h
new file mode 100644 (file)
index 0000000..0c29302
--- /dev/null
@@ -0,0 +1,31 @@
+/* character-class table */
+static struct cclass {
+       char *name;
+       char *chars;
+       char *multis;
+} cclasses[] = {
+       "alnum",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789",                           "",
+       "alpha",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+                                       "",
+       "blank",        " \t",          "",
+       "cntrl",        "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
+\25\26\27\30\31\32\33\34\35\36\37\177",        "",
+       "digit",        "0123456789",   "",
+       "graph",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+                                       "",
+       "lower",        "abcdefghijklmnopqrstuvwxyz",
+                                       "",
+       "print",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
+                                       "",
+       "punct",        "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+                                       "",
+       "space",        "\t\n\v\f\r ",  "",
+       "upper",        "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+                                       "",
+       "xdigit",       "0123456789ABCDEFabcdef",
+                                       "",
+       NULL,           0,              ""
+};
diff --git a/vcnet/regex/cname.h b/vcnet/regex/cname.h
new file mode 100644 (file)
index 0000000..02e86e9
--- /dev/null
@@ -0,0 +1,102 @@
+/* character-name table */
+static struct cname {
+       char *name;
+       char code;
+} cnames[] = {
+       "NUL",  '\0',
+       "SOH",  '\001',
+       "STX",  '\002',
+       "ETX",  '\003',
+       "EOT",  '\004',
+       "ENQ",  '\005',
+       "ACK",  '\006',
+       "BEL",  '\007',
+       "alert",        '\007',
+       "BS",           '\010',
+       "backspace",    '\b',
+       "HT",           '\011',
+       "tab",          '\t',
+       "LF",           '\012',
+       "newline",      '\n',
+       "VT",           '\013',
+       "vertical-tab", '\v',
+       "FF",           '\014',
+       "form-feed",    '\f',
+       "CR",           '\015',
+       "carriage-return",      '\r',
+       "SO",   '\016',
+       "SI",   '\017',
+       "DLE",  '\020',
+       "DC1",  '\021',
+       "DC2",  '\022',
+       "DC3",  '\023',
+       "DC4",  '\024',
+       "NAK",  '\025',
+       "SYN",  '\026',
+       "ETB",  '\027',
+       "CAN",  '\030',
+       "EM",   '\031',
+       "SUB",  '\032',
+       "ESC",  '\033',
+       "IS4",  '\034',
+       "FS",   '\034',
+       "IS3",  '\035',
+       "GS",   '\035',
+       "IS2",  '\036',
+       "RS",   '\036',
+       "IS1",  '\037',
+       "US",   '\037',
+       "space",                ' ',
+       "exclamation-mark",     '!',
+       "quotation-mark",       '"',
+       "number-sign",          '#',
+       "dollar-sign",          '$',
+       "percent-sign",         '%',
+       "ampersand",            '&',
+       "apostrophe",           '\'',
+       "left-parenthesis",     '(',
+       "right-parenthesis",    ')',
+       "asterisk",     '*',
+       "plus-sign",    '+',
+       "comma",        ',',
+       "hyphen",       '-',
+       "hyphen-minus", '-',
+       "period",       '.',
+       "full-stop",    '.',
+       "slash",        '/',
+       "solidus",      '/',
+       "zero",         '0',
+       "one",          '1',
+       "two",          '2',
+       "three",        '3',
+       "four",         '4',
+       "five",         '5',
+       "six",          '6',
+       "seven",        '7',
+       "eight",        '8',
+       "nine",         '9',
+       "colon",        ':',
+       "semicolon",    ';',
+       "less-than-sign",       '<',
+       "equals-sign",          '=',
+       "greater-than-sign",    '>',
+       "question-mark",        '?',
+       "commercial-at",        '@',
+       "left-square-bracket",  '[',
+       "backslash",            '\\',
+       "reverse-solidus",      '\\',
+       "right-square-bracket", ']',
+       "circumflex",           '^',
+       "circumflex-accent",    '^',
+       "underscore",           '_',
+       "low-line",             '_',
+       "grave-accent",         '`',
+       "left-brace",           '{',
+       "left-curly-bracket",   '{',
+       "vertical-line",        '|',
+       "right-brace",          '}',
+       "right-curly-bracket",  '}',
+       "tilde",                '~',
+       "DEL",  '\177',
+       NULL,   0,
+};
diff --git a/vcnet/regex/debug.c b/vcnet/regex/debug.c
new file mode 100644 (file)
index 0000000..99ce7da
--- /dev/null
@@ -0,0 +1,242 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+#include "debug.ih"
+
+/*
+ - regprint - print a regexp for debugging
+ == void regprint(regex_t *r, FILE *d);
+ */
+void
+regprint(r, d)
+regex_t *r;
+FILE *d;
+{
+       register struct re_guts *g = r->re_g;
+       register int i;
+       register int c;
+       register int last;
+       int nincat[NC];
+
+       fprintf(d, "%ld states, %d categories", (long)g->nstates,
+                                                       g->ncategories);
+       fprintf(d, ", first %ld last %ld", (long)g->firststate,
+                                               (long)g->laststate);
+       if (g->iflags&USEBOL)
+               fprintf(d, ", USEBOL");
+       if (g->iflags&USEEOL)
+               fprintf(d, ", USEEOL");
+       if (g->iflags&BAD)
+               fprintf(d, ", BAD");
+       if (g->nsub > 0)
+               fprintf(d, ", nsub=%ld", (long)g->nsub);
+       if (g->must != NULL)
+               fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
+                                                               g->must);
+       if (g->backrefs)
+               fprintf(d, ", backrefs");
+       if (g->nplus > 0)
+               fprintf(d, ", nplus %ld", (long)g->nplus);
+       fprintf(d, "\n");
+       s_print(g, d);
+       for (i = 0; i < g->ncategories; i++) {
+               nincat[i] = 0;
+               for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+                       if (g->categories[c] == i)
+                               nincat[i]++;
+       }
+       fprintf(d, "cc0#%d", nincat[0]);
+       for (i = 1; i < g->ncategories; i++)
+               if (nincat[i] == 1) {
+                       for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+                               if (g->categories[c] == i)
+                                       break;
+                       fprintf(d, ", %d=%s", i, regchar(c));
+               }
+       fprintf(d, "\n");
+       for (i = 1; i < g->ncategories; i++)
+               if (nincat[i] != 1) {
+                       fprintf(d, "cc%d\t", i);
+                       last = -1;
+                       for (c = CHAR_MIN; c <= CHAR_MAX+1; c++)        /* +1 does flush */
+                               if (c <= CHAR_MAX && g->categories[c] == i) {
+                                       if (last < 0) {
+                                               fprintf(d, "%s", regchar(c));
+                                               last = c;
+                                       }
+                               } else {
+                                       if (last >= 0) {
+                                               if (last != c-1)
+                                                       fprintf(d, "-%s",
+                                                               regchar(c-1));
+                                               last = -1;
+                                       }
+                               }
+                       fprintf(d, "\n");
+               }
+}
+
+/*
+ - s_print - print the strip for debugging
+ == static void s_print(register struct re_guts *g, FILE *d);
+ */
+static void
+s_print(g, d)
+register struct re_guts *g;
+FILE *d;
+{
+       register sop *s;
+       register cset *cs;
+       register int i;
+       register int done = 0;
+       register sop opnd;
+       register int col = 0;
+       register int last;
+       register sopno offset = 2;
+#      define  GAP()   {       if (offset % 5 == 0) { \
+                                       if (col > 40) { \
+                                               fprintf(d, "\n\t"); \
+                                               col = 0; \
+                                       } else { \
+                                               fprintf(d, " "); \
+                                               col++; \
+                                       } \
+                               } else \
+                                       col++; \
+                               offset++; \
+                       }
+
+       if (OP(g->strip[0]) != OEND)
+               fprintf(d, "missing initial OEND!\n");
+       for (s = &g->strip[1]; !done; s++) {
+               opnd = OPND(*s);
+               switch (OP(*s)) {
+               case OEND:
+                       fprintf(d, "\n");
+                       done = 1;
+                       break;
+               case OCHAR:
+                       if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
+                               fprintf(d, "\\%c", (char)opnd);
+                       else
+                               fprintf(d, "%s", regchar((char)opnd));
+                       break;
+               case OBOL:
+                       fprintf(d, "^");
+                       break;
+               case OEOL:
+                       fprintf(d, "$");
+                       break;
+               case OBOW:
+                       fprintf(d, "\\{");
+                       break;
+               case OEOW:
+                       fprintf(d, "\\}");
+                       break;
+               case OANY:
+                       fprintf(d, ".");
+                       break;
+               case OANYOF:
+                       fprintf(d, "[(%ld)", (long)opnd);
+                       cs = &g->sets[opnd];
+                       last = -1;
+                       for (i = 0; i < g->csetsize+1; i++)     /* +1 flushes */
+                               if (CHIN(cs, i) && i < g->csetsize) {
+                                       if (last < 0) {
+                                               fprintf(d, "%s", regchar(i));
+                                               last = i;
+                                       }
+                               } else {
+                                       if (last >= 0) {
+                                               if (last != i-1)
+                                                       fprintf(d, "-%s",
+                                                               regchar(i-1));
+                                               last = -1;
+                                       }
+                               }
+                       fprintf(d, "]");
+                       break;
+               case OBACK_:
+                       fprintf(d, "(\\<%ld>", (long)opnd);
+                       break;
+               case O_BACK:
+                       fprintf(d, "<%ld>\\)", (long)opnd);
+                       break;
+               case OPLUS_:
+                       fprintf(d, "(+");
+                       if (OP(*(s+opnd)) != O_PLUS)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       break;
+               case O_PLUS:
+                       if (OP(*(s-opnd)) != OPLUS_)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       fprintf(d, "+)");
+                       break;
+               case OQUEST_:
+                       fprintf(d, "(?");
+                       if (OP(*(s+opnd)) != O_QUEST)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       break;
+               case O_QUEST:
+                       if (OP(*(s-opnd)) != OQUEST_)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       fprintf(d, "?)");
+                       break;
+               case OLPAREN:
+                       fprintf(d, "((<%ld>", (long)opnd);
+                       break;
+               case ORPAREN:
+                       fprintf(d, "<%ld>))", (long)opnd);
+                       break;
+               case OCH_:
+                       fprintf(d, "<");
+                       if (OP(*(s+opnd)) != OOR2)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       break;
+               case OOR1:
+                       if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       fprintf(d, "|");
+                       break;
+               case OOR2:
+                       fprintf(d, "|");
+                       if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       break;
+               case O_CH:
+                       if (OP(*(s-opnd)) != OOR1)
+                               fprintf(d, "<%ld>", (long)opnd);
+                       fprintf(d, ">");
+                       break;
+               default:
+                       fprintf(d, "!%d(%d)!", OP(*s), opnd);
+                       break;
+               }
+               if (!done)
+                       GAP();
+       }
+}
+
+/*
+ - regchar - make a character printable
+ == static char *regchar(int ch);
+ */
+static char *                  /* -> representation */
+regchar(ch)
+int ch;
+{
+       static char buf[10];
+
+       if (isprint(ch) || ch == ' ')
+               sprintf(buf, "%c", ch);
+       else
+               sprintf(buf, "\\%o", ch);
+       return(buf);
+}
diff --git a/vcnet/regex/debug.ih b/vcnet/regex/debug.ih
new file mode 100644 (file)
index 0000000..5f40ff7
--- /dev/null
@@ -0,0 +1,14 @@
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === debug.c === */
+void regprint(regex_t *r, FILE *d);
+static void s_print(register struct re_guts *g, FILE *d);
+static char *regchar(int ch);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/vcnet/regex/engine.c b/vcnet/regex/engine.c
new file mode 100644 (file)
index 0000000..919fe3f
--- /dev/null
@@ -0,0 +1,1019 @@
+/*
+ * The matching engine and friends.  This file is #included by regexec.c
+ * after suitable #defines of a variety of macros used herein, so that
+ * different state representations can be used without duplicating masses
+ * of code.
+ */
+
+#ifdef SNAMES
+#define        matcher smatcher
+#define        fast    sfast
+#define        slow    sslow
+#define        dissect sdissect
+#define        backref sbackref
+#define        step    sstep
+#define        print   sprint
+#define        at      sat
+#define        match   smat
+#endif
+#ifdef LNAMES
+#define        matcher lmatcher
+#define        fast    lfast
+#define        slow    lslow
+#define        dissect ldissect
+#define        backref lbackref
+#define        step    lstep
+#define        print   lprint
+#define        at      lat
+#define        match   lmat
+#endif
+
+/* another structure passed up and down to avoid zillions of parameters */
+struct match {
+       struct re_guts *g;
+       int eflags;
+       regmatch_t *pmatch;     /* [nsub+1] (0 element unused) */
+       char *offp;             /* offsets work from here */
+       char *beginp;           /* start of string -- virtual NUL precedes */
+       char *endp;             /* end of string -- virtual NUL here */
+       char *coldp;            /* can be no match starting before here */
+       char **lastpos;         /* [nplus+1] */
+       STATEVARS;
+       states st;              /* current states */
+       states fresh;           /* states for a fresh start */
+       states tmp;             /* temporary */
+       states empty;           /* empty set of states */
+};
+
+#include "engine.ih"
+
+#ifdef REDEBUG
+#define        SP(t, s, c)     print(m, t, s, c, stdout)
+#define        AT(t, p1, p2, s1, s2)   at(m, t, p1, p2, s1, s2)
+#define        NOTE(str)       { if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }
+#else
+#define        SP(t, s, c)     /* nothing */
+#define        AT(t, p1, p2, s1, s2)   /* nothing */
+#define        NOTE(s) /* nothing */
+#endif
+
+/*
+ - matcher - the actual matching engine
+ == static int matcher(register struct re_guts *g, char *string, \
+ ==    size_t nmatch, regmatch_t pmatch[], int eflags);
+ */
+static int                     /* 0 success, REG_NOMATCH failure */
+matcher(g, string, nmatch, pmatch, eflags)
+register struct re_guts *g;
+char *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+       register char *endp;
+       register int i;
+       struct match mv;
+       register struct match *m = &mv;
+       register char *dp;
+       const register sopno gf = g->firststate+1;      /* +1 for OEND */
+       const register sopno gl = g->laststate;
+       char *start;
+       char *stop;
+
+       /* simplify the situation where possible */
+       if (g->cflags&REG_NOSUB)
+               nmatch = 0;
+       if (eflags&REG_STARTEND) {
+               start = string + pmatch[0].rm_so;
+               stop = string + pmatch[0].rm_eo;
+       } else {
+               start = string;
+               stop = start + strlen(start);
+       }
+       if (stop < start)
+               return(REG_INVARG);
+
+       /* prescreening; this does wonders for this rather slow code */
+       if (g->must != NULL) {
+               for (dp = start; dp < stop; dp++)
+                       if (*dp == g->must[0] && stop - dp >= g->mlen &&
+                               memcmp(dp, g->must, (size_t)g->mlen) == 0)
+                               break;
+               if (dp == stop)         /* we didn't find g->must */
+                       return(REG_NOMATCH);
+       }
+
+       /* match struct setup */
+       m->g = g;
+       m->eflags = eflags;
+       m->pmatch = NULL;
+       m->lastpos = NULL;
+       m->offp = string;
+       m->beginp = start;
+       m->endp = stop;
+       STATESETUP(m, 4);
+       SETUP(m->st);
+       SETUP(m->fresh);
+       SETUP(m->tmp);
+       SETUP(m->empty);
+       CLEAR(m->empty);
+
+       /* this loop does only one repetition except for backrefs */
+       for (;;) {
+               endp = fast(m, start, stop, gf, gl);
+               if (endp == NULL) {             /* a miss */
+                       STATETEARDOWN(m);
+                       return(REG_NOMATCH);
+               }
+               if (nmatch == 0 && !g->backrefs)
+                       break;          /* no further info needed */
+
+               /* where? */
+               assert(m->coldp != NULL);
+               for (;;) {
+                       NOTE("finding start");
+                       endp = slow(m, m->coldp, stop, gf, gl);
+                       if (endp != NULL)
+                               break;
+                       assert(m->coldp < m->endp);
+                       m->coldp++;
+               }
+               if (nmatch == 1 && !g->backrefs)
+                       break;          /* no further info needed */
+
+               /* oh my, he wants the subexpressions... */
+               if (m->pmatch == NULL)
+                       m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
+                                                       sizeof(regmatch_t));
+               if (m->pmatch == NULL) {
+                       STATETEARDOWN(m);
+                       return(REG_ESPACE);
+               }
+               for (i = 1; i <= m->g->nsub; i++)
+                       m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
+               if (!g->backrefs && !(m->eflags&REG_BACKR)) {
+                       NOTE("dissecting");
+                       dp = dissect(m, m->coldp, endp, gf, gl);
+               } else {
+                       if (g->nplus > 0 && m->lastpos == NULL)
+                               m->lastpos = (char **)malloc((g->nplus+1) *
+                                                       sizeof(char *));
+                       if (g->nplus > 0 && m->lastpos == NULL) {
+                               free(m->pmatch);
+                               STATETEARDOWN(m);
+                               return(REG_ESPACE);
+                       }
+                       NOTE("backref dissect");
+                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+               }
+               if (dp != NULL)
+                       break;
+
+               /* uh-oh... we couldn't find a subexpression-level match */
+               assert(g->backrefs);    /* must be back references doing it */
+               assert(g->nplus == 0 || m->lastpos != NULL);
+               for (;;) {
+                       if (dp != NULL || endp <= m->coldp)
+                               break;          /* defeat */
+                       NOTE("backoff");
+                       endp = slow(m, m->coldp, endp-1, gf, gl);
+                       if (endp == NULL)
+                               break;          /* defeat */
+                       /* try it on a shorter possibility */
+#ifndef NDEBUG
+                       for (i = 1; i <= m->g->nsub; i++) {
+                               assert(m->pmatch[i].rm_so == -1);
+                               assert(m->pmatch[i].rm_eo == -1);
+                       }
+#endif
+                       NOTE("backoff dissect");
+                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+               }
+               assert(dp == NULL || dp == endp);
+               if (dp != NULL)         /* found a shorter one */
+                       break;
+
+               /* despite initial appearances, there is no match here */
+               NOTE("false alarm");
+               start = m->coldp + 1;   /* recycle starting later */
+               assert(start <= stop);
+       }
+
+       /* fill in the details if requested */
+       if (nmatch > 0) {
+               pmatch[0].rm_so = m->coldp - m->offp;
+               pmatch[0].rm_eo = endp - m->offp;
+       }
+       if (nmatch > 1) {
+               assert(m->pmatch != NULL);
+               for (i = 1; i < nmatch; i++)
+                       if (i <= m->g->nsub)
+                               pmatch[i] = m->pmatch[i];
+                       else {
+                               pmatch[i].rm_so = -1;
+                               pmatch[i].rm_eo = -1;
+                       }
+       }
+
+       if (m->pmatch != NULL)
+               free((char *)m->pmatch);
+       if (m->lastpos != NULL)
+               free((char *)m->lastpos);
+       STATETEARDOWN(m);
+       return(0);
+}
+
+/*
+ - dissect - figure out what matched what, no back references
+ == static char *dissect(register struct match *m, char *start, \
+ ==    char *stop, sopno startst, sopno stopst);
+ */
+static char *                  /* == stop (success) always */
+dissect(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+       register int i;
+       register sopno ss;      /* start sop of current subRE */
+       register sopno es;      /* end sop of current subRE */
+       register char *sp;      /* start of string matched by it */
+       register char *stp;     /* string matched by it cannot pass here */
+       register char *rest;    /* start of rest of string */
+       register char *tail;    /* string unmatched by rest of RE */
+       register sopno ssub;    /* start sop of subsubRE */
+       register sopno esub;    /* end sop of subsubRE */
+       register char *ssp;     /* start of string matched by subsubRE */
+       register char *sep;     /* end of string matched by subsubRE */
+       register char *oldssp;  /* previous ssp */
+       register char *dp;
+
+       AT("diss", start, stop, startst, stopst);
+       sp = start;
+       for (ss = startst; ss < stopst; ss = es) {
+               /* identify end of subRE */
+               es = ss;
+               switch (OP(m->g->strip[es])) {
+               case OPLUS_:
+               case OQUEST_:
+                       es += OPND(m->g->strip[es]);
+                       break;
+               case OCH_:
+                       while (OP(m->g->strip[es]) != O_CH)
+                               es += OPND(m->g->strip[es]);
+                       break;
+               }
+               es++;
+
+               /* figure out what it matched */
+               switch (OP(m->g->strip[ss])) {
+               case OEND:
+                       assert(nope);
+                       break;
+               case OCHAR:
+                       sp++;
+                       break;
+               case OBOL:
+               case OEOL:
+               case OBOW:
+               case OEOW:
+                       break;
+               case OANY:
+               case OANYOF:
+                       sp++;
+                       break;
+               case OBACK_:
+               case O_BACK:
+                       assert(nope);
+                       break;
+               /* cases where length of match is hard to find */
+               case OQUEST_:
+                       stp = stop;
+                       for (;;) {
+                               /* how long could this one be? */
+                               rest = slow(m, sp, stp, ss, es);
+                               assert(rest != NULL);   /* it did match */
+                               /* could the rest match the rest? */
+                               tail = slow(m, rest, stop, es, stopst);
+                               if (tail == stop)
+                                       break;          /* yes! */
+                               /* no -- try a shorter match for this one */
+                               stp = rest - 1;
+                               assert(stp >= sp);      /* it did work */
+                       }
+                       ssub = ss + 1;
+                       esub = es - 1;
+                       /* did innards match? */
+                       if (slow(m, sp, rest, ssub, esub) != NULL) {
+                               dp = dissect(m, sp, rest, ssub, esub);
+                               assert(dp == rest);
+                       } else          /* no */
+                               assert(sp == rest);
+                       sp = rest;
+                       break;
+               case OPLUS_:
+                       stp = stop;
+                       for (;;) {
+                               /* how long could this one be? */
+                               rest = slow(m, sp, stp, ss, es);
+                               assert(rest != NULL);   /* it did match */
+                               /* could the rest match the rest? */
+                               tail = slow(m, rest, stop, es, stopst);
+                               if (tail == stop)
+                                       break;          /* yes! */
+                               /* no -- try a shorter match for this one */
+                               stp = rest - 1;
+                               assert(stp >= sp);      /* it did work */
+                       }
+                       ssub = ss + 1;
+                       esub = es - 1;
+                       ssp = sp;
+                       oldssp = ssp;
+                       for (;;) {      /* find last match of innards */
+                               sep = slow(m, ssp, rest, ssub, esub);
+                               if (sep == NULL || sep == ssp)
+                                       break;  /* failed or matched null */
+                               oldssp = ssp;   /* on to next try */
+                               ssp = sep;
+                       }
+                       if (sep == NULL) {
+                               /* last successful match */
+                               sep = ssp;
+                               ssp = oldssp;
+                       }
+                       assert(sep == rest);    /* must exhaust substring */
+                       assert(slow(m, ssp, sep, ssub, esub) == rest);
+                       dp = dissect(m, ssp, sep, ssub, esub);
+                       assert(dp == sep);
+                       sp = rest;
+                       break;
+               case OCH_:
+                       stp = stop;
+                       for (;;) {
+                               /* how long could this one be? */
+                               rest = slow(m, sp, stp, ss, es);
+                               assert(rest != NULL);   /* it did match */
+                               /* could the rest match the rest? */
+                               tail = slow(m, rest, stop, es, stopst);
+                               if (tail == stop)
+                                       break;          /* yes! */
+                               /* no -- try a shorter match for this one */
+                               stp = rest - 1;
+                               assert(stp >= sp);      /* it did work */
+                       }
+                       ssub = ss + 1;
+                       esub = ss + OPND(m->g->strip[ss]) - 1;
+                       assert(OP(m->g->strip[esub]) == OOR1);
+                       for (;;) {      /* find first matching branch */
+                               if (slow(m, sp, rest, ssub, esub) == rest)
+                                       break;  /* it matched all of it */
+                               /* that one missed, try next one */
+                               assert(OP(m->g->strip[esub]) == OOR1);
+                               esub++;
+                               assert(OP(m->g->strip[esub]) == OOR2);
+                               ssub = esub + 1;
+                               esub += OPND(m->g->strip[esub]);
+                               if (OP(m->g->strip[esub]) == OOR2)
+                                       esub--;
+                               else
+                                       assert(OP(m->g->strip[esub]) == O_CH);
+                       }
+                       dp = dissect(m, sp, rest, ssub, esub);
+                       assert(dp == rest);
+                       sp = rest;
+                       break;
+               case O_PLUS:
+               case O_QUEST:
+               case OOR1:
+               case OOR2:
+               case O_CH:
+                       assert(nope);
+                       break;
+               case OLPAREN:
+                       i = OPND(m->g->strip[ss]);
+                       assert(0 < i && i <= m->g->nsub);
+                       m->pmatch[i].rm_so = sp - m->offp;
+                       break;
+               case ORPAREN:
+                       i = OPND(m->g->strip[ss]);
+                       assert(0 < i && i <= m->g->nsub);
+                       m->pmatch[i].rm_eo = sp - m->offp;
+                       break;
+               default:                /* uh oh */
+                       assert(nope);
+                       break;
+               }
+       }
+
+       assert(sp == stop);
+       return(sp);
+}
+
+/*
+ - backref - figure out what matched what, figuring in back references
+ == static char *backref(register struct match *m, char *start, \
+ ==    char *stop, sopno startst, sopno stopst, sopno lev);
+ */
+static char *                  /* == stop (success) or NULL (failure) */
+backref(m, start, stop, startst, stopst, lev)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+sopno lev;                     /* PLUS nesting level */
+{
+       register int i;
+       register sopno ss;      /* start sop of current subRE */
+       register char *sp;      /* start of string matched by it */
+       register sopno ssub;    /* start sop of subsubRE */
+       register sopno esub;    /* end sop of subsubRE */
+       register char *ssp;     /* start of string matched by subsubRE */
+       register char *dp;
+       register size_t len;
+       register int hard;
+       register sop s;
+       register regoff_t offsave;
+       register cset *cs;
+
+       AT("back", start, stop, startst, stopst);
+       sp = start;
+
+       /* get as far as we can with easy stuff */
+       hard = 0;
+       for (ss = startst; !hard && ss < stopst; ss++)
+               switch (OP(s = m->g->strip[ss])) {
+               case OCHAR:
+                       if (sp == stop || *sp++ != (char)OPND(s))
+                               return(NULL);
+                       break;
+               case OANY:
+                       if (sp == stop)
+                               return(NULL);
+                       sp++;
+                       break;
+               case OANYOF:
+                       cs = &m->g->sets[OPND(s)];
+                       if (sp == stop || !CHIN(cs, *sp++))
+                               return(NULL);
+                       break;
+               case OBOL:
+                       if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+                                       (sp < m->endp && *(sp-1) == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case OEOL:
+                       if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+                                       (sp < m->endp && *sp == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case OBOW:
+                       if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+                                       (sp < m->endp && *(sp-1) == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) ||
+                                       (sp > m->beginp &&
+                                                       !ISWORD(*(sp-1))) ) &&
+                                       (sp < m->endp && ISWORD(*sp)) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case OEOW:
+                       if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+                                       (sp < m->endp && *sp == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) ||
+                                       (sp < m->endp && !ISWORD(*sp)) ) &&
+                                       (sp > m->beginp && ISWORD(*(sp-1))) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case O_QUEST:
+                       break;
+               case OOR1:      /* matches null but needs to skip */
+                       ss++;
+                       s = m->g->strip[ss];
+                       do {
+                               assert(OP(s) == OOR2);
+                               ss += OPND(s);
+                       } while (OP(s = m->g->strip[ss]) != O_CH);
+                       /* note that the ss++ gets us past the O_CH */
+                       break;
+               default:        /* have to make a choice */
+                       hard = 1;
+                       break;
+               }
+       if (!hard) {            /* that was it! */
+               if (sp != stop)
+                       return(NULL);
+               return(sp);
+       }
+       ss--;                   /* adjust for the for's final increment */
+
+       /* the hard stuff */
+       AT("hard", sp, stop, ss, stopst);
+       s = m->g->strip[ss];
+       switch (OP(s)) {
+       case OBACK_:            /* the vilest depths */
+               i = OPND(s);
+               assert(0 < i && i <= m->g->nsub);
+               if (m->pmatch[i].rm_eo == -1)
+                       return(NULL);
+               assert(m->pmatch[i].rm_so != -1);
+               len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+               assert(stop - m->beginp >= len);
+               if (sp > stop - len)
+                       return(NULL);   /* not enough left to match */
+               ssp = m->offp + m->pmatch[i].rm_so;
+               if (memcmp(sp, ssp, len) != 0)
+                       return(NULL);
+               while (m->g->strip[ss] != SOP(O_BACK, i))
+                       ss++;
+               return(backref(m, sp+len, stop, ss+1, stopst, lev));
+               break;
+       case OQUEST_:           /* to null or not */
+               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               if (dp != NULL)
+                       return(dp);     /* not */
+               return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+               break;
+       case OPLUS_:
+               assert(m->lastpos != NULL);
+               assert(lev+1 <= m->g->nplus);
+               m->lastpos[lev+1] = sp;
+               return(backref(m, sp, stop, ss+1, stopst, lev+1));
+               break;
+       case O_PLUS:
+               if (sp == m->lastpos[lev])      /* last pass matched null */
+                       return(backref(m, sp, stop, ss+1, stopst, lev-1));
+               /* try another pass */
+               m->lastpos[lev] = sp;
+               dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+               if (dp == NULL)
+                       return(backref(m, sp, stop, ss+1, stopst, lev-1));
+               else
+                       return(dp);
+               break;
+       case OCH_:              /* find the right one, if any */
+               ssub = ss + 1;
+               esub = ss + OPND(s) - 1;
+               assert(OP(m->g->strip[esub]) == OOR1);
+               for (;;) {      /* find first matching branch */
+                       dp = backref(m, sp, stop, ssub, esub, lev);
+                       if (dp != NULL)
+                               return(dp);
+                       /* that one missed, try next one */
+                       if (OP(m->g->strip[esub]) == O_CH)
+                               return(NULL);   /* there is none */
+                       esub++;
+                       assert(OP(m->g->strip[esub]) == OOR2);
+                       ssub = esub + 1;
+                       esub += OPND(m->g->strip[esub]);
+                       if (OP(m->g->strip[esub]) == OOR2)
+                               esub--;
+                       else
+                               assert(OP(m->g->strip[esub]) == O_CH);
+               }
+               break;
+       case OLPAREN:           /* must undo assignment if rest fails */
+               i = OPND(s);
+               assert(0 < i && i <= m->g->nsub);
+               offsave = m->pmatch[i].rm_so;
+               m->pmatch[i].rm_so = sp - m->offp;
+               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               if (dp != NULL)
+                       return(dp);
+               m->pmatch[i].rm_so = offsave;
+               return(NULL);
+               break;
+       case ORPAREN:           /* must undo assignment if rest fails */
+               i = OPND(s);
+               assert(0 < i && i <= m->g->nsub);
+               offsave = m->pmatch[i].rm_eo;
+               m->pmatch[i].rm_eo = sp - m->offp;
+               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               if (dp != NULL)
+                       return(dp);
+               m->pmatch[i].rm_eo = offsave;
+               return(NULL);
+               break;
+       default:                /* uh oh */
+               assert(nope);
+               break;
+       }
+
+       /* "can't happen" */
+       assert(nope);
+       /* NOTREACHED */
+       return((char *)NULL);   /* dummy */
+}
+
+/*
+ - fast - step through the string at top speed
+ == static char *fast(register struct match *m, char *start, \
+ ==    char *stop, sopno startst, sopno stopst);
+ */
+static char *                  /* where tentative match ended, or NULL */
+fast(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+       register states st = m->st;
+       register states fresh = m->fresh;
+       register states tmp = m->tmp;
+       register char *p = start;
+       register int c = (start == m->beginp) ? OUT : *(start-1);
+       register int lastc;     /* previous c */
+       register int flagch;
+       register int i;
+       register char *coldp;   /* last p after which no match was underway */
+
+       CLEAR(st);
+       SET1(st, startst);
+       st = step(m->g, startst, stopst, st, NOTHING, st);
+       ASSIGN(fresh, st);
+       SP("start", st, *p);
+       coldp = NULL;
+       for (;;) {
+               /* next character */
+               lastc = c;
+               c = (p == m->endp) ? OUT : *p;
+               if (EQ(st, fresh))
+                       coldp = p;
+
+               /* is there an EOL and/or BOL between lastc and c? */
+               flagch = '\0';
+               i = 0;
+               if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+                       flagch = BOL;
+                       i = m->g->nbol;
+               }
+               if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+                       flagch = (flagch == BOL) ? BOLEOL : EOL;
+                       i += m->g->neol;
+               }
+               if (i != 0) {
+                       for (; i > 0; i--)
+                               st = step(m->g, startst, stopst, st, flagch, st);
+                       SP("boleol", st, c);
+               }
+
+               /* how about a word boundary? */
+               if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+                                       (c != OUT && ISWORD(c)) ) {
+                       flagch = BOW;
+               }
+               if ( (lastc != OUT && ISWORD(lastc)) &&
+                               (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+                       flagch = EOW;
+               }
+               if (flagch == BOW || flagch == EOW) {
+                       st = step(m->g, startst, stopst, st, flagch, st);
+                       SP("boweow", st, c);
+               }
+
+               /* are we done? */
+               if (ISSET(st, stopst) || p == stop)
+                       break;          /* NOTE BREAK OUT */
+
+               /* no, we must deal with this character */
+               ASSIGN(tmp, st);
+               ASSIGN(st, fresh);
+               assert(c != OUT);
+               st = step(m->g, startst, stopst, tmp, c, st);
+               SP("aft", st, c);
+               assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+               p++;
+       }
+
+       assert(coldp != NULL);
+       m->coldp = coldp;
+       if (ISSET(st, stopst))
+               return(p+1);
+       else
+               return(NULL);
+}
+
+/*
+ - slow - step through the string more deliberately
+ == static char *slow(register struct match *m, char *start, \
+ ==    char *stop, sopno startst, sopno stopst);
+ */
+static char *                  /* where it ended */
+slow(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+       register states st = m->st;
+       register states empty = m->empty;
+       register states tmp = m->tmp;
+       register char *p = start;
+       register int c = (start == m->beginp) ? OUT : *(start-1);
+       register int lastc;     /* previous c */
+       register int flagch;
+       register int i;
+       register char *matchp;  /* last p at which a match ended */
+
+       AT("slow", start, stop, startst, stopst);
+       CLEAR(st);
+       SET1(st, startst);
+       SP("sstart", st, *p);
+       st = step(m->g, startst, stopst, st, NOTHING, st);
+       matchp = NULL;
+       for (;;) {
+               /* next character */
+               lastc = c;
+               c = (p == m->endp) ? OUT : *p;
+
+               /* is there an EOL and/or BOL between lastc and c? */
+               flagch = '\0';
+               i = 0;
+               if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+                       flagch = BOL;
+                       i = m->g->nbol;
+               }
+               if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+                       flagch = (flagch == BOL) ? BOLEOL : EOL;
+                       i += m->g->neol;
+               }
+               if (i != 0) {
+                       for (; i > 0; i--)
+                               st = step(m->g, startst, stopst, st, flagch, st);
+                       SP("sboleol", st, c);
+               }
+
+               /* how about a word boundary? */
+               if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+                                       (c != OUT && ISWORD(c)) ) {
+                       flagch = BOW;
+               }
+               if ( (lastc != OUT && ISWORD(lastc)) &&
+                               (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+                       flagch = EOW;
+               }
+               if (flagch == BOW || flagch == EOW) {
+                       st = step(m->g, startst, stopst, st, flagch, st);
+                       SP("sboweow", st, c);
+               }
+
+               /* are we done? */
+               if (ISSET(st, stopst))
+                       matchp = p;
+               if (EQ(st, empty) || p == stop)
+                       break;          /* NOTE BREAK OUT */
+
+               /* no, we must deal with this character */
+               ASSIGN(tmp, st);
+               ASSIGN(st, empty);
+               assert(c != OUT);
+               st = step(m->g, startst, stopst, tmp, c, st);
+               SP("saft", st, c);
+               assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+               p++;
+       }
+
+       return(matchp);
+}
+
+
+/*
+ - step - map set of states reachable before char to set reachable after
+ == static states step(register struct re_guts *g, sopno start, sopno stop, \
+ ==    register states bef, int ch, register states aft);
+ == #define    BOL     (OUT+1)
+ == #define    EOL     (BOL+1)
+ == #define    BOLEOL  (BOL+2)
+ == #define    NOTHING (BOL+3)
+ == #define    BOW     (BOL+4)
+ == #define    EOW     (BOL+5)
+ == #define    CODEMAX (BOL+5)         // highest code used
+ == #define    NONCHAR(c)      ((c) > CHAR_MAX)
+ == #define    NNONCHAR        (CODEMAX-CHAR_MAX)
+ */
+static states
+step(g, start, stop, bef, ch, aft)
+register struct re_guts *g;
+sopno start;                   /* start state within strip */
+sopno stop;                    /* state after stop state within strip */
+register states bef;           /* states reachable before */
+int ch;                                /* character or NONCHAR code */
+register states aft;           /* states already known reachable after */
+{
+       register cset *cs;
+       register sop s;
+       register sopno pc;
+       register onestate here;         /* note, macros know this name */
+       register sopno look;
+       register long i;
+
+       for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
+               s = g->strip[pc];
+               switch (OP(s)) {
+               case OEND:
+                       assert(pc == stop-1);
+                       break;
+               case OCHAR:
+                       /* only characters can match */
+                       assert(!NONCHAR(ch) || ch != (char)OPND(s));
+                       if (ch == (char)OPND(s))
+                               FWD(aft, bef, 1);
+                       break;
+               case OBOL:
+                       if (ch == BOL || ch == BOLEOL)
+                               FWD(aft, bef, 1);
+                       break;
+               case OEOL:
+                       if (ch == EOL || ch == BOLEOL)
+                               FWD(aft, bef, 1);
+                       break;
+               case OBOW:
+                       if (ch == BOW)
+                               FWD(aft, bef, 1);
+                       break;
+               case OEOW:
+                       if (ch == EOW)
+                               FWD(aft, bef, 1);
+                       break;
+               case OANY:
+                       if (!NONCHAR(ch))
+                               FWD(aft, bef, 1);
+                       break;
+               case OANYOF:
+                       cs = &g->sets[OPND(s)];
+                       if (!NONCHAR(ch) && CHIN(cs, ch))
+                               FWD(aft, bef, 1);
+                       break;
+               case OBACK_:            /* ignored here */
+               case O_BACK:
+                       FWD(aft, aft, 1);
+                       break;
+               case OPLUS_:            /* forward, this is just an empty */
+                       FWD(aft, aft, 1);
+                       break;
+               case O_PLUS:            /* both forward and back */
+                       FWD(aft, aft, 1);
+                       i = ISSETBACK(aft, OPND(s));
+                       BACK(aft, aft, OPND(s));
+                       if (!i && ISSETBACK(aft, OPND(s))) {
+                               /* oho, must reconsider loop body */
+                               pc -= OPND(s) + 1;
+                               INIT(here, pc);
+                       }
+                       break;
+               case OQUEST_:           /* two branches, both forward */
+                       FWD(aft, aft, 1);
+                       FWD(aft, aft, OPND(s));
+                       break;
+               case O_QUEST:           /* just an empty */
+                       FWD(aft, aft, 1);
+                       break;
+               case OLPAREN:           /* not significant here */
+               case ORPAREN:
+                       FWD(aft, aft, 1);
+                       break;
+               case OCH_:              /* mark the first two branches */
+                       FWD(aft, aft, 1);
+                       assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+                       FWD(aft, aft, OPND(s));
+                       break;
+               case OOR1:              /* done a branch, find the O_CH */
+                       if (ISSTATEIN(aft, here)) {
+                               for (look = 1;
+                                               OP(s = g->strip[pc+look]) != O_CH;
+                                               look += OPND(s))
+                                       assert(OP(s) == OOR2);
+                               FWD(aft, aft, look);
+                       }
+                       break;
+               case OOR2:              /* propagate OCH_'s marking */
+                       FWD(aft, aft, 1);
+                       if (OP(g->strip[pc+OPND(s)]) != O_CH) {
+                               assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+                               FWD(aft, aft, OPND(s));
+                       }
+                       break;
+               case O_CH:              /* just empty */
+                       FWD(aft, aft, 1);
+                       break;
+               default:                /* ooooops... */
+                       assert(nope);
+                       break;
+               }
+       }
+
+       return(aft);
+}
+
+#ifdef REDEBUG
+/*
+ - print - print a set of states
+ == #ifdef REDEBUG
+ == static void print(struct match *m, char *caption, states st, \
+ ==    int ch, FILE *d);
+ == #endif
+ */
+static void
+print(m, caption, st, ch, d)
+struct match *m;
+char *caption;
+states st;
+int ch;
+FILE *d;
+{
+       register struct re_guts *g = m->g;
+       register int i;
+       register int first = 1;
+
+       if (!(m->eflags&REG_TRACE))
+               return;
+
+       fprintf(d, "%s", caption);
+       if (ch != '\0')
+               fprintf(d, " %s", pchar(ch));
+       for (i = 0; i < g->nstates; i++)
+               if (ISSET(st, i)) {
+                       fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
+                       first = 0;
+               }
+       fprintf(d, "\n");
+}
+
+/* 
+ - at - print current situation
+ == #ifdef REDEBUG
+ == static void at(struct match *m, char *title, char *start, char *stop, \
+ ==                                            sopno startst, sopno stopst);
+ == #endif
+ */
+static void
+at(m, title, start, stop, startst, stopst)
+struct match *m;
+char *title;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+       if (!(m->eflags&REG_TRACE))
+               return;
+
+       printf("%s %s-", title, pchar(*start));
+       printf("%s ", pchar(*stop));
+       printf("%ld-%ld\n", (long)startst, (long)stopst);
+}
+
+#ifndef PCHARDONE
+#define        PCHARDONE       /* never again */
+/*
+ - pchar - make a character printable
+ == #ifdef REDEBUG
+ == static char *pchar(int ch);
+ == #endif
+ *
+ * Is this identical to regchar() over in debug.c?  Well, yes.  But a
+ * duplicate here avoids having a debugging-capable regexec.o tied to
+ * a matching debug.o, and this is convenient.  It all disappears in
+ * the non-debug compilation anyway, so it doesn't matter much.
+ */
+static char *                  /* -> representation */
+pchar(ch)
+int ch;
+{
+       static char pbuf[10];
+
+       if (isprint(ch) || ch == ' ')
+               sprintf(pbuf, "%c", ch);
+       else
+               sprintf(pbuf, "\\%o", ch);
+       return(pbuf);
+}
+#endif
+#endif
+
+#undef matcher
+#undef fast
+#undef slow
+#undef dissect
+#undef backref
+#undef step
+#undef print
+#undef at
+#undef match
diff --git a/vcnet/regex/engine.ih b/vcnet/regex/engine.ih
new file mode 100644 (file)
index 0000000..cc98334
--- /dev/null
@@ -0,0 +1,35 @@
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === engine.c === */
+static int matcher(register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static char *dissect(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *backref(register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
+static char *fast(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *slow(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static states step(register struct re_guts *g, sopno start, sopno stop, register states bef, int ch, register states aft);
+#define        BOL     (OUT+1)
+#define        EOL     (BOL+1)
+#define        BOLEOL  (BOL+2)
+#define        NOTHING (BOL+3)
+#define        BOW     (BOL+4)
+#define        EOW     (BOL+5)
+#define        CODEMAX (BOL+5)         /* highest code used */
+#define        NONCHAR(c)      ((c) > CHAR_MAX)
+#define        NNONCHAR        (CODEMAX-CHAR_MAX)
+#ifdef REDEBUG
+static void print(struct match *m, char *caption, states st, int ch, FILE *d);
+#endif
+#ifdef REDEBUG
+static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
+#endif
+#ifdef REDEBUG
+static char *pchar(int ch);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/vcnet/regex/main.c b/vcnet/regex/main.c
new file mode 100644 (file)
index 0000000..0221e77
--- /dev/null
@@ -0,0 +1,510 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <assert.h>
+
+#include "main.ih"
+
+char *progname;
+int debug = 0;
+int line = 0;
+int status = 0;
+
+int copts = REG_EXTENDED;
+int eopts = 0;
+regoff_t startoff = 0;
+regoff_t endoff = 0;
+
+
+extern int split();
+extern void regprint();
+
+/*
+ - main - do the simple case, hand off to regress() for regression
+ */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       regex_t re;
+#      define  NS      10
+       regmatch_t subs[NS];
+       char erbuf[100];
+       int err;
+       size_t len;
+       int c;
+       int errflg = 0;
+       register int i;
+       extern int optind;
+       extern char *optarg;
+
+       progname = argv[0];
+
+       while ((c = getopt(argc, argv, "c:e:S:E:x")) != EOF)
+               switch (c) {
+               case 'c':       /* compile options */
+                       copts = options('c', optarg);
+                       break;
+               case 'e':       /* execute options */
+                       eopts = options('e', optarg);
+                       break;
+               case 'S':       /* start offset */
+                       startoff = (regoff_t)atoi(optarg);
+                       break;
+               case 'E':       /* end offset */
+                       endoff = (regoff_t)atoi(optarg);
+                       break;
+               case 'x':       /* Debugging. */
+                       debug++;
+                       break;
+               case '?':
+               default:
+                       errflg++;
+                       break;
+               }
+       if (errflg) {
+               fprintf(stderr, "usage: %s ", progname);
+               fprintf(stderr, "[-c copt][-C][-d] [re]\n");
+               exit(2);
+       }
+
+       if (optind >= argc) {
+               regress(stdin);
+               exit(status);
+       }
+
+       err = regcomp(&re, argv[optind++], copts);
+       if (err) {
+               len = regerror(err, &re, erbuf, sizeof(erbuf));
+               fprintf(stderr, "error %s, %d/%d `%s'\n",
+                       eprint(err), len, sizeof(erbuf), erbuf);
+               exit(status);
+       }
+       regprint(&re, stdout);  
+
+       if (optind >= argc) {
+               regfree(&re);
+               exit(status);
+       }
+
+       if (eopts&REG_STARTEND) {
+               subs[0].rm_so = startoff;
+               subs[0].rm_eo = strlen(argv[optind]) - endoff;
+       }
+       err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
+       if (err) {
+               len = regerror(err, &re, erbuf, sizeof(erbuf));
+               fprintf(stderr, "error %s, %d/%d `%s'\n",
+                       eprint(err), len, sizeof(erbuf), erbuf);
+               exit(status);
+       }
+       if (!(copts&REG_NOSUB)) {
+               len = (int)(subs[0].rm_eo - subs[0].rm_so);
+               if (subs[0].rm_so != -1) {
+                       if (len != 0)
+                               printf("match `%.*s'\n", len,
+                                       argv[optind] + subs[0].rm_so);
+                       else
+                               printf("match `'@%.1s\n",
+                                       argv[optind] + subs[0].rm_so);
+               }
+               for (i = 1; i < NS; i++)
+                       if (subs[i].rm_so != -1)
+                               printf("(%d) `%.*s'\n", i,
+                                       (int)(subs[i].rm_eo - subs[i].rm_so),
+                                       argv[optind] + subs[i].rm_so);
+       }
+       exit(status);
+}
+
+/*
+ - regress - main loop of regression test
+ == void regress(FILE *in);
+ */
+void
+regress(in)
+FILE *in;
+{
+       char inbuf[1000];
+#      define  MAXF    10
+       char *f[MAXF];
+       int nf;
+       int i;
+       char erbuf[100];
+       size_t ne;
+       char *badpat = "invalid regular expression";
+#      define  SHORT   10
+       char *bpname = "REG_BADPAT";
+       regex_t re;
+
+       while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
+               line++;
+               if (inbuf[0] == '#' || inbuf[0] == '\n')
+                       continue;                       /* NOTE CONTINUE */
+               inbuf[strlen(inbuf)-1] = '\0';  /* get rid of stupid \n */
+               if (debug)
+                       fprintf(stdout, "%d:\n", line);
+               nf = split(inbuf, f, MAXF, "\t\t");
+               if (nf < 3) {
+                       fprintf(stderr, "bad input, line %d\n", line);
+                       exit(1);
+               }
+               for (i = 0; i < nf; i++)
+                       if (strcmp(f[i], "\"\"") == 0)
+                               f[i] = "";
+               if (nf <= 3)
+                       f[3] = NULL;
+               if (nf <= 4)
+                       f[4] = NULL;
+               try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
+               if (opt('&', f[1]))     /* try with either type of RE */
+                       try(f[0], f[1], f[2], f[3], f[4],
+                                       options('c', f[1]) &~ REG_EXTENDED);
+       }
+
+       ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
+       if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
+               fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
+                                                       erbuf, badpat);
+               status = 1;
+       }
+       ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT);
+       if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
+                                               ne != strlen(badpat)+1) {
+               fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
+                                               erbuf, SHORT-1, badpat);
+               status = 1;
+       }
+       ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
+       if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
+               fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
+                                               erbuf, bpname);
+               status = 1;
+       }
+       re.re_endp = bpname;
+       ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
+       if (atoi(erbuf) != (int)REG_BADPAT) {
+               fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
+                                               erbuf, (long)REG_BADPAT);
+               status = 1;
+       } else if (ne != strlen(erbuf)+1) {
+               fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
+                                               erbuf, (long)REG_BADPAT);
+               status = 1;
+       }
+}
+
+/*
+ - try - try it, and report on problems
+ == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
+ */
+void
+try(f0, f1, f2, f3, f4, opts)
+char *f0;
+char *f1;
+char *f2;
+char *f3;
+char *f4;
+int opts;                      /* may not match f1 */
+{
+       regex_t re;
+#      define  NSUBS   10
+       regmatch_t subs[NSUBS];
+#      define  NSHOULD 15
+       char *should[NSHOULD];
+       int nshould;
+       char erbuf[100];
+       int err;
+       int len;
+       char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
+       register int i;
+       char *grump;
+       char f0copy[1000];
+       char f2copy[1000];
+
+       strcpy(f0copy, f0);
+       re.re_endp = (opts&REG_PEND) ? f0copy + strlen(f0copy) : NULL;
+       fixstr(f0copy);
+       err = regcomp(&re, f0copy, opts);
+       if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
+               /* unexpected error or wrong error */
+               len = regerror(err, &re, erbuf, sizeof(erbuf));
+               fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
+                                       line, type, eprint(err), len,
+                                       sizeof(erbuf), erbuf);
+               status = 1;
+       } else if (err == 0 && opt('C', f1)) {
+               /* unexpected success */
+               fprintf(stderr, "%d: %s should have given REG_%s\n",
+                                               line, type, f2);
+               status = 1;
+               err = 1;        /* so we won't try regexec */
+       }
+
+       if (err != 0) {
+               regfree(&re);
+               return;
+       }
+
+       strcpy(f2copy, f2);
+       fixstr(f2copy);
+
+       if (options('e', f1)&REG_STARTEND) {
+               if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
+                       fprintf(stderr, "%d: bad STARTEND syntax\n", line);
+               subs[0].rm_so = strchr(f2, '(') - f2 + 1;
+               subs[0].rm_eo = strchr(f2, ')') - f2;
+       }
+       err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
+
+       if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
+               /* unexpected error or wrong error */
+               len = regerror(err, &re, erbuf, sizeof(erbuf));
+               fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
+                                       line, type, eprint(err), len,
+                                       sizeof(erbuf), erbuf);
+               status = 1;
+       } else if (err != 0) {
+               /* nothing more to check */
+       } else if (f3 == NULL) {
+               /* unexpected success */
+               fprintf(stderr, "%d: %s exec should have failed\n",
+                                               line, type);
+               status = 1;
+               err = 1;                /* just on principle */
+       } else if (opts&REG_NOSUB) {
+               /* nothing more to check */
+       } else if ((grump = check(f2, subs[0], f3)) != NULL) {
+               fprintf(stderr, "%d: %s %s\n", line, type, grump);
+               status = 1;
+               err = 1;
+       }
+
+       if (err != 0 || f4 == NULL) {
+               regfree(&re);
+               return;
+       }
+
+       for (i = 1; i < NSHOULD; i++)
+               should[i] = NULL;
+       nshould = split(f4, should+1, NSHOULD-1, ",");
+       if (nshould == 0) {
+               nshould = 1;
+               should[1] = "";
+       }
+       for (i = 1; i < NSUBS; i++) {
+               grump = check(f2, subs[i], should[i]);
+               if (grump != NULL) {
+                       fprintf(stderr, "%d: %s $%d %s\n", line,
+                                                       type, i, grump);
+                       status = 1;
+                       err = 1;
+               }
+       }
+
+       regfree(&re);
+}
+
+/*
+ - options - pick options out of a regression-test string
+ == int options(int type, char *s);
+ */
+int
+options(type, s)
+int type;                      /* 'c' compile, 'e' exec */
+char *s;
+{
+       register char *p;
+       register int o = (type == 'c') ? copts : eopts;
+       register char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
+
+       for (p = s; *p != '\0'; p++)
+               if (strchr(legal, *p) != NULL)
+                       switch (*p) {
+                       case 'b':
+                               o &= ~REG_EXTENDED;
+                               break;
+                       case 'i':
+                               o |= REG_ICASE;
+                               break;
+                       case 's':
+                               o |= REG_NOSUB;
+                               break;
+                       case 'n':
+                               o |= REG_NEWLINE;
+                               break;
+                       case 'm':
+                               o &= ~REG_EXTENDED;
+                               o |= REG_NOSPEC;
+                               break;
+                       case 'p':
+                               o |= REG_PEND;
+                               break;
+                       case '^':
+                               o |= REG_NOTBOL;
+                               break;
+                       case '$':
+                               o |= REG_NOTEOL;
+                               break;
+                       case '#':
+                               o |= REG_STARTEND;
+                               break;
+                       case 't':       /* trace */
+                               o |= REG_TRACE;
+                               break;
+                       case 'l':       /* force long representation */
+                               o |= REG_LARGE;
+                               break;
+                       case 'r':       /* force backref use */
+                               o |= REG_BACKR;
+                               break;
+                       }
+       return(o);
+}
+
+/*
+ - opt - is a particular option in a regression string?
+ == int opt(int c, char *s);
+ */
+int                            /* predicate */
+opt(c, s)
+int c;
+char *s;
+{
+       return(strchr(s, c) != NULL);
+}
+
+/*
+ - fixstr - transform magic characters in strings
+ == void fixstr(register char *p);
+ */
+void
+fixstr(p)
+register char *p;
+{
+       if (p == NULL)
+               return;
+
+       for (; *p != '\0'; p++)
+               if (*p == 'N')
+                       *p = '\n';
+               else if (*p == 'T')
+                       *p = '\t';
+               else if (*p == 'S')
+                       *p = ' ';
+               else if (*p == 'Z')
+                       *p = '\0';
+}
+
+/*
+ - check - check a substring match
+ == char *check(char *str, regmatch_t sub, char *should);
+ */
+char *                         /* NULL or complaint */
+check(str, sub, should)
+char *str;
+regmatch_t sub;
+char *should;
+{
+       register int len;
+       register int shlen;
+       register char *p;
+       static char grump[500];
+       register char *at = NULL;
+
+       if (should != NULL && strcmp(should, "-") == 0)
+               should = NULL;
+       if (should != NULL && should[0] == '@') {
+               at = should + 1;
+               should = "";
+       }
+
+       /* check rm_so and rm_eo for consistency */
+       if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
+                               (sub.rm_so != -1 && sub.rm_eo == -1) ||
+                               (sub.rm_so != -1 && sub.rm_so < 0) ||
+                               (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
+               sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
+                                                       (long)sub.rm_eo);
+               return(grump);
+       }
+
+       /* check for no match */
+       if (sub.rm_so == -1 && should == NULL)
+               return(NULL);
+       if (sub.rm_so == -1)
+               return("did not match");
+
+       /* check for in range */
+       if (sub.rm_eo > strlen(str)) {
+               sprintf(grump, "start %ld end %ld, past end of string",
+                                       (long)sub.rm_so, (long)sub.rm_eo);
+               return(grump);
+       }
+
+       len = (int)(sub.rm_eo - sub.rm_so);
+       shlen = (int)strlen(should);
+       p = str + sub.rm_so;
+
+       /* check for not supposed to match */
+       if (should == NULL) {
+               sprintf(grump, "matched `%.*s'", len, p);
+               return(grump);
+       }
+
+       /* check for wrong match */
+       if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
+               sprintf(grump, "matched `%.*s' instead", len, p);
+               return(grump);
+       }
+       if (shlen > 0)
+               return(NULL);
+
+       /* check null match in right place */
+       if (at == NULL)
+               return(NULL);
+       shlen = strlen(at);
+       if (shlen == 0)
+               shlen = 1;      /* force check for end-of-string */
+       if (strncmp(p, at, shlen) != 0) {
+               sprintf(grump, "matched null at `%.20s'", p);
+               return(grump);
+       }
+       return(NULL);
+}
+
+/*
+ - eprint - convert error number to name
+ == static char *eprint(int err);
+ */
+static char *
+eprint(err)
+int err;
+{
+       static char epbuf[100];
+       size_t len;
+
+       len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf));
+       assert(len <= sizeof(epbuf));
+       return(epbuf);
+}
+
+/*
+ - efind - convert error name to number
+ == static int efind(char *name);
+ */
+static int
+efind(name)
+char *name;
+{
+       static char efbuf[100];
+       size_t n;
+       regex_t re;
+
+       sprintf(efbuf, "REG_%s", name);
+       assert(strlen(efbuf) < sizeof(efbuf));
+       re.re_endp = efbuf;
+       (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
+       return(atoi(efbuf));
+}
diff --git a/vcnet/regex/main.ih b/vcnet/regex/main.ih
new file mode 100644 (file)
index 0000000..5a0118a
--- /dev/null
@@ -0,0 +1,19 @@
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === main.c === */
+void regress(FILE *in);
+void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
+int options(int type, char *s);
+int opt(int c, char *s);
+void fixstr(register char *p);
+char *check(char *str, regmatch_t sub, char *should);
+static char *eprint(int err);
+static int efind(char *name);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/vcnet/regex/mkh b/vcnet/regex/mkh
new file mode 100644 (file)
index 0000000..252b246
--- /dev/null
@@ -0,0 +1,76 @@
+#! /bin/sh
+# mkh - pull headers out of C source
+PATH=/bin:/usr/bin ; export PATH
+
+# egrep pattern to pick out marked lines
+egrep='^ =([   ]|$)'
+
+# Sed program to process marked lines into lines for the header file.
+# The markers have already been removed.  Two things are done here:  removal
+# of backslashed newlines, and some fudging of comments.  The first is done
+# because -o needs to have prototypes on one line to strip them down.
+# Getting comments into the output is tricky; we turn C++-style // comments
+# into /* */ comments, after altering any existing */'s to avoid trouble.
+peel=' /\\$/N
+       /\\\n[  ]*/s///g
+       /\/\//s;\*/;* /;g
+       /\/\//s;//\(.*\);/*\1 */;'
+
+for a
+do
+       case "$a" in
+       -o)     # old (pre-function-prototype) compiler
+               # add code to comment out argument lists
+               peel="$peel
+                       "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1(/*\2*/);'
+               shift
+               ;;
+       -b)     # funny Berkeley __P macro
+               peel="$peel
+                       "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1 __P((\2));'
+               shift
+               ;;
+       -s)     # compiler doesn't like `static foo();'
+               # add code to get rid of the `static'
+               peel="$peel
+                       "'/^static[     ][^\/]*[a-zA-Z0-9_)](.*)/s;static.;;'
+               shift
+               ;;
+       -p)     # private declarations
+               egrep='^ ==([   ]|$)'
+               shift
+               ;;
+       -i)     # wrap in #ifndef, argument is name
+               ifndef="$2"
+               shift ; shift
+               ;;
+       *)      break
+               ;;
+       esac
+done
+
+if test " $ifndef" != " "
+then
+       echo "#ifndef $ifndef"
+       echo "#define   $ifndef /* never again */"
+fi
+echo "/* ========= begin header generated by $0 ========= */"
+echo '#ifdef __cplusplus'
+echo 'extern "C" {'
+echo '#endif'
+for f
+do
+       echo
+       echo "/* === $f === */"
+       egrep "$egrep" $f | sed 's/^ ==*[       ]//;s/^ ==*$//' | sed "$peel"
+       echo
+done
+echo '#ifdef __cplusplus'
+echo '}'
+echo '#endif'
+echo "/* ========= end header generated by $0 ========= */"
+if test " $ifndef" != " "
+then
+       echo "#endif"
+fi
+exit 0
diff --git a/vcnet/regex/regcomp.c b/vcnet/regex/regcomp.c
new file mode 100644 (file)
index 0000000..dc48601
--- /dev/null
@@ -0,0 +1,1603 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+#include "cclass.h"
+#include "cname.h"
+
+/*
+ * parse structure, passed up and down to avoid global variables and
+ * other clumsinesses
+ */
+struct parse {
+       char *next;             /* next character in RE */
+       char *end;              /* end of string (-> NUL normally) */
+       int error;              /* has an error been seen? */
+       sop *strip;             /* malloced strip */
+       sopno ssize;            /* malloced strip size (allocated) */
+       sopno slen;             /* malloced strip length (used) */
+       int ncsalloc;           /* number of csets allocated */
+       struct re_guts *g;
+#      define  NPAREN  10      /* we need to remember () 1-9 for back refs */
+       sopno pbegin[NPAREN];   /* -> ( ([0] unused) */
+       sopno pend[NPAREN];     /* -> ) ([0] unused) */
+};
+
+#include "regcomp.ih"
+
+static char nuls[10];          /* place to point scanner in event of error */
+
+/*
+ * macros for use with parse structure
+ * BEWARE:  these know that the parse structure is named `p' !!!
+ */
+#define        PEEK()  (*p->next)
+#define        PEEK2() (*(p->next+1))
+#define        MORE()  (p->next < p->end)
+#define        MORE2() (p->next+1 < p->end)
+#define        SEE(c)  (MORE() && PEEK() == (c))
+#define        SEETWO(a, b)    (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
+#define        EAT(c)  ((SEE(c)) ? (NEXT(), 1) : 0)
+#define        EATTWO(a, b)    ((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
+#define        NEXT()  (p->next++)
+#define        NEXT2() (p->next += 2)
+#define        NEXTn(n)        (p->next += (n))
+#define        GETNEXT()       (*p->next++)
+#define        SETERROR(e)     seterr(p, (e))
+#define        REQUIRE(co, e)  ((co) || SETERROR(e))
+#define        MUSTSEE(c, e)   (REQUIRE(MORE() && PEEK() == (c), e))
+#define        MUSTEAT(c, e)   (REQUIRE(MORE() && GETNEXT() == (c), e))
+#define        MUSTNOTSEE(c, e)        (REQUIRE(!MORE() || PEEK() != (c), e))
+#define        EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd))
+#define        INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
+#define        AHEAD(pos)              dofwd(p, pos, HERE()-(pos))
+#define        ASTERN(sop, pos)        EMIT(sop, HERE()-pos)
+#define        HERE()          (p->slen)
+#define        THERE()         (p->slen - 1)
+#define        THERETHERE()    (p->slen - 2)
+#define        DROP(n) (p->slen -= (n))
+
+#ifndef NDEBUG
+static int never = 0;          /* for use in asserts; shuts lint up */
+#else
+#define        never   0               /* some <assert.h>s have bugs too */
+#endif
+
+/*
+ - regcomp - interface for parser and compilation
+ = extern int regcomp(regex_t *, const char *, int);
+ = #define     REG_BASIC       0000
+ = #define     REG_EXTENDED    0001
+ = #define     REG_ICASE       0002
+ = #define     REG_NOSUB       0004
+ = #define     REG_NEWLINE     0010
+ = #define     REG_NOSPEC      0020
+ = #define     REG_PEND        0040
+ = #define     REG_DUMP        0200
+ */
+int                            /* 0 success, otherwise REG_something */
+regcomp(preg, pattern, cflags)
+regex_t *preg;
+const char *pattern;
+int cflags;
+{
+       struct parse pa;
+       register struct re_guts *g;
+       register struct parse *p = &pa;
+       register int i;
+       register size_t len;
+#ifdef REDEBUG
+#      define  GOODFLAGS(f)    (f)
+#else
+#      define  GOODFLAGS(f)    ((f)&~REG_DUMP)
+#endif
+
+       cflags = GOODFLAGS(cflags);
+       if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
+               return(REG_INVARG);
+
+       if (cflags&REG_PEND) {
+               if (preg->re_endp < pattern)
+                       return(REG_INVARG);
+               len = preg->re_endp - pattern;
+       } else
+               len = strlen((char *)pattern);
+
+       /* do the mallocs early so failure handling is easy */
+       g = (struct re_guts *)malloc(sizeof(struct re_guts) +
+                                                       (NC-1)*sizeof(cat_t));
+       if (g == NULL)
+               return(REG_ESPACE);
+       p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
+       p->strip = (sop *)malloc(p->ssize * sizeof(sop));
+       p->slen = 0;
+       if (p->strip == NULL) {
+               free((char *)g);
+               return(REG_ESPACE);
+       }
+
+       /* set things up */
+       p->g = g;
+       p->next = (char *)pattern;      /* convenience; we do not modify it */
+       p->end = p->next + len;
+       p->error = 0;
+       p->ncsalloc = 0;
+       for (i = 0; i < NPAREN; i++) {
+               p->pbegin[i] = 0;
+               p->pend[i] = 0;
+       }
+       g->csetsize = NC;
+       g->sets = NULL;
+       g->setbits = NULL;
+       g->ncsets = 0;
+       g->cflags = cflags;
+       g->iflags = 0;
+       g->nbol = 0;
+       g->neol = 0;
+       g->must = NULL;
+       g->mlen = 0;
+       g->nsub = 0;
+       g->ncategories = 1;     /* category 0 is "everything else" */
+       g->categories = &g->catspace[-(CHAR_MIN)];
+       (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));
+       g->backrefs = 0;
+
+       /* do it */
+       EMIT(OEND, 0);
+       g->firststate = THERE();
+       if (cflags&REG_EXTENDED)
+               p_ere(p, OUT);
+       else if (cflags&REG_NOSPEC)
+               p_str(p);
+       else
+               p_bre(p, OUT, OUT);
+       EMIT(OEND, 0);
+       g->laststate = THERE();
+
+       /* tidy up loose ends and fill things in */
+       categorize(p, g);
+       stripsnug(p, g);
+       findmust(p, g);
+       g->nplus = pluscount(p, g);
+       g->magic = MAGIC2;
+       preg->re_nsub = g->nsub;
+       preg->re_g = g;
+       preg->re_magic = MAGIC1;
+#ifndef REDEBUG
+       /* not debugging, so can't rely on the assert() in regexec() */
+       if (g->iflags&BAD)
+               SETERROR(REG_ASSERT);
+#endif
+
+       /* win or lose, we're done */
+       if (p->error != 0)      /* lose */
+               regfree(preg);
+       return(p->error);
+}
+
+/*
+ - p_ere - ERE parser top level, concatenation and alternation
+ == static void p_ere(register struct parse *p, int stop);
+ */
+static void
+p_ere(p, stop)
+register struct parse *p;
+int stop;                      /* character this ERE should end at */
+{
+       register char c;
+       register sopno prevback;
+       register sopno prevfwd;
+       register sopno conc;
+       register int first = 1;         /* is this the first alternative? */
+
+       for (;;) {
+               /* do a bunch of concatenated expressions */
+               conc = HERE();
+               while (MORE() && (c = PEEK()) != '|' && c != stop)
+                       p_ere_exp(p);
+               REQUIRE(HERE() != conc, REG_EMPTY);     /* require nonempty */
+
+               if (!EAT('|'))
+                       break;          /* NOTE BREAK OUT */
+
+               if (first) {
+                       INSERT(OCH_, conc);     /* offset is wrong */
+                       prevfwd = conc;
+                       prevback = conc;
+                       first = 0;
+               }
+               ASTERN(OOR1, prevback);
+               prevback = THERE();
+               AHEAD(prevfwd);                 /* fix previous offset */
+               prevfwd = HERE();
+               EMIT(OOR2, 0);                  /* offset is very wrong */
+       }
+
+       if (!first) {           /* tail-end fixups */
+               AHEAD(prevfwd);
+               ASTERN(O_CH, prevback);
+       }
+
+       assert(!MORE() || SEE(stop));
+}
+
+/*
+ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
+ == static void p_ere_exp(register struct parse *p);
+ */
+static void
+p_ere_exp(p)
+register struct parse *p;
+{
+       register char c;
+       register sopno pos;
+       register int count;
+       register int count2;
+       register sopno subno;
+       int wascaret = 0;
+
+       assert(MORE());         /* caller should have ensured this */
+       c = GETNEXT();
+
+       pos = HERE();
+       switch (c) {
+       case '(':
+               REQUIRE(MORE(), REG_EPAREN);
+               p->g->nsub++;
+               subno = p->g->nsub;
+               if (subno < NPAREN)
+                       p->pbegin[subno] = HERE();
+               EMIT(OLPAREN, subno);
+               if (!SEE(')'))
+                       p_ere(p, ')');
+               if (subno < NPAREN) {
+                       p->pend[subno] = HERE();
+                       assert(p->pend[subno] != 0);
+               }
+               EMIT(ORPAREN, subno);
+               MUSTEAT(')', REG_EPAREN);
+               break;
+#ifndef POSIX_MISTAKE
+       case ')':               /* happens only if no current unmatched ( */
+               /*
+                * You may ask, why the ifndef?  Because I didn't notice
+                * this until slightly too late for 1003.2, and none of the
+                * other 1003.2 regular-expression reviewers noticed it at
+                * all.  So an unmatched ) is legal POSIX, at least until
+                * we can get it fixed.
+                */
+               SETERROR(REG_EPAREN);
+               break;
+#endif
+       case '^':
+               EMIT(OBOL, 0);
+               p->g->iflags |= USEBOL;
+               p->g->nbol++;
+               wascaret = 1;
+               break;
+       case '$':
+               EMIT(OEOL, 0);
+               p->g->iflags |= USEEOL;
+               p->g->neol++;
+               break;
+       case '|':
+               SETERROR(REG_EMPTY);
+               break;
+       case '*':
+       case '+':
+       case '?':
+               SETERROR(REG_BADRPT);
+               break;
+       case '.':
+               if (p->g->cflags&REG_NEWLINE)
+                       nonnewline(p);
+               else
+                       EMIT(OANY, 0);
+               break;
+       case '[':
+               p_bracket(p);
+               break;
+       case '\\':
+               REQUIRE(MORE(), REG_EESCAPE);
+               c = GETNEXT();
+               ordinary(p, c);
+               break;
+       case '{':               /* okay as ordinary except if digit follows */
+               REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT);
+               /* FALLTHROUGH */
+       default:
+               ordinary(p, c);
+               break;
+       }
+
+       if (!MORE())
+               return;
+       c = PEEK();
+       /* we call { a repetition if followed by a digit */
+       if (!( c == '*' || c == '+' || c == '?' ||
+                               (c == '{' && MORE2() && isdigit(PEEK2())) ))
+               return;         /* no repetition, we're done */
+       NEXT();
+
+       REQUIRE(!wascaret, REG_BADRPT);
+       switch (c) {
+       case '*':       /* implemented as +? */
+               /* this case does not require the (y|) trick, noKLUDGE */
+               INSERT(OPLUS_, pos);
+               ASTERN(O_PLUS, pos);
+               INSERT(OQUEST_, pos);
+               ASTERN(O_QUEST, pos);
+               break;
+       case '+':
+               INSERT(OPLUS_, pos);
+               ASTERN(O_PLUS, pos);
+               break;
+       case '?':
+               /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+               INSERT(OCH_, pos);              /* offset slightly wrong */
+               ASTERN(OOR1, pos);              /* this one's right */
+               AHEAD(pos);                     /* fix the OCH_ */
+               EMIT(OOR2, 0);                  /* offset very wrong... */
+               AHEAD(THERE());                 /* ...so fix it */
+               ASTERN(O_CH, THERETHERE());
+               break;
+       case '{':
+               count = p_count(p);
+               if (EAT(',')) {
+                       if (isdigit(PEEK())) {
+                               count2 = p_count(p);
+                               REQUIRE(count <= count2, REG_BADBR);
+                       } else          /* single number with comma */
+                               count2 = INFINITY;
+               } else          /* just a single number */
+                       count2 = count;
+               repeat(p, pos, count, count2);
+               if (!EAT('}')) {        /* error heuristics */
+                       while (MORE() && PEEK() != '}')
+                               NEXT();
+                       REQUIRE(MORE(), REG_EBRACE);
+                       SETERROR(REG_BADBR);
+               }
+               break;
+       }
+
+       if (!MORE())
+               return;
+       c = PEEK();
+       if (!( c == '*' || c == '+' || c == '?' ||
+                               (c == '{' && MORE2() && isdigit(PEEK2())) ) )
+               return;
+       SETERROR(REG_BADRPT);
+}
+
+/*
+ - p_str - string (no metacharacters) "parser"
+ == static void p_str(register struct parse *p);
+ */
+static void
+p_str(p)
+register struct parse *p;
+{
+       REQUIRE(MORE(), REG_EMPTY);
+       while (MORE())
+               ordinary(p, GETNEXT());
+}
+
+/*
+ - p_bre - BRE parser top level, anchoring and concatenation
+ == static void p_bre(register struct parse *p, register int end1, \
+ ==    register int end2);
+ * Giving end1 as OUT essentially eliminates the end1/end2 check.
+ *
+ * This implementation is a bit of a kludge, in that a trailing $ is first
+ * taken as an ordinary character and then revised to be an anchor.  The
+ * only undesirable side effect is that '$' gets included as a character
+ * category in such cases.  This is fairly harmless; not worth fixing.
+ * The amount of lookahead needed to avoid this kludge is excessive.
+ */
+static void
+p_bre(p, end1, end2)
+register struct parse *p;
+register int end1;             /* first terminating character */
+register int end2;             /* second terminating character */
+{
+       register sopno start = HERE();
+       register int first = 1;                 /* first subexpression? */
+       register int wasdollar = 0;
+
+       if (EAT('^')) {
+               EMIT(OBOL, 0);
+               p->g->iflags |= USEBOL;
+               p->g->nbol++;
+       }
+       while (MORE() && !SEETWO(end1, end2)) {
+               wasdollar = p_simp_re(p, first);
+               first = 0;
+       }
+       if (wasdollar) {        /* oops, that was a trailing anchor */
+               DROP(1);
+               EMIT(OEOL, 0);
+               p->g->iflags |= USEEOL;
+               p->g->neol++;
+       }
+
+       REQUIRE(HERE() != start, REG_EMPTY);    /* require nonempty */
+}
+
+/*
+ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
+ == static int p_simp_re(register struct parse *p, int starordinary);
+ */
+static int                     /* was the simple RE an unbackslashed $? */
+p_simp_re(p, starordinary)
+register struct parse *p;
+int starordinary;              /* is a leading * an ordinary character? */
+{
+       register int c;
+       register int count;
+       register int count2;
+       register sopno pos;
+       register int i;
+       register sopno subno;
+#      define  BACKSL  (1<<CHAR_BIT)
+
+       pos = HERE();           /* repetion op, if any, covers from here */
+
+       assert(MORE());         /* caller should have ensured this */
+       c = GETNEXT();
+       if (c == '\\') {
+               REQUIRE(MORE(), REG_EESCAPE);
+               c = BACKSL | (unsigned char)GETNEXT();
+       }
+       switch (c) {
+       case '.':
+               if (p->g->cflags&REG_NEWLINE)
+                       nonnewline(p);
+               else
+                       EMIT(OANY, 0);
+               break;
+       case '[':
+               p_bracket(p);
+               break;
+       case BACKSL|'{':
+               SETERROR(REG_BADRPT);
+               break;
+       case BACKSL|'(':
+               p->g->nsub++;
+               subno = p->g->nsub;
+               if (subno < NPAREN)
+                       p->pbegin[subno] = HERE();
+               EMIT(OLPAREN, subno);
+               /* the MORE here is an error heuristic */
+               if (MORE() && !SEETWO('\\', ')'))
+                       p_bre(p, '\\', ')');
+               if (subno < NPAREN) {
+                       p->pend[subno] = HERE();
+                       assert(p->pend[subno] != 0);
+               }
+               EMIT(ORPAREN, subno);
+               REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+               break;
+       case BACKSL|')':        /* should not get here -- must be user */
+       case BACKSL|'}':
+               SETERROR(REG_EPAREN);
+               break;
+       case BACKSL|'1':
+       case BACKSL|'2':
+       case BACKSL|'3':
+       case BACKSL|'4':
+       case BACKSL|'5':
+       case BACKSL|'6':
+       case BACKSL|'7':
+       case BACKSL|'8':
+       case BACKSL|'9':
+               i = (c&~BACKSL) - '0';
+               assert(i < NPAREN);
+               if (p->pend[i] != 0) {
+                       assert(i <= p->g->nsub);
+                       EMIT(OBACK_, i);
+                       assert(p->pbegin[i] != 0);
+                       assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
+                       assert(OP(p->strip[p->pend[i]]) == ORPAREN);
+                       (void) dupl(p, p->pbegin[i]+1, p->pend[i]);
+                       EMIT(O_BACK, i);
+               } else
+                       SETERROR(REG_ESUBREG);
+               p->g->backrefs = 1;
+               break;
+       case '*':
+               REQUIRE(starordinary, REG_BADRPT);
+               /* FALLTHROUGH */
+       default:
+               ordinary(p, (char)c);   /* takes off BACKSL, if any */
+               break;
+       }
+
+       if (EAT('*')) {         /* implemented as +? */
+               /* this case does not require the (y|) trick, noKLUDGE */
+               INSERT(OPLUS_, pos);
+               ASTERN(O_PLUS, pos);
+               INSERT(OQUEST_, pos);
+               ASTERN(O_QUEST, pos);
+       } else if (EATTWO('\\', '{')) {
+               count = p_count(p);
+               if (EAT(',')) {
+                       if (MORE() && isdigit(PEEK())) {
+                               count2 = p_count(p);
+                               REQUIRE(count <= count2, REG_BADBR);
+                       } else          /* single number with comma */
+                               count2 = INFINITY;
+               } else          /* just a single number */
+                       count2 = count;
+               repeat(p, pos, count, count2);
+               if (!EATTWO('\\', '}')) {       /* error heuristics */
+                       while (MORE() && !SEETWO('\\', '}'))
+                               NEXT();
+                       REQUIRE(MORE(), REG_EBRACE);
+                       SETERROR(REG_BADBR);
+               }
+       } else if (c == (unsigned char)'$')     /* $ (but not \$) ends it */
+               return(1);
+
+       return(0);
+}
+
+/*
+ - p_count - parse a repetition count
+ == static int p_count(register struct parse *p);
+ */
+static int                     /* the value */
+p_count(p)
+register struct parse *p;
+{
+       register int count = 0;
+       register int ndigits = 0;
+
+       while (MORE() && isdigit(PEEK()) && count <= DUPMAX) {
+               count = count*10 + (GETNEXT() - '0');
+               ndigits++;
+       }
+
+       REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+       return(count);
+}
+
+/*
+ - p_bracket - parse a bracketed character list
+ == static void p_bracket(register struct parse *p);
+ *
+ * Note a significant property of this code:  if the allocset() did SETERROR,
+ * no set operations are done.
+ */
+static void
+p_bracket(p)
+register struct parse *p;
+{
+       register cset *cs = allocset(p);
+       register int invert = 0;
+
+       /* Dept of Truly Sickening Special-Case Kludges */
+       if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
+               EMIT(OBOW, 0);
+               NEXTn(6);
+               return;
+       }
+       if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {
+               EMIT(OEOW, 0);
+               NEXTn(6);
+               return;
+       }
+
+       if (EAT('^'))
+               invert++;       /* make note to invert set at end */
+       if (EAT(']'))
+               CHadd(cs, ']');
+       else if (EAT('-'))
+               CHadd(cs, '-');
+       while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
+               p_b_term(p, cs);
+       if (EAT('-'))
+               CHadd(cs, '-');
+       MUSTEAT(']', REG_EBRACK);
+
+       if (p->error != 0)      /* don't mess things up further */
+               return;
+
+       if (p->g->cflags&REG_ICASE) {
+               register int i;
+               register int ci;
+
+               for (i = p->g->csetsize - 1; i >= 0; i--)
+                       if (CHIN(cs, i) && isalpha(i)) {
+                               ci = othercase(i);
+                               if (ci != i)
+                                       CHadd(cs, ci);
+                       }
+               if (cs->multis != NULL)
+                       mccase(p, cs);
+       }
+       if (invert) {
+               register int i;
+
+               for (i = p->g->csetsize - 1; i >= 0; i--)
+                       if (CHIN(cs, i))
+                               CHsub(cs, i);
+                       else
+                               CHadd(cs, i);
+               if (p->g->cflags&REG_NEWLINE)
+                       CHsub(cs, '\n');
+               if (cs->multis != NULL)
+                       mcinvert(p, cs);
+       }
+
+       assert(cs->multis == NULL);             /* xxx */
+
+       if (nch(p, cs) == 1) {          /* optimize singleton sets */
+               ordinary(p, firstch(p, cs));
+               freeset(p, cs);
+       } else
+               EMIT(OANYOF, freezeset(p, cs));
+}
+
+/*
+ - p_b_term - parse one term of a bracketed character list
+ == static void p_b_term(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_term(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register char c;
+       register char start, finish;
+       register int i;
+
+       /* classify what we've got */
+       switch ((MORE()) ? PEEK() : '\0') {
+       case '[':
+               c = (MORE2()) ? PEEK2() : '\0';
+               break;
+       case '-':
+               SETERROR(REG_ERANGE);
+               return;                 /* NOTE RETURN */
+               break;
+       default:
+               c = '\0';
+               break;
+       }
+
+       switch (c) {
+       case ':':               /* character class */
+               NEXT2();
+               REQUIRE(MORE(), REG_EBRACK);
+               c = PEEK();
+               REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+               p_b_cclass(p, cs);
+               REQUIRE(MORE(), REG_EBRACK);
+               REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+               break;
+       case '=':               /* equivalence class */
+               NEXT2();
+               REQUIRE(MORE(), REG_EBRACK);
+               c = PEEK();
+               REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+               p_b_eclass(p, cs);
+               REQUIRE(MORE(), REG_EBRACK);
+               REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+               break;
+       default:                /* symbol, ordinary character, or range */
+/* xxx revision needed for multichar stuff */
+               start = p_b_symbol(p);
+               if (SEE('-') && MORE2() && PEEK2() != ']') {
+                       /* range */
+                       NEXT();
+                       if (EAT('-'))
+                               finish = '-';
+                       else
+                               finish = p_b_symbol(p);
+               } else
+                       finish = start;
+/* xxx what about signed chars here... */
+               REQUIRE(start <= finish, REG_ERANGE);
+               for (i = start; i <= finish; i++)
+                       CHadd(cs, i);
+               break;
+       }
+}
+
+/*
+ - p_b_cclass - parse a character-class name and deal with it
+ == static void p_b_cclass(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_cclass(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register char *sp = p->next;
+       register struct cclass *cp;
+       register size_t len;
+       register char *u;
+       register char c;
+
+       while (MORE() && isalpha(PEEK()))
+               NEXT();
+       len = p->next - sp;
+       for (cp = cclasses; cp->name != NULL; cp++)
+               if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+                       break;
+       if (cp->name == NULL) {
+               /* oops, didn't find it */
+               SETERROR(REG_ECTYPE);
+               return;
+       }
+
+       u = cp->chars;
+       while ((c = *u++) != '\0')
+               CHadd(cs, c);
+       for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
+               MCadd(p, cs, u);
+}
+
+/*
+ - p_b_eclass - parse an equivalence-class name and deal with it
+ == static void p_b_eclass(register struct parse *p, register cset *cs);
+ *
+ * This implementation is incomplete. xxx
+ */
+static void
+p_b_eclass(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register char c;
+
+       c = p_b_coll_elem(p, '=');
+       CHadd(cs, c);
+}
+
+/*
+ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
+ == static char p_b_symbol(register struct parse *p);
+ */
+static char                    /* value of symbol */
+p_b_symbol(p)
+register struct parse *p;
+{
+       register char value;
+
+       REQUIRE(MORE(), REG_EBRACK);
+       if (!EATTWO('[', '.'))
+               return(GETNEXT());
+
+       /* collating symbol */
+       value = p_b_coll_elem(p, '.');
+       REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+       return(value);
+}
+
+/*
+ - p_b_coll_elem - parse a collating-element name and look it up
+ == static char p_b_coll_elem(register struct parse *p, int endc);
+ */
+static char                    /* value of collating element */
+p_b_coll_elem(p, endc)
+register struct parse *p;
+int endc;                      /* name ended by endc,']' */
+{
+       register char *sp = p->next;
+       register struct cname *cp;
+       register int len;
+
+       while (MORE() && !SEETWO(endc, ']'))
+               NEXT();
+       if (!MORE()) {
+               SETERROR(REG_EBRACK);
+               return(0);
+       }
+       len = p->next - sp;
+       for (cp = cnames; cp->name != NULL; cp++)
+               if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+                       return(cp->code);       /* known name */
+       if (len == 1)
+               return(*sp);    /* single character */
+       SETERROR(REG_ECOLLATE);                 /* neither */
+       return(0);
+}
+
+/*
+ - othercase - return the case counterpart of an alphabetic
+ == static char othercase(int ch);
+ */
+static char                    /* if no counterpart, return ch */
+othercase(ch)
+int ch;
+{
+       assert(isalpha(ch));
+       if (isupper(ch))
+               return(tolower(ch));
+       else if (islower(ch))
+               return(toupper(ch));
+       else                    /* peculiar, but could happen */
+               return(ch);
+}
+
+/*
+ - bothcases - emit a dualcase version of a two-case character
+ == static void bothcases(register struct parse *p, int ch);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+bothcases(p, ch)
+register struct parse *p;
+int ch;
+{
+       register char *oldnext = p->next;
+       register char *oldend = p->end;
+       char bracket[3];
+
+       assert(othercase(ch) != ch);    /* p_bracket() would recurse */
+       p->next = bracket;
+       p->end = bracket+2;
+       bracket[0] = ch;
+       bracket[1] = ']';
+       bracket[2] = '\0';
+       p_bracket(p);
+       assert(p->next == bracket+2);
+       p->next = oldnext;
+       p->end = oldend;
+}
+
+/*
+ - ordinary - emit an ordinary character
+ == static void ordinary(register struct parse *p, register int ch);
+ */
+static void
+ordinary(p, ch)
+register struct parse *p;
+register int ch;
+{
+       register cat_t *cap = p->g->categories;
+
+       if ((p->g->cflags&REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+               bothcases(p, ch);
+       else {
+               EMIT(OCHAR, (unsigned char)ch);
+               if (cap[ch] == 0)
+                       cap[ch] = p->g->ncategories++;
+       }
+}
+
+/*
+ - nonnewline - emit REG_NEWLINE version of OANY
+ == static void nonnewline(register struct parse *p);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+nonnewline(p)
+register struct parse *p;
+{
+       register char *oldnext = p->next;
+       register char *oldend = p->end;
+       char bracket[4];
+
+       p->next = bracket;
+       p->end = bracket+3;
+       bracket[0] = '^';
+       bracket[1] = '\n';
+       bracket[2] = ']';
+       bracket[3] = '\0';
+       p_bracket(p);
+       assert(p->next == bracket+3);
+       p->next = oldnext;
+       p->end = oldend;
+}
+
+/*
+ - repeat - generate code for a bounded repetition, recursively if needed
+ == static void repeat(register struct parse *p, sopno start, int from, int to);
+ */
+static void
+repeat(p, start, from, to)
+register struct parse *p;
+sopno start;                   /* operand from here to end of strip */
+int from;                      /* repeated from this number */
+int to;                                /* to this number of times (maybe INFINITY) */
+{
+       register sopno finish = HERE();
+#      define  N       2
+#      define  INF     3
+#      define  REP(f, t)       ((f)*8 + (t))
+#      define  MAP(n)  (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
+       register sopno copy;
+
+       if (p->error != 0)      /* head off possible runaway recursion */
+               return;
+
+       assert(from <= to);
+
+       switch (REP(MAP(from), MAP(to))) {
+       case REP(0, 0):                 /* must be user doing this */
+               DROP(finish-start);     /* drop the operand */
+               break;
+       case REP(0, 1):                 /* as x{1,1}? */
+       case REP(0, N):                 /* as x{1,n}? */
+       case REP(0, INF):               /* as x{1,}? */
+               /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+               INSERT(OCH_, start);            /* offset is wrong... */
+               repeat(p, start+1, 1, to);
+               ASTERN(OOR1, start);
+               AHEAD(start);                   /* ... fix it */
+               EMIT(OOR2, 0);
+               AHEAD(THERE());
+               ASTERN(O_CH, THERETHERE());
+               break;
+       case REP(1, 1):                 /* trivial case */
+               /* done */
+               break;
+       case REP(1, N):                 /* as x?x{1,n-1} */
+               /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+               INSERT(OCH_, start);
+               ASTERN(OOR1, start);
+               AHEAD(start);
+               EMIT(OOR2, 0);                  /* offset very wrong... */
+               AHEAD(THERE());                 /* ...so fix it */
+               ASTERN(O_CH, THERETHERE());
+               copy = dupl(p, start+1, finish+1);
+               assert(copy == finish+4);
+               repeat(p, copy, 1, to-1);
+               break;
+       case REP(1, INF):               /* as x+ */
+               INSERT(OPLUS_, start);
+               ASTERN(O_PLUS, start);
+               break;
+       case REP(N, N):                 /* as xx{m-1,n-1} */
+               copy = dupl(p, start, finish);
+               repeat(p, copy, from-1, to-1);
+               break;
+       case REP(N, INF):               /* as xx{n-1,INF} */
+               copy = dupl(p, start, finish);
+               repeat(p, copy, from-1, to);
+               break;
+       default:                        /* "can't happen" */
+               SETERROR(REG_ASSERT);   /* just in case */
+               break;
+       }
+}
+
+/*
+ - seterr - set an error condition
+ == static int seterr(register struct parse *p, int e);
+ */
+static int                     /* useless but makes type checking happy */
+seterr(p, e)
+register struct parse *p;
+int e;
+{
+       if (p->error == 0)      /* keep earliest error condition */
+               p->error = e;
+       p->next = nuls;         /* try to bring things to a halt */
+       p->end = nuls;
+       return(0);              /* make the return value well-defined */
+}
+
+/*
+ - allocset - allocate a set of characters for []
+ == static cset *allocset(register struct parse *p);
+ */
+static cset *
+allocset(p)
+register struct parse *p;
+{
+       register int no = p->g->ncsets++;
+       register size_t nc;
+       register size_t nbytes;
+       register cset *cs;
+       register size_t css = (size_t)p->g->csetsize;
+       register int i;
+
+       if (no >= p->ncsalloc) {        /* need another column of space */
+               p->ncsalloc += CHAR_BIT;
+               nc = p->ncsalloc;
+               assert(nc % CHAR_BIT == 0);
+               nbytes = nc / CHAR_BIT * css;
+               if (p->g->sets == NULL)
+                       p->g->sets = (cset *)malloc(nc * sizeof(cset));
+               else
+                       p->g->sets = (cset *)realloc((char *)p->g->sets,
+                                                       nc * sizeof(cset));
+               if (p->g->setbits == NULL)
+                       p->g->setbits = (uch *)malloc(nbytes);
+               else {
+                       p->g->setbits = (uch *)realloc((char *)p->g->setbits,
+                                                               nbytes);
+                       /* xxx this isn't right if setbits is now NULL */
+                       for (i = 0; i < no; i++)
+                               p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
+               }
+               if (p->g->sets != NULL && p->g->setbits != NULL)
+                       (void) memset((char *)p->g->setbits + (nbytes - css),
+                                                               0, css);
+               else {
+                       no = 0;
+                       SETERROR(REG_ESPACE);
+                       /* caller's responsibility not to do set ops */
+               }
+       }
+
+       assert(p->g->sets != NULL);     /* xxx */
+       cs = &p->g->sets[no];
+       cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);
+       cs->mask = 1 << ((no) % CHAR_BIT);
+       cs->hash = 0;
+       cs->smultis = 0;
+       cs->multis = NULL;
+
+       return(cs);
+}
+
+/*
+ - freeset - free a now-unused set
+ == static void freeset(register struct parse *p, register cset *cs);
+ */
+static void
+freeset(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register int i;
+       register cset *top = &p->g->sets[p->g->ncsets];
+       register size_t css = (size_t)p->g->csetsize;
+
+       for (i = 0; i < css; i++)
+               CHsub(cs, i);
+       if (cs == top-1)        /* recover only the easy case */
+               p->g->ncsets--;
+}
+
+/*
+ - freezeset - final processing on a set of characters
+ == static int freezeset(register struct parse *p, register cset *cs);
+ *
+ * The main task here is merging identical sets.  This is usually a waste
+ * of time (although the hash code minimizes the overhead), but can win
+ * big if REG_ICASE is being used.  REG_ICASE, by the way, is why the hash
+ * is done using addition rather than xor -- all ASCII [aA] sets xor to
+ * the same value!
+ */
+static int                     /* set number */
+freezeset(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register uch h = cs->hash;
+       register int i;
+       register cset *top = &p->g->sets[p->g->ncsets];
+       register cset *cs2;
+       register size_t css = (size_t)p->g->csetsize;
+
+       /* look for an earlier one which is the same */
+       for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
+               if (cs2->hash == h && cs2 != cs) {
+                       /* maybe */
+                       for (i = 0; i < css; i++)
+                               if (!!CHIN(cs2, i) != !!CHIN(cs, i))
+                                       break;          /* no */
+                       if (i == css)
+                               break;                  /* yes */
+               }
+
+       if (cs2 < top) {        /* found one */
+               freeset(p, cs);
+               cs = cs2;
+       }
+
+       return((int)(cs - p->g->sets));
+}
+
+/*
+ - firstch - return first character in a set (which must have at least one)
+ == static int firstch(register struct parse *p, register cset *cs);
+ */
+static int                     /* character; there is no "none" value */
+firstch(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register int i;
+       register size_t css = (size_t)p->g->csetsize;
+
+       for (i = 0; i < css; i++)
+               if (CHIN(cs, i))
+                       return((char)i);
+       assert(never);
+       return(0);              /* arbitrary */
+}
+
+/*
+ - nch - number of characters in a set
+ == static int nch(register struct parse *p, register cset *cs);
+ */
+static int
+nch(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       register int i;
+       register size_t css = (size_t)p->g->csetsize;
+       register int n = 0;
+
+       for (i = 0; i < css; i++)
+               if (CHIN(cs, i))
+                       n++;
+       return(n);
+}
+
+/*
+ - mcadd - add a collating element to a cset
+ == static void mcadd(register struct parse *p, register cset *cs, \
+ ==    register char *cp);
+ */
+static void
+mcadd(p, cs, cp)
+register struct parse *p;
+register cset *cs;
+register char *cp;
+{
+       register size_t oldend = cs->smultis;
+
+       cs->smultis += strlen(cp) + 1;
+       if (cs->multis == NULL)
+               cs->multis = malloc(cs->smultis);
+       else
+               cs->multis = realloc(cs->multis, cs->smultis);
+       if (cs->multis == NULL) {
+               SETERROR(REG_ESPACE);
+               return;
+       }
+
+       (void) strcpy(cs->multis + oldend - 1, cp);
+       cs->multis[cs->smultis - 1] = '\0';
+}
+
+/*
+ - mcsub - subtract a collating element from a cset
+ == static void mcsub(register cset *cs, register char *cp);
+ */
+static void
+mcsub(cs, cp)
+register cset *cs;
+register char *cp;
+{
+       register char *fp = mcfind(cs, cp);
+       register size_t len = strlen(fp);
+
+       assert(fp != NULL);
+       (void) memmove(fp, fp + len + 1,
+                               cs->smultis - (fp + len + 1 - cs->multis));
+       cs->smultis -= len;
+
+       if (cs->smultis == 0) {
+               free(cs->multis);
+               cs->multis = NULL;
+               return;
+       }
+
+       cs->multis = realloc(cs->multis, cs->smultis);
+       assert(cs->multis != NULL);
+}
+
+/*
+ - mcin - is a collating element in a cset?
+ == static int mcin(register cset *cs, register char *cp);
+ */
+static int
+mcin(cs, cp)
+register cset *cs;
+register char *cp;
+{
+       return(mcfind(cs, cp) != NULL);
+}
+
+/*
+ - mcfind - find a collating element in a cset
+ == static char *mcfind(register cset *cs, register char *cp);
+ */
+static char *
+mcfind(cs, cp)
+register cset *cs;
+register char *cp;
+{
+       register char *p;
+
+       if (cs->multis == NULL)
+               return(NULL);
+       for (p = cs->multis; *p != '\0'; p += strlen(p) + 1)
+               if (strcmp(cp, p) == 0)
+                       return(p);
+       return(NULL);
+}
+
+/*
+ - mcinvert - invert the list of collating elements in a cset
+ == static void mcinvert(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities.  Implementation
+ * is deferred.
+ */
+static void
+mcinvert(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       assert(cs->multis == NULL);     /* xxx */
+}
+
+/*
+ - mccase - add case counterparts of the list of collating elements in a cset
+ == static void mccase(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities.  Implementation
+ * is deferred.
+ */
+static void
+mccase(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+       assert(cs->multis == NULL);     /* xxx */
+}
+
+/*
+ - isinsets - is this character in any sets?
+ == static int isinsets(register struct re_guts *g, int c);
+ */
+static int                     /* predicate */
+isinsets(g, c)
+register struct re_guts *g;
+int c;
+{
+       register uch *col;
+       register int i;
+       register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+       register unsigned uc = (unsigned char)c;
+
+       for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+               if (col[uc] != 0)
+                       return(1);
+       return(0);
+}
+
+/*
+ - samesets - are these two characters in exactly the same sets?
+ == static int samesets(register struct re_guts *g, int c1, int c2);
+ */
+static int                     /* predicate */
+samesets(g, c1, c2)
+register struct re_guts *g;
+int c1;
+int c2;
+{
+       register uch *col;
+       register int i;
+       register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+       register unsigned uc1 = (unsigned char)c1;
+       register unsigned uc2 = (unsigned char)c2;
+
+       for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+               if (col[uc1] != col[uc2])
+                       return(0);
+       return(1);
+}
+
+/*
+ - categorize - sort out character categories
+ == static void categorize(struct parse *p, register struct re_guts *g);
+ */
+static void
+categorize(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+       register cat_t *cats = g->categories;
+       register int c;
+       register int c2;
+       register cat_t cat;
+
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+               if (cats[c] == 0 && isinsets(g, c)) {
+                       cat = g->ncategories++;
+                       cats[c] = cat;
+                       for (c2 = c+1; c2 <= CHAR_MAX; c2++)
+                               if (cats[c2] == 0 && samesets(g, c, c2))
+                                       cats[c2] = cat;
+               }
+}
+
+/*
+ - dupl - emit a duplicate of a bunch of sops
+ == static sopno dupl(register struct parse *p, sopno start, sopno finish);
+ */
+static sopno                   /* start of duplicate */
+dupl(p, start, finish)
+register struct parse *p;
+sopno start;                   /* from here */
+sopno finish;                  /* to this less one */
+{
+       register sopno ret = HERE();
+       register sopno len = finish - start;
+
+       assert(finish >= start);
+       if (len == 0)
+               return(ret);
+       enlarge(p, p->ssize + len);     /* this many unexpected additions */
+       assert(p->ssize >= p->slen + len);
+       (void) memcpy((char *)(p->strip + p->slen),
+               (char *)(p->strip + start), (size_t)len*sizeof(sop));
+       p->slen += len;
+       return(ret);
+}
+
+/*
+ - doemit - emit a strip operator
+ == static void doemit(register struct parse *p, sop op, size_t opnd);
+ *
+ * It might seem better to implement this as a macro with a function as
+ * hard-case backup, but it's just too big and messy unless there are
+ * some changes to the data structures.  Maybe later.
+ */
+static void
+doemit(p, op, opnd)
+register struct parse *p;
+sop op;
+size_t opnd;
+{
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       /* deal with oversize operands ("can't happen", more or less) */
+       assert(opnd < 1<<OPSHIFT);
+
+       /* deal with undersized strip */
+       if (p->slen >= p->ssize)
+               enlarge(p, (p->ssize+1) / 2 * 3);       /* +50% */
+       assert(p->slen < p->ssize);
+
+       /* finally, it's all reduced to the easy case */
+       p->strip[p->slen++] = SOP(op, opnd);
+}
+
+/*
+ - doinsert - insert a sop into the strip
+ == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+ */
+static void
+doinsert(p, op, opnd, pos)
+register struct parse *p;
+sop op;
+size_t opnd;
+sopno pos;
+{
+       register sopno sn;
+       register sop s;
+       register int i;
+
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       sn = HERE();
+       EMIT(op, opnd);         /* do checks, ensure space */
+       assert(HERE() == sn+1);
+       s = p->strip[sn];
+
+       /* adjust paren pointers */
+       assert(pos > 0);
+       for (i = 1; i < NPAREN; i++) {
+               if (p->pbegin[i] >= pos) {
+                       p->pbegin[i]++;
+               }
+               if (p->pend[i] >= pos) {
+                       p->pend[i]++;
+               }
+       }
+
+       memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
+                                               (HERE()-pos-1)*sizeof(sop));
+       p->strip[pos] = s;
+}
+
+/*
+ - dofwd - complete a forward reference
+ == static void dofwd(register struct parse *p, sopno pos, sop value);
+ */
+static void
+dofwd(p, pos, value)
+register struct parse *p;
+register sopno pos;
+sop value;
+{
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       assert(value < 1<<OPSHIFT);
+       p->strip[pos] = OP(p->strip[pos]) | value;
+}
+
+/*
+ - enlarge - enlarge the strip
+ == static void enlarge(register struct parse *p, sopno size);
+ */
+static void
+enlarge(p, size)
+register struct parse *p;
+register sopno size;
+{
+       register sop *sp;
+
+       if (p->ssize >= size)
+               return;
+
+       sp = (sop *)realloc(p->strip, size*sizeof(sop));
+       if (sp == NULL) {
+               SETERROR(REG_ESPACE);
+               return;
+       }
+       p->strip = sp;
+       p->ssize = size;
+}
+
+/*
+ - stripsnug - compact the strip
+ == static void stripsnug(register struct parse *p, register struct re_guts *g);
+ */
+static void
+stripsnug(p, g)
+register struct parse *p;
+register struct re_guts *g;
+{
+       g->nstates = p->slen;
+       g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
+       if (g->strip == NULL) {
+               SETERROR(REG_ESPACE);
+               g->strip = p->strip;
+       }
+}
+
+/*
+ - findmust - fill in must and mlen with longest mandatory literal string
+ == static void findmust(register struct parse *p, register struct re_guts *g);
+ *
+ * This algorithm could do fancy things like analyzing the operands of |
+ * for common subsequences.  Someday.  This code is simple and finds most
+ * of the interesting cases.
+ *
+ * Note that must and mlen got initialized during setup.
+ */
+static void
+findmust(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+       register sop *scan;
+       sop *start;
+       register sop *newstart;
+       register sopno newlen;
+       register sop s;
+       register char *cp;
+       register sopno i;
+
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       /* find the longest OCHAR sequence in strip */
+       newlen = 0;
+       scan = g->strip + 1;
+       do {
+               s = *scan++;
+               switch (OP(s)) {
+               case OCHAR:             /* sequence member */
+                       if (newlen == 0)                /* new sequence */
+                               newstart = scan - 1;
+                       newlen++;
+                       break;
+               case OPLUS_:            /* things that don't break one */
+               case OLPAREN:
+               case ORPAREN:
+                       break;
+               case OQUEST_:           /* things that must be skipped */
+               case OCH_:
+                       scan--;
+                       do {
+                               scan += OPND(s);
+                               s = *scan;
+                               /* assert() interferes w debug printouts */
+                               if (OP(s) != O_QUEST && OP(s) != O_CH &&
+                                                       OP(s) != OOR2) {
+                                       g->iflags |= BAD;
+                                       return;
+                               }
+                       } while (OP(s) != O_QUEST && OP(s) != O_CH);
+                       /* fallthrough */
+               default:                /* things that break a sequence */
+                       if (newlen > g->mlen) {         /* ends one */
+                               start = newstart;
+                               g->mlen = newlen;
+                       }
+                       newlen = 0;
+                       break;
+               }
+       } while (OP(s) != OEND);
+
+       if (g->mlen == 0)               /* there isn't one */
+               return;
+
+       /* turn it into a character string */
+       g->must = malloc((size_t)g->mlen + 1);
+       if (g->must == NULL) {          /* argh; just forget it */
+               g->mlen = 0;
+               return;
+       }
+       cp = g->must;
+       scan = start;
+       for (i = g->mlen; i > 0; i--) {
+               while (OP(s = *scan++) != OCHAR)
+                       continue;
+               assert(cp < g->must + g->mlen);
+               *cp++ = (char)OPND(s);
+       }
+       assert(cp == g->must + g->mlen);
+       *cp++ = '\0';           /* just on general principles */
+}
+
+/*
+ - pluscount - count + nesting
+ == static sopno pluscount(register struct parse *p, register struct re_guts *g);
+ */
+static sopno                   /* nesting depth */
+pluscount(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+       register sop *scan;
+       register sop s;
+       register sopno plusnest = 0;
+       register sopno maxnest = 0;
+
+       if (p->error != 0)
+               return(0);      /* there may not be an OEND */
+
+       scan = g->strip + 1;
+       do {
+               s = *scan++;
+               switch (OP(s)) {
+               case OPLUS_:
+                       plusnest++;
+                       break;
+               case O_PLUS:
+                       if (plusnest > maxnest)
+                               maxnest = plusnest;
+                       plusnest--;
+                       break;
+               }
+       } while (OP(s) != OEND);
+       if (plusnest != 0)
+               g->iflags |= BAD;
+       return(maxnest);
+}
diff --git a/vcnet/regex/regcomp.ih b/vcnet/regex/regcomp.ih
new file mode 100644 (file)
index 0000000..0776e71
--- /dev/null
@@ -0,0 +1,51 @@
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regcomp.c === */
+static void p_ere(register struct parse *p, int stop);
+static void p_ere_exp(register struct parse *p);
+static void p_str(register struct parse *p);
+static void p_bre(register struct parse *p, register int end1, register int end2);
+static int p_simp_re(register struct parse *p, int starordinary);
+static int p_count(register struct parse *p);
+static void p_bracket(register struct parse *p);
+static void p_b_term(register struct parse *p, register cset *cs);
+static void p_b_cclass(register struct parse *p, register cset *cs);
+static void p_b_eclass(register struct parse *p, register cset *cs);
+static char p_b_symbol(register struct parse *p);
+static char p_b_coll_elem(register struct parse *p, int endc);
+static char othercase(int ch);
+static void bothcases(register struct parse *p, int ch);
+static void ordinary(register struct parse *p, register int ch);
+static void nonnewline(register struct parse *p);
+static void repeat(register struct parse *p, sopno start, int from, int to);
+static int seterr(register struct parse *p, int e);
+static cset *allocset(register struct parse *p);
+static void freeset(register struct parse *p, register cset *cs);
+static int freezeset(register struct parse *p, register cset *cs);
+static int firstch(register struct parse *p, register cset *cs);
+static int nch(register struct parse *p, register cset *cs);
+static void mcadd(register struct parse *p, register cset *cs, register char *cp);
+static void mcsub(register cset *cs, register char *cp);
+static int mcin(register cset *cs, register char *cp);
+static char *mcfind(register cset *cs, register char *cp);
+static void mcinvert(register struct parse *p, register cset *cs);
+static void mccase(register struct parse *p, register cset *cs);
+static int isinsets(register struct re_guts *g, int c);
+static int samesets(register struct re_guts *g, int c1, int c2);
+static void categorize(struct parse *p, register struct re_guts *g);
+static sopno dupl(register struct parse *p, sopno start, sopno finish);
+static void doemit(register struct parse *p, sop op, size_t opnd);
+static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+static void dofwd(register struct parse *p, sopno pos, sop value);
+static void enlarge(register struct parse *p, sopno size);
+static void stripsnug(register struct parse *p, register struct re_guts *g);
+static void findmust(register struct parse *p, register struct re_guts *g);
+static sopno pluscount(register struct parse *p, register struct re_guts *g);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/vcnet/regex/regerror.c b/vcnet/regex/regerror.c
new file mode 100644 (file)
index 0000000..9ddd25c
--- /dev/null
@@ -0,0 +1,126 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regerror.ih"
+
+/*
+ = #define     REG_OKAY         0
+ = #define     REG_NOMATCH      1
+ = #define     REG_BADPAT       2
+ = #define     REG_ECOLLATE     3
+ = #define     REG_ECTYPE       4
+ = #define     REG_EESCAPE      5
+ = #define     REG_ESUBREG      6
+ = #define     REG_EBRACK       7
+ = #define     REG_EPAREN       8
+ = #define     REG_EBRACE       9
+ = #define     REG_BADBR       10
+ = #define     REG_ERANGE      11
+ = #define     REG_ESPACE      12
+ = #define     REG_BADRPT      13
+ = #define     REG_EMPTY       14
+ = #define     REG_ASSERT      15
+ = #define     REG_INVARG      16
+ = #define     REG_ATOI        255     // convert name to number (!)
+ = #define     REG_ITOA        0400    // convert number to name (!)
+ */
+static struct rerr {
+       int code;
+       char *name;
+       char *explain;
+} rerrs[] = {
+       REG_OKAY,       "REG_OKAY",     "no errors detected",
+       REG_NOMATCH,    "REG_NOMATCH",  "regexec() failed to match",
+       REG_BADPAT,     "REG_BADPAT",   "invalid regular expression",
+       REG_ECOLLATE,   "REG_ECOLLATE", "invalid collating element",
+       REG_ECTYPE,     "REG_ECTYPE",   "invalid character class",
+       REG_EESCAPE,    "REG_EESCAPE",  "trailing backslash (\\)",
+       REG_ESUBREG,    "REG_ESUBREG",  "invalid backreference number",
+       REG_EBRACK,     "REG_EBRACK",   "brackets ([ ]) not balanced",
+       REG_EPAREN,     "REG_EPAREN",   "parentheses not balanced",
+       REG_EBRACE,     "REG_EBRACE",   "braces not balanced",
+       REG_BADBR,      "REG_BADBR",    "invalid repetition count(s)",
+       REG_ERANGE,     "REG_ERANGE",   "invalid character range",
+       REG_ESPACE,     "REG_ESPACE",   "out of memory",
+       REG_BADRPT,     "REG_BADRPT",   "repetition-operator operand invalid",
+       REG_EMPTY,      "REG_EMPTY",    "empty (sub)expression",
+       REG_ASSERT,     "REG_ASSERT",   "\"can't happen\" -- you found a bug",
+       REG_INVARG,     "REG_INVARG",   "invalid argument to regex routine",
+       -1,             "",             "*** unknown regexp error code ***",
+};
+
+/*
+ - regerror - the interface to error numbers
+ = extern size_t regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+size_t
+regerror(
+int errcode,
+const regex_t *preg,
+char *errbuf,
+size_t errbuf_size)
+{
+       register struct rerr *r;
+       register size_t len;
+       register int target = errcode &~ REG_ITOA;
+       register char *s;
+       char convbuf[50];
+
+       if (errcode == REG_ATOI)
+               s = regatoi(preg, convbuf);
+       else {
+               for (r = rerrs; r->code >= 0; r++)
+                       if (r->code == target)
+                               break;
+       
+               if (errcode&REG_ITOA) {
+                       if (r->code >= 0)
+                               (void) strcpy(convbuf, r->name);
+                       else
+                               sprintf(convbuf, "REG_0x%x", target);
+                       assert(strlen(convbuf) < sizeof(convbuf));
+                       s = convbuf;
+               } else
+                       s = r->explain;
+       }
+
+       len = strlen(s) + 1;
+       if (errbuf_size > 0) {
+               if (errbuf_size > len)
+                       (void) strcpy(errbuf, s);
+               else {
+                       (void) strncpy(errbuf, s, errbuf_size-1);
+                       errbuf[errbuf_size-1] = '\0';
+               }
+       }
+
+       return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(preg, localbuf)
+const regex_t *preg;
+char *localbuf;
+{
+       register struct rerr *r;
+
+       for (r = rerrs; r->code >= 0; r++)
+               if (strcmp(r->name, preg->re_endp) == 0)
+                       break;
+       if (r->code < 0)
+               return("0");
+
+       sprintf(localbuf, "%d", r->code);
+       return(localbuf);
+}
diff --git a/vcnet/regex/regerror.ih b/vcnet/regex/regerror.ih
new file mode 100644 (file)
index 0000000..2cb668c
--- /dev/null
@@ -0,0 +1,12 @@
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/vcnet/regex/regex.3 b/vcnet/regex/regex.3
new file mode 100644 (file)
index 0000000..bc74709
--- /dev/null
@@ -0,0 +1,509 @@
+.TH REGEX 3 "25 Sept 1997"
+.BY "Henry Spencer"
+.de ZR
+.\" one other place knows this name:  the SEE ALSO section
+.IR regex (7) \\$1
+..
+.SH NAME
+regcomp, regexec, regerror, regfree \- regular-expression library
+.SH SYNOPSIS
+.ft B
+.\".na
+#include <sys/types.h>
+.br
+#include <regex.h>
+.HP 10
+int regcomp(regex_t\ *preg, const\ char\ *pattern, int\ cflags);
+.HP
+int\ regexec(const\ regex_t\ *preg, const\ char\ *string,
+size_t\ nmatch, regmatch_t\ pmatch[], int\ eflags);
+.HP
+size_t\ regerror(int\ errcode, const\ regex_t\ *preg,
+char\ *errbuf, size_t\ errbuf_size);
+.HP
+void\ regfree(regex_t\ *preg);
+.\".ad
+.ft
+.SH DESCRIPTION
+These routines implement POSIX 1003.2 regular expressions (``RE''s);
+see
+.ZR .
+.I Regcomp
+compiles an RE written as a string into an internal form,
+.I regexec
+matches that internal form against a string and reports results,
+.I regerror
+transforms error codes from either into human-readable messages,
+and
+.I regfree
+frees any dynamically-allocated storage used by the internal form
+of an RE.
+.PP
+The header
+.I <regex.h>
+declares two structure types,
+.I regex_t
+and
+.IR regmatch_t ,
+the former for compiled internal forms and the latter for match reporting.
+It also declares the four functions,
+a type
+.IR regoff_t ,
+and a number of constants with names starting with ``REG_''.
+.PP
+.I Regcomp
+compiles the regular expression contained in the
+.I pattern
+string,
+subject to the flags in
+.IR cflags ,
+and places the results in the
+.I regex_t
+structure pointed to by
+.IR preg .
+.I Cflags
+is the bitwise OR of zero or more of the following flags:
+.IP REG_EXTENDED \w'REG_EXTENDED'u+2n
+Compile modern (``extended'') REs,
+rather than the obsolete (``basic'') REs that
+are the default.
+.IP REG_BASIC
+This is a synonym for 0,
+provided as a counterpart to REG_EXTENDED to improve readability.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.IP REG_NOSPEC
+Compile with recognition of all special characters turned off.
+All characters are thus considered ordinary,
+so the ``RE'' is a literal string.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+REG_EXTENDED and REG_NOSPEC may not be used
+in the same call to
+.IR regcomp .
+.IP REG_ICASE
+Compile for matching that ignores upper/lower case distinctions.
+See
+.ZR .
+.IP REG_NOSUB
+Compile for matching that need only report success or failure,
+not what was matched.
+.IP REG_NEWLINE
+Compile for newline-sensitive matching.
+By default, newline is a completely ordinary character with no special
+meaning in either REs or strings.
+With this flag,
+`[^' bracket expressions and `.' never match newline,
+a `^' anchor matches the null string after any newline in the string
+in addition to its normal function,
+and the `$' anchor matches the null string before any newline in the
+string in addition to its normal function.
+.IP REG_PEND
+The regular expression ends,
+not at the first NUL,
+but just before the character pointed to by the
+.I re_endp
+member of the structure pointed to by
+.IR preg .
+The
+.I re_endp
+member is of type
+.IR const\ char\ * .
+This flag permits inclusion of NULs in the RE;
+they are considered ordinary characters.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+When successful,
+.I regcomp
+returns 0 and fills in the structure pointed to by
+.IR preg .
+One member of that structure
+(other than
+.IR re_endp )
+is publicized:
+.IR re_nsub ,
+of type
+.IR size_t ,
+contains the number of parenthesized subexpressions within the RE
+(except that the value of this member is undefined if the
+REG_NOSUB flag was used).
+If
+.I regcomp
+fails, it returns a non-zero error code;
+see DIAGNOSTICS.
+.PP
+.I Regexec
+matches the compiled RE pointed to by
+.I preg
+against the
+.IR string ,
+subject to the flags in
+.IR eflags ,
+and reports results using
+.IR nmatch ,
+.IR pmatch ,
+and the returned value.
+The RE must have been compiled by a previous invocation of
+.IR regcomp .
+The compiled form is not altered during execution of
+.IR regexec ,
+so a single compiled RE can be used simultaneously by multiple threads.
+.PP
+By default,
+the NUL-terminated string pointed to by
+.I string
+is considered to be the text of an entire line,
+with the NUL indicating the end of the line.
+(That is,
+any other end-of-line marker is considered to have been removed
+and replaced by the NUL.)
+The
+.I eflags
+argument is the bitwise OR of zero or more of the following flags:
+.IP REG_NOTBOL \w'REG_STARTEND'u+2n
+The first character of
+the string
+is not the beginning of a line, so the `^' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_NOTEOL
+The NUL terminating
+the string
+does not end a line, so the `$' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_STARTEND
+The string is considered to start at
+\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_so\fR
+and to have a terminating NUL located at
+\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_eo\fR
+(there need not actually be a NUL at that location),
+regardless of the value of
+.IR nmatch .
+See below for the definition of
+.IR pmatch
+and
+.IR nmatch .
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Note that a non-zero \fIrm_so\fR does not imply REG_NOTBOL;
+REG_STARTEND affects only the location of the string,
+not how it is matched.
+.PP
+See
+.ZR
+for a discussion of what is matched in situations where an RE or a
+portion thereof could match any of several substrings of
+.IR string .
+.PP
+Normally,
+.I regexec
+returns 0 for success and the non-zero code REG_NOMATCH for failure.
+Other non-zero error codes may be returned in exceptional situations;
+see DIAGNOSTICS.
+.PP
+If REG_NOSUB was specified in the compilation of the RE,
+or if
+.I nmatch
+is 0,
+.I regexec
+ignores the
+.I pmatch
+argument (but see below for the case where REG_STARTEND is specified).
+Otherwise,
+.I pmatch
+points to an array of
+.I nmatch
+structures of type
+.IR regmatch_t .
+Such a structure has at least the members
+.I rm_so
+and
+.IR rm_eo ,
+both of type
+.I regoff_t
+(a signed arithmetic type at least as large as an
+.I off_t
+and a
+.IR ssize_t ),
+containing respectively the offset of the first character of a substring
+and the offset of the first character after the end of the substring.
+Offsets are measured from the beginning of the
+.I string
+argument given to
+.IR regexec .
+An empty substring is denoted by equal offsets,
+both indicating the character following the empty substring.
+.PP
+The 0th member of the
+.I pmatch
+array is filled in to indicate what substring of
+.I string
+was matched by the entire RE.
+Remaining members report what substring was matched by parenthesized
+subexpressions within the RE;
+member
+.I i
+reports subexpression
+.IR i ,
+with subexpressions counted (starting at 1) by the order of their opening
+parentheses in the RE, left to right.
+Unused entries in the array\(emcorresponding either to subexpressions that
+did not participate in the match at all, or to subexpressions that do not
+exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fIre_nsub\fR)\(emhave both
+.I rm_so
+and
+.I rm_eo
+set to \-1.
+If a subexpression participated in the match several times,
+the reported substring is the last one it matched.
+(Note, as an example in particular, that when the RE `(b*)+' matches `bbb',
+the parenthesized subexpression matches the three `b's and then
+an infinite number of empty strings following the last `b',
+so the reported substring is one of the empties.)
+.PP
+If REG_STARTEND is specified,
+.I pmatch
+must point to at least one
+.I regmatch_t
+(even if
+.I nmatch
+is 0 or REG_NOSUB was specified),
+to hold the input offsets for REG_STARTEND.
+Use for output is still entirely controlled by
+.IR nmatch ;
+if
+.I nmatch
+is 0 or REG_NOSUB was specified,
+the value of
+.IR pmatch [0]
+will not be changed by a successful
+.IR regexec .
+.PP
+.I Regerror
+maps a non-zero
+.I errcode
+from either
+.I regcomp
+or
+.I regexec
+to a human-readable, printable message.
+If
+.I preg
+is non-NULL,
+the error code should have arisen from use of
+the
+.I regex_t
+pointed to by
+.IR preg ,
+and if the error code came from
+.IR regcomp ,
+it should have been the result from the most recent
+.I regcomp
+using that
+.IR regex_t .
+.RI ( Regerror
+may be able to supply a more detailed message using information
+from the
+.IR regex_t .)
+.I Regerror
+places the NUL-terminated message into the buffer pointed to by
+.IR errbuf ,
+limiting the length (including the NUL) to at most
+.I errbuf_size
+bytes.
+If the whole message won't fit,
+as much of it as will fit before the terminating NUL is supplied.
+In any case,
+the returned value is the size of buffer needed to hold the whole
+message (including terminating NUL).
+If
+.I errbuf_size
+is 0,
+.I errbuf
+is ignored but the return value is still correct.
+.PP
+If the
+.I errcode
+given to
+.I regerror
+is first ORed with REG_ITOA,
+the ``message'' that results is the printable name of the error code,
+e.g. ``REG_NOMATCH'',
+rather than an explanation thereof.
+If
+.I errcode
+is REG_ATOI,
+then
+.I preg
+shall be non-NULL and the
+.I re_endp
+member of the structure it points to
+must point to the printable name of an error code;
+in this case, the result in
+.I errbuf
+is the decimal digits of
+the numeric value of the error code
+(0 if the name is not recognized).
+REG_ITOA and REG_ATOI are intended primarily as debugging facilities;
+they are extensions,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Be warned also that they are considered experimental and changes are possible.
+.PP
+.I Regfree
+frees any dynamically-allocated storage associated with the compiled RE
+pointed to by
+.IR preg .
+The remaining
+.I regex_t
+is no longer a valid compiled RE
+and the effect of supplying it to
+.I regexec
+or
+.I regerror
+is undefined.
+.PP
+None of these functions references global variables except for tables
+of constants;
+all are safe for use from multiple threads if the arguments are safe.
+.SH IMPLEMENTATION CHOICES
+There are a number of decisions that 1003.2 leaves up to the implementor,
+either by explicitly saying ``undefined'' or by virtue of them being
+forbidden by the RE grammar.
+This implementation treats them as follows.
+.PP
+See
+.ZR
+for a discussion of the definition of case-independent matching.
+.PP
+There is no particular limit on the length of REs,
+except insofar as memory is limited.
+Memory usage is approximately linear in RE size, and largely insensitive
+to RE complexity, except for bounded repetitions.
+See BUGS for one short RE using them
+that will run almost any system out of memory.
+.PP
+A backslashed character other than one specifically given a magic meaning
+by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs)
+is taken as an ordinary character.
+.PP
+Any unmatched [ is a REG_EBRACK error.
+.PP
+Equivalence classes cannot begin or end bracket-expression ranges.
+The endpoint of one range cannot begin another.
+.PP
+RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255.
+.PP
+A repetition operator (?, *, +, or bounds) cannot follow another
+repetition operator.
+A repetition operator cannot begin an expression or subexpression
+or follow `^' or `|'.
+.PP
+`|' cannot appear first or last in a (sub)expression or after another `|',
+i.e. an operand of `|' cannot be an empty subexpression.
+An empty parenthesized subexpression, `()', is legal and matches an
+empty (sub)string.
+An empty string is not a legal RE.
+.PP
+A `{' followed by a digit is considered the beginning of bounds for a
+bounded repetition, which must then follow the syntax for bounds.
+A `{' \fInot\fR followed by a digit is considered an ordinary character.
+.PP
+`^' and `$' beginning and ending subexpressions in obsolete (``basic'')
+REs are anchors, not ordinary characters.
+.SH SEE ALSO
+grep(1), regex(7)
+.PP
+POSIX 1003.2, sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.SH DIAGNOSTICS
+Non-zero error codes from
+.I regcomp
+and
+.I regexec
+include the following:
+.PP
+.nf
+.ta \w'REG_ECOLLATE'u+3n
+REG_NOMATCH    regexec() failed to match
+REG_BADPAT     invalid regular expression
+REG_ECOLLATE   invalid collating element
+REG_ECTYPE     invalid character class
+REG_EESCAPE    \e applied to unescapable character
+REG_ESUBREG    invalid backreference number
+REG_EBRACK     brackets [ ] not balanced
+REG_EPAREN     parentheses ( ) not balanced
+REG_EBRACE     braces { } not balanced
+REG_BADBR      invalid repetition count(s) in { }
+REG_ERANGE     invalid character range in [ ]
+REG_ESPACE     ran out of memory
+REG_BADRPT     ?, *, or + operand invalid
+REG_EMPTY      empty (sub)expression
+REG_ASSERT     ``can't happen''\(emyou found a bug
+REG_INVARG     invalid argument, e.g. negative-length string
+.fi
+.SH HISTORY
+Written by Henry Spencer,
+henry@zoo.toronto.edu.
+.SH BUGS
+This is an alpha release with known defects.
+Please report problems.
+.PP
+There is one known functionality bug.
+The implementation of internationalization is incomplete:
+the locale is always assumed to be the default one of 1003.2,
+and only the collating elements etc. of that locale are available.
+.PP
+The back-reference code is subtle and doubts linger about its correctness
+in complex cases.
+.PP
+.I Regexec
+performance is poor.
+This will improve with later releases.
+.I Nmatch
+exceeding 0 is expensive;
+.I nmatch
+exceeding 1 is worse.
+.I Regexec
+is largely insensitive to RE complexity \fIexcept\fR that back
+references are massively expensive.
+RE length does matter; in particular, there is a strong speed bonus
+for keeping RE length under about 30 characters,
+with most special characters counting roughly double.
+.PP
+.I Regcomp
+implements bounded repetitions by macro expansion,
+which is costly in time and space if counts are large
+or bounded repetitions are nested.
+An RE like, say,
+`((((a{1,100}){1,100}){1,100}){1,100}){1,100}'
+will (eventually) run almost any existing machine out of swap space.
+.PP
+There are suspected problems with response to obscure error conditions.
+Notably,
+certain kinds of internal overflow,
+produced only by truly enormous REs or by multiply nested bounded repetitions,
+are probably not handled well.
+.PP
+Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is
+a special character only in the presence of a previous unmatched `('.
+This can't be fixed until the spec is fixed.
+.PP
+The standard's definition of back references is vague.
+For example, does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?
+Until the standard is clarified,
+behavior in such cases should not be relied on.
+.PP
+The implementation of word-boundary matching is a bit of a kludge,
+and bugs may lurk in combinations of word-boundary matching and anchoring.
diff --git a/vcnet/regex/regex.7 b/vcnet/regex/regex.7
new file mode 100644 (file)
index 0000000..0fa1802
--- /dev/null
@@ -0,0 +1,235 @@
+.TH REGEX 7 "25 Oct 1995"
+.BY "Henry Spencer"
+.SH NAME
+regex \- POSIX 1003.2 regular expressions
+.SH DESCRIPTION
+Regular expressions (``RE''s),
+as defined in POSIX 1003.2, come in two forms:
+modern REs (roughly those of
+.IR egrep ;
+1003.2 calls these ``extended'' REs)
+and obsolete REs (roughly those of
+.IR ed ;
+1003.2 ``basic'' REs).
+Obsolete REs mostly exist for backward compatibility in some old programs;
+they will be discussed at the end.
+1003.2 leaves some aspects of RE syntax and semantics open;
+`\(dg' marks decisions on these aspects that
+may not be fully portable to other 1003.2 implementations.
+.PP
+A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR,
+separated by `|'.
+It matches anything that matches one of the branches.
+.PP
+A branch is one\(dg or more \fIpieces\fR, concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.PP
+A piece is an \fIatom\fR possibly followed
+by a single\(dg `*', `+', `?', or \fIbound\fR.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a sequence of 0 or 1 matches of the atom.
+.PP
+A \fIbound\fR is `{' followed by an unsigned decimal integer,
+possibly followed by `,'
+possibly followed by another unsigned decimal integer,
+always followed by `}'.
+The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer \fIi\fR
+and no comma matches
+a sequence of exactly \fIi\fR matches of the atom.
+An atom followed by a bound
+containing one integer \fIi\fR and a comma matches
+a sequence of \fIi\fR or more matches of the atom.
+An atom followed by a bound
+containing two integers \fIi\fR and \fIj\fR matches
+a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom.
+.PP
+An atom is a regular expression enclosed in `()' (matching a match for the
+regular expression),
+an empty set of `()' (matching the null string)\(dg,
+a \fIbracket expression\fR (see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of a line), `$' (matching the null string at the
+end of a line), a `\e' followed by one of the characters
+`^.[$()|*+?{\e'
+(matching that character taken as an ordinary character),
+a `\e' followed by any other character\(dg
+(matching that character taken as an ordinary character,
+as if the `\e' had not been present\(dg),
+or a single character with no other significance (matching that character).
+A `{' followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dg.
+It is illegal to end an RE with `\e'.
+.PP
+A \fIbracket expression\fR is a list of characters enclosed in `[]'.
+It normally matches any single character from the list (but see below).
+If the list begins with `^',
+it matches any single character
+(but see below) \fInot\fR from the rest of the list.
+If two characters in the list are separated by `\-', this is shorthand
+for the full \fIrange\fR of characters between those two (inclusive) in the
+collating sequence,
+e.g. `[0\-9]' in ASCII matches any decimal digit.
+It is illegal\(dg for two ranges to share an
+endpoint, e.g. `a\-c\-e'.
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.PP
+To include a literal `]' in the list, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character,
+or the second endpoint of a range.
+To use a literal `\-' as the first endpoint of a range,
+enclose it in `[.' and `.]' to make it a collating element (see below).
+With the exception of these and some combinations using `[' (see next
+paragraphs), all other special characters, including `\e', lose their
+special significance within a bracket expression.
+.PP
+Within a bracket expression, a collating element (a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in `[.' and `.]' stands for the
+sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element 
+can thus match more than one character,
+e.g. if the collating sequence includes a `ch' collating element,
+then the RE `[[.ch.]]*c' matches the first five characters
+of `chchcc'.
+.PP
+Within a bracket expression, a collating element enclosed in `[=' and
+`=]' is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were `[.' and `.]'.)
+For example, if o and \o'o^' are the members of an equivalence class,
+then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous.
+An equivalence class may not\(dg be an endpoint
+of a range.
+.PP
+Within a bracket expression, the name of a \fIcharacter class\fR enclosed
+in `[:' and `:]' stands for the list of all characters belonging to that
+class.
+Standard character class names are:
+.PP
+.RS
+.nf
+.ta 3c 6c 9c
+alnum  digit   punct
+alpha  graph   space
+blank  lower   upper
+cntrl  print   xdigit
+.fi
+.RE
+.PP
+These stand for the character classes defined in
+.IR ctype (3).
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.PP
+There are two special cases\(dg of bracket expressions:
+the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at
+the beginning and end of a word respectively.
+A word is defined as a sequence of
+word characters
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.I alnum
+character (as defined by
+.IR ctype (3))
+or an underscore.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.PP
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+`bb*' matches the three middle characters of `abbbc',
+`(wee|week)(knights|nights)' matches all ten characters of `weeknights',
+when `(.*).*' is matched against `abc' the parenthesized subexpression
+matches all three characters, and
+when `(a*)*' is matched against `bc' both the whole RE and the parenthesized
+subexpression match the null string.
+.PP
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+e.g. `x' becomes `[xX]'.
+When it appears inside a bracket expression, all case counterparts
+of it are added to the bracket expression, so that (e.g.) `[x]'
+becomes `[xX]' and `[^x]' becomes `[^xX]'.
+.PP
+No particular limit is imposed on the length of REs\(dg.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.PP
+Obsolete (``basic'') regular expressions differ in several respects.
+`|', `+', and `?' are ordinary characters and there is no equivalent
+for their functionality.
+The delimiters for bounds are `\e{' and `\e}',
+with `{' and `}' by themselves ordinary characters.
+The parentheses for nested subexpressions are `\e(' and `\e)',
+with `(' and `)' by themselves ordinary characters.
+`^' is an ordinary character except at the beginning of the
+RE or\(dg the beginning of a parenthesized subexpression,
+`$' is an ordinary character except at the end of the
+RE or\(dg the end of a parenthesized subexpression,
+and `*' is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading `^').
+Finally, there is one new type of atom, a \fIback reference\fR:
+`\e' followed by a non-zero decimal digit \fId\fR
+matches the same sequence of characters
+matched by the \fId\fRth parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'.
+.SH SEE ALSO
+regex(3)
+.PP
+POSIX 1003.2, section 2.8 (Regular Expression Notation).
+.SH HISTORY
+Written by Henry Spencer, based on the 1003.2 spec.
+.SH BUGS
+Having two kinds of REs is a botch.
+.PP
+The current 1003.2 spec says that `)' is an ordinary character in
+the absence of an unmatched `(';
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.PP
+Back references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?).
+Avoid using them.
+.PP
+1003.2's specification of case-independent matching is vague.
+The ``one case implies all cases'' definition given above
+is current consensus among implementors as to the right interpretation.
+.PP
+The syntax for word boundaries is incredibly ugly.
diff --git a/vcnet/regex/regex.h b/vcnet/regex/regex.h
new file mode 100644 (file)
index 0000000..6918a55
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef _REGEX_H_
+#define        _REGEX_H_       /* never again */
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regex2.h === */
+typedef long regoff_t;
+typedef struct {
+       int re_magic;
+       size_t re_nsub;         /* number of parenthesized subexpressions */
+       const char *re_endp;    /* end pointer for REG_PEND */
+       struct re_guts *re_g;   /* none of your business :-) */
+} regex_t;
+typedef struct {
+       regoff_t rm_so;         /* start of match */
+       regoff_t rm_eo;         /* end of match */
+} regmatch_t;
+
+
+/* === regcomp.c === */
+extern int regcomp(regex_t *, const char *, int);
+#define        REG_BASIC       0000
+#define        REG_EXTENDED    0001
+#define        REG_ICASE       0002
+#define        REG_NOSUB       0004
+#define        REG_NEWLINE     0010
+#define        REG_NOSPEC      0020
+#define        REG_PEND        0040
+#define        REG_DUMP        0200
+
+
+/* === regerror.c === */
+#define        REG_OKAY         0
+#define        REG_NOMATCH      1
+#define        REG_BADPAT       2
+#define        REG_ECOLLATE     3
+#define        REG_ECTYPE       4
+#define        REG_EESCAPE      5
+#define        REG_ESUBREG      6
+#define        REG_EBRACK       7
+#define        REG_EPAREN       8
+#define        REG_EBRACE       9
+#define        REG_BADBR       10
+#define        REG_ERANGE      11
+#define        REG_ESPACE      12
+#define        REG_BADRPT      13
+#define        REG_EMPTY       14
+#define        REG_ASSERT      15
+#define        REG_INVARG      16
+#define        REG_ATOI        255     /* convert name to number (!) */
+#define        REG_ITOA        0400    /* convert number to name (!) */
+extern size_t regerror(int, const regex_t *, char *, size_t);
+
+
+/* === regexec.c === */
+extern int regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
+#define        REG_NOTBOL      00001
+#define        REG_NOTEOL      00002
+#define        REG_STARTEND    00004
+#define        REG_TRACE       00400   /* tracing of execution */
+#define        REG_LARGE       01000   /* force large representation */
+#define        REG_BACKR       02000   /* force use of backref code */
+
+
+/* === regfree.c === */
+extern void regfree(regex_t *);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+#endif
diff --git a/vcnet/regex/regex2.h b/vcnet/regex/regex2.h
new file mode 100644 (file)
index 0000000..58fd8d8
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * First, the stuff that ends up in the outside-world include file
+ = typedef off_t regoff_t;
+ = typedef struct {
+ =     int re_magic;
+ =     size_t re_nsub;         // number of parenthesized subexpressions
+ =     const char *re_endp;    // end pointer for REG_PEND
+ =     struct re_guts *re_g;   // none of your business :-)
+ = } regex_t;
+ = typedef struct {
+ =     regoff_t rm_so;         // start of match
+ =     regoff_t rm_eo;         // end of match
+ = } regmatch_t;
+ */
+/*
+ * internals of regex_t
+ */
+#define        MAGIC1  ((('r'^0200)<<8) | 'e')
+
+/*
+ * The internal representation is a *strip*, a sequence of
+ * operators ending with an endmarker.  (Some terminology etc. is a
+ * historical relic of earlier versions which used multiple strips.)
+ * Certain oddities in the representation are there to permit running
+ * the machinery backwards; in particular, any deviation from sequential
+ * flow must be marked at both its source and its destination.  Some
+ * fine points:
+ *
+ * - OPLUS_ and O_PLUS are *inside* the loop they create.
+ * - OQUEST_ and O_QUEST are *outside* the bypass they create.
+ * - OCH_ and O_CH are *outside* the multi-way branch they create, while
+ *   OOR1 and OOR2 are respectively the end and the beginning of one of
+ *   the branches.  Note that there is an implicit OOR2 following OCH_
+ *   and an implicit OOR1 preceding O_CH.
+ *
+ * In state representations, an operator's bit is on to signify a state
+ * immediately *preceding* "execution" of that operator.
+ */
+typedef long sop;              /* strip operator */
+typedef long sopno;
+#define        OPRMASK 0x7c000000
+#define        OPDMASK 0x03ffffff
+#define        OPSHIFT (26)
+#define        OP(n)   ((n)&OPRMASK)
+#define        OPND(n) ((n)&OPDMASK)
+#define        SOP(op, opnd)   ((op)|(opnd))
+/* operators                      meaning      operand                 */
+/*                                             (back, fwd are offsets) */
+#define        OEND    (1<<OPSHIFT)    /* endmarker    -                       */
+#define        OCHAR   (2<<OPSHIFT)    /* character    unsigned char           */
+#define        OBOL    (3<<OPSHIFT)    /* left anchor  -                       */
+#define        OEOL    (4<<OPSHIFT)    /* right anchor -                       */
+#define        OANY    (5<<OPSHIFT)    /* .            -                       */
+#define        OANYOF  (6<<OPSHIFT)    /* [...]        set number              */
+#define        OBACK_  (7<<OPSHIFT)    /* begin \d     paren number            */
+#define        O_BACK  (8<<OPSHIFT)    /* end \d       paren number            */
+#define        OPLUS_  (9<<OPSHIFT)    /* + prefix     fwd to suffix           */
+#define        O_PLUS  (10<<OPSHIFT)   /* + suffix     back to prefix          */
+#define        OQUEST_ (11<<OPSHIFT)   /* ? prefix     fwd to suffix           */
+#define        O_QUEST (12<<OPSHIFT)   /* ? suffix     back to prefix          */
+#define        OLPAREN (13<<OPSHIFT)   /* (            fwd to )                */
+#define        ORPAREN (14<<OPSHIFT)   /* )            back to (               */
+#define        OCH_    (15<<OPSHIFT)   /* begin choice fwd to OOR2             */
+#define        OOR1    (16<<OPSHIFT)   /* | pt. 1      back to OOR1 or OCH_    */
+#define        OOR2    (17<<OPSHIFT)   /* | pt. 2      fwd to OOR2 or O_CH     */
+#define        O_CH    (18<<OPSHIFT)   /* end choice   back to OOR1            */
+#define        OBOW    (19<<OPSHIFT)   /* begin word   -                       */
+#define        OEOW    (20<<OPSHIFT)   /* end word     -                       */
+
+/*
+ * Structure for [] character-set representation.  Character sets are
+ * done as bit vectors, grouped 8 to a byte vector for compactness.
+ * The individual set therefore has both a pointer to the byte vector
+ * and a mask to pick out the relevant bit of each byte.  A hash code
+ * simplifies testing whether two sets could be identical.
+ *
+ * This will get trickier for multicharacter collating elements.  As
+ * preliminary hooks for dealing with such things, we also carry along
+ * a string of multi-character elements, and decide the size of the
+ * vectors at run time.
+ */
+typedef struct {
+       uch *ptr;               /* -> uch [csetsize] */
+       uch mask;               /* bit within array */
+       uch hash;               /* hash code */
+       size_t smultis;
+       char *multis;           /* -> char[smulti]  ab\0cd\0ef\0\0 */
+} cset;
+/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
+#define        CHadd(cs, c)    ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
+#define        CHsub(cs, c)    ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
+#define        CHIN(cs, c)     ((cs)->ptr[(uch)(c)] & (cs)->mask)
+#define        MCadd(p, cs, cp)        mcadd(p, cs, cp)        /* regcomp() internal fns */
+#define        MCsub(p, cs, cp)        mcsub(p, cs, cp)
+#define        MCin(p, cs, cp) mcin(p, cs, cp)
+
+/* stuff for character categories */
+typedef unsigned char cat_t;
+
+/*
+ * main compiled-expression structure
+ */
+struct re_guts {
+       int magic;
+#              define  MAGIC2  ((('R'^0200)<<8)|'E')
+       sop *strip;             /* malloced area for strip */
+       int csetsize;           /* number of bits in a cset vector */
+       int ncsets;             /* number of csets in use */
+       cset *sets;             /* -> cset [ncsets] */
+       uch *setbits;           /* -> uch[csetsize][ncsets/CHAR_BIT] */
+       int cflags;             /* copy of regcomp() cflags argument */
+       sopno nstates;          /* = number of sops */
+       sopno firststate;       /* the initial OEND (normally 0) */
+       sopno laststate;        /* the final OEND */
+       int iflags;             /* internal flags */
+#              define  USEBOL  01      /* used ^ */
+#              define  USEEOL  02      /* used $ */
+#              define  BAD     04      /* something wrong */
+       int nbol;               /* number of ^ used */
+       int neol;               /* number of $ used */
+       int ncategories;        /* how many character categories */
+       cat_t *categories;      /* ->catspace[-CHAR_MIN] */
+       char *must;             /* match must contain this string */
+       int mlen;               /* length of must */
+       size_t nsub;            /* copy of re_nsub */
+       int backrefs;           /* does it use back references? */
+       sopno nplus;            /* how deep does it nest +s? */
+       /* catspace must be last */
+       cat_t catspace[1];      /* actually [NC] */
+};
+
+/* misc utilities */
+#define        OUT     (CHAR_MAX+1)    /* a non-character value */
+#define        ISWORD(c)       (isalnum(c) || (c) == '_')
diff --git a/vcnet/regex/regexec.c b/vcnet/regex/regexec.c
new file mode 100644 (file)
index 0000000..dcb11b2
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * the outer shell of regexec()
+ *
+ * This file includes engine.c *twice*, after muchos fiddling with the
+ * macros that code uses.  This lets the same code operate on two different
+ * representations for state sets.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+static int nope = 0;           /* for use in asserts; shuts lint up */
+
+/* macros for manipulating states, small version */
+#define        states  unsigned
+#define        states1 unsigned        /* for later use in regexec() decision */
+#define        CLEAR(v)        ((v) = 0)
+#define        SET0(v, n)      ((v) &= ~((unsigned)1 << (n)))
+#define        SET1(v, n)      ((v) |= (unsigned)1 << (n))
+#define        ISSET(v, n)     ((v) & ((unsigned)1 << (n)))
+#define        ASSIGN(d, s)    ((d) = (s))
+#define        EQ(a, b)        ((a) == (b))
+#define        STATEVARS       int dummy       /* dummy version */
+#define        STATESETUP(m, n)        /* nothing */
+#define        STATETEARDOWN(m)        /* nothing */
+#define        SETUP(v)        ((v) = 0)
+#define        onestate        unsigned
+#define        INIT(o, n)      ((o) = (unsigned)1 << (n))
+#define        INC(o)  ((o) <<= 1)
+#define        ISSTATEIN(v, o) ((v) & (o))
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define        FWD(dst, src, n)        ((dst) |= ((unsigned)(src)&(here)) << (n))
+#define        BACK(dst, src, n)       ((dst) |= ((unsigned)(src)&(here)) >> (n))
+#define        ISSETBACK(v, n) ((v) & ((unsigned)here >> (n)))
+/* function names */
+#define SNAMES                 /* engine.c looks after details */
+
+#include "engine.c"
+
+/* now undo things */
+#undef states
+#undef CLEAR
+#undef SET0
+#undef SET1
+#undef ISSET
+#undef ASSIGN
+#undef EQ
+#undef STATEVARS
+#undef STATESETUP
+#undef STATETEARDOWN
+#undef SETUP
+#undef onestate
+#undef INIT
+#undef INC
+#undef ISSTATEIN
+#undef FWD
+#undef BACK
+#undef ISSETBACK
+#undef SNAMES
+
+/* macros for manipulating states, large version */
+#define        states  char *
+#define        CLEAR(v)        memset(v, 0, m->g->nstates)
+#define        SET0(v, n)      ((v)[n] = 0)
+#define        SET1(v, n)      ((v)[n] = 1)
+#define        ISSET(v, n)     ((v)[n])
+#define        ASSIGN(d, s)    memcpy(d, s, m->g->nstates)
+#define        EQ(a, b)        (memcmp(a, b, m->g->nstates) == 0)
+#define        STATEVARS       int vn; char *space
+#define        STATESETUP(m, nv)       { (m)->space = malloc((nv)*(m)->g->nstates); \
+                               if ((m)->space == NULL) return(REG_ESPACE); \
+                               (m)->vn = 0; }
+#define        STATETEARDOWN(m)        { free((m)->space); }
+#define        SETUP(v)        ((v) = &m->space[m->vn++ * m->g->nstates])
+#define        onestate        int
+#define        INIT(o, n)      ((o) = (n))
+#define        INC(o)  ((o)++)
+#define        ISSTATEIN(v, o) ((v)[o])
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define        FWD(dst, src, n)        ((dst)[here+(n)] |= (src)[here])
+#define        BACK(dst, src, n)       ((dst)[here-(n)] |= (src)[here])
+#define        ISSETBACK(v, n) ((v)[here - (n)])
+/* function names */
+#define        LNAMES                  /* flag */
+
+#include "engine.c"
+
+/*
+ - regexec - interface for matching
+ = extern int regexec(const regex_t *, const char *, size_t, \
+ =                                     regmatch_t [], int);
+ = #define     REG_NOTBOL      00001
+ = #define     REG_NOTEOL      00002
+ = #define     REG_STARTEND    00004
+ = #define     REG_TRACE       00400   // tracing of execution
+ = #define     REG_LARGE       01000   // force large representation
+ = #define     REG_BACKR       02000   // force use of backref code
+ *
+ * We put this here so we can exploit knowledge of the state representation
+ * when choosing which matcher to call.  Also, by this point the matchers
+ * have been prototyped.
+ */
+int                            /* 0 success, REG_NOMATCH failure */
+regexec(preg, string, nmatch, pmatch, eflags)
+const regex_t *preg;
+const char *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+       register struct re_guts *g = preg->re_g;
+#ifdef REDEBUG
+#      define  GOODFLAGS(f)    (f)
+#else
+#      define  GOODFLAGS(f)    ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
+#endif
+
+       if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
+               return(REG_BADPAT);
+       assert(!(g->iflags&BAD));
+       if (g->iflags&BAD)              /* backstop for no-debug case */
+               return(REG_BADPAT);
+       eflags = GOODFLAGS(eflags);
+
+       if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
+               return(smatcher(g, (char *)string, nmatch, pmatch, eflags));
+       else
+               return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));
+}
diff --git a/vcnet/regex/regfree.c b/vcnet/regex/regfree.c
new file mode 100644 (file)
index 0000000..9a6acf1
--- /dev/null
@@ -0,0 +1,37 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+/*
+ - regfree - free everything
+ = extern void regfree(regex_t *);
+ */
+void
+regfree(preg)
+regex_t *preg;
+{
+       register struct re_guts *g;
+
+       if (preg->re_magic != MAGIC1)   /* oops */
+               return;                 /* nice to complain, but hard */
+
+       g = preg->re_g;
+       if (g == NULL || g->magic != MAGIC2)    /* oops again */
+               return;
+       preg->re_magic = 0;             /* mark it invalid */
+       g->magic = 0;                   /* mark it invalid */
+
+       if (g->strip != NULL)
+               free((char *)g->strip);
+       if (g->sets != NULL)
+               free((char *)g->sets);
+       if (g->setbits != NULL)
+               free((char *)g->setbits);
+       if (g->must != NULL)
+               free(g->must);
+       free((char *)g);
+}
diff --git a/vcnet/regex/split.c b/vcnet/regex/split.c
new file mode 100644 (file)
index 0000000..188bdb7
--- /dev/null
@@ -0,0 +1,316 @@
+#include <stdio.h>
+#include <string.h>
+
+/*
+ - split - divide a string into fields, like awk split()
+ = int split(char *string, char *fields[], int nfields, char *sep);
+ */
+int                            /* number of fields, including overflow */
+split(string, fields, nfields, sep)
+char *string;
+char *fields[];                        /* list is not NULL-terminated */
+int nfields;                   /* number of entries available in fields[] */
+char *sep;                     /* "" white, "c" single char, "ab" [ab]+ */
+{
+       register char *p = string;
+       register char c;                        /* latest character */
+       register char sepc = sep[0];
+       register char sepc2;
+       register int fn;
+       register char **fp = fields;
+       register char *sepp;
+       register int trimtrail;
+
+       /* white space */
+       if (sepc == '\0') {
+               while ((c = *p++) == ' ' || c == '\t')
+                       continue;
+               p--;
+               trimtrail = 1;
+               sep = " \t";    /* note, code below knows this is 2 long */
+               sepc = ' ';
+       } else
+               trimtrail = 0;
+       sepc2 = sep[1];         /* now we can safely pick this up */
+
+       /* catch empties */
+       if (*p == '\0')
+               return(0);
+
+       /* single separator */
+       if (sepc2 == '\0') {
+               fn = nfields;
+               for (;;) {
+                       *fp++ = p;
+                       fn--;
+                       if (fn == 0)
+                               break;
+                       while ((c = *p++) != sepc)
+                               if (c == '\0')
+                                       return(nfields - fn);
+                       *(p-1) = '\0';
+               }
+               /* we have overflowed the fields vector -- just count them */
+               fn = nfields;
+               for (;;) {
+                       while ((c = *p++) != sepc)
+                               if (c == '\0')
+                                       return(fn);
+                       fn++;
+               }
+               /* not reached */
+       }
+
+       /* two separators */
+       if (sep[2] == '\0') {
+               fn = nfields;
+               for (;;) {
+                       *fp++ = p;
+                       fn--;
+                       while ((c = *p++) != sepc && c != sepc2)
+                               if (c == '\0') {
+                                       if (trimtrail && **(fp-1) == '\0')
+                                               fn++;
+                                       return(nfields - fn);
+                               }
+                       if (fn == 0)
+                               break;
+                       *(p-1) = '\0';
+                       while ((c = *p++) == sepc || c == sepc2)
+                               continue;
+                       p--;
+               }
+               /* we have overflowed the fields vector -- just count them */
+               fn = nfields;
+               while (c != '\0') {
+                       while ((c = *p++) == sepc || c == sepc2)
+                               continue;
+                       p--;
+                       fn++;
+                       while ((c = *p++) != '\0' && c != sepc && c != sepc2)
+                               continue;
+               }
+               /* might have to trim trailing white space */
+               if (trimtrail) {
+                       p--;
+                       while ((c = *--p) == sepc || c == sepc2)
+                               continue;
+                       p++;
+                       if (*p != '\0') {
+                               if (fn == nfields+1)
+                                       *p = '\0';
+                               fn--;
+                       }
+               }
+               return(fn);
+       }
+
+       /* n separators */
+       fn = 0;
+       for (;;) {
+               if (fn < nfields)
+                       *fp++ = p;
+               fn++;
+               for (;;) {
+                       c = *p++;
+                       if (c == '\0')
+                               return(fn);
+                       sepp = sep;
+                       while ((sepc = *sepp++) != '\0' && sepc != c)
+                               continue;
+                       if (sepc != '\0')       /* it was a separator */
+                               break;
+               }
+               if (fn < nfields)
+                       *(p-1) = '\0';
+               for (;;) {
+                       c = *p++;
+                       sepp = sep;
+                       while ((sepc = *sepp++) != '\0' && sepc != c)
+                               continue;
+                       if (sepc == '\0')       /* it wasn't a separator */
+                               break;
+               }
+               p--;
+       }
+
+       /* not reached */
+}
+
+#ifdef TEST_SPLIT
+
+
+/*
+ * test program
+ * pgm         runs regression
+ * pgm sep     splits stdin lines by sep
+ * pgm str sep splits str by sep
+ * pgm str sep n       splits str by sep n times
+ */
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       char buf[512];
+       register int n;
+#      define  MNF     10
+       char *fields[MNF];
+
+       if (argc > 4)
+               for (n = atoi(argv[3]); n > 0; n--) {
+                       (void) strcpy(buf, argv[1]);
+               }
+       else if (argc > 3)
+               for (n = atoi(argv[3]); n > 0; n--) {
+                       (void) strcpy(buf, argv[1]);
+                       (void) split(buf, fields, MNF, argv[2]);
+               }
+       else if (argc > 2)
+               dosplit(argv[1], argv[2]);
+       else if (argc > 1)
+               while (fgets(buf, sizeof(buf), stdin) != NULL) {
+                       buf[strlen(buf)-1] = '\0';      /* stomp newline */
+                       dosplit(buf, argv[1]);
+               }
+       else
+               regress();
+
+       exit(0);
+}
+
+dosplit(string, seps)
+char *string;
+char *seps;
+{
+#      define  NF      5
+       char *fields[NF];
+       register int nf;
+
+       nf = split(string, fields, NF, seps);
+       print(nf, NF, fields);
+}
+
+print(nf, nfp, fields)
+int nf;
+int nfp;
+char *fields[];
+{
+       register int fn;
+       register int bound;
+
+       bound = (nf > nfp) ? nfp : nf;
+       printf("%d:\t", nf);
+       for (fn = 0; fn < bound; fn++)
+               printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n");
+}
+
+#define        RNF     5               /* some table entries know this */
+struct {
+       char *str;
+       char *seps;
+       int nf;
+       char *fi[RNF];
+} tests[] = {
+       "",             " ",    0,      { "" },
+       " ",            " ",    2,      { "", "" },
+       "x",            " ",    1,      { "x" },
+       "xy",           " ",    1,      { "xy" },
+       "x y",          " ",    2,      { "x", "y" },
+       "abc def  g ",  " ",    5,      { "abc", "def", "", "g", "" },
+       "  a bcd",      " ",    4,      { "", "", "a", "bcd" },
+       "a b c d e f",  " ",    6,      { "a", "b", "c", "d", "e f" },
+       " a b c d ",    " ",    6,      { "", "a", "b", "c", "d " },
+
+       "",             " _",   0,      { "" },
+       " ",            " _",   2,      { "", "" },
+       "x",            " _",   1,      { "x" },
+       "x y",          " _",   2,      { "x", "y" },
+       "ab _ cd",      " _",   2,      { "ab", "cd" },
+       " a_b  c ",     " _",   5,      { "", "a", "b", "c", "" },
+       "a b c_d e f",  " _",   6,      { "a", "b", "c", "d", "e f" },
+       " a b c d ",    " _",   6,      { "", "a", "b", "c", "d " },
+
+       "",             " _~",  0,      { "" },
+       " ",            " _~",  2,      { "", "" },
+       "x",            " _~",  1,      { "x" },
+       "x y",          " _~",  2,      { "x", "y" },
+       "ab _~ cd",     " _~",  2,      { "ab", "cd" },
+       " a_b  c~",     " _~",  5,      { "", "a", "b", "c", "" },
+       "a b_c d~e f",  " _~",  6,      { "a", "b", "c", "d", "e f" },
+       "~a b c d ",    " _~",  6,      { "", "a", "b", "c", "d " },
+
+       "",             " _~-", 0,      { "" },
+       " ",            " _~-", 2,      { "", "" },
+       "x",            " _~-", 1,      { "x" },
+       "x y",          " _~-", 2,      { "x", "y" },
+       "ab _~- cd",    " _~-", 2,      { "ab", "cd" },
+       " a_b  c~",     " _~-", 5,      { "", "a", "b", "c", "" },
+       "a b_c-d~e f",  " _~-", 6,      { "a", "b", "c", "d", "e f" },
+       "~a-b c d ",    " _~-", 6,      { "", "a", "b", "c", "d " },
+
+       "",             "  ",   0,      { "" },
+       " ",            "  ",   2,      { "", "" },
+       "x",            "  ",   1,      { "x" },
+       "xy",           "  ",   1,      { "xy" },
+       "x y",          "  ",   2,      { "x", "y" },
+       "abc def  g ",  "  ",   4,      { "abc", "def", "g", "" },
+       "  a bcd",      "  ",   3,      { "", "a", "bcd" },
+       "a b c d e f",  "  ",   6,      { "a", "b", "c", "d", "e f" },
+       " a b c d ",    "  ",   6,      { "", "a", "b", "c", "d " },
+
+       "",             "",     0,      { "" },
+       " ",            "",     0,      { "" },
+       "x",            "",     1,      { "x" },
+       "xy",           "",     1,      { "xy" },
+       "x y",          "",     2,      { "x", "y" },
+       "abc def  g ",  "",     3,      { "abc", "def", "g" },
+       "\t a bcd",     "",     2,      { "a", "bcd" },
+       "  a \tb\t c ", "",     3,      { "a", "b", "c" },
+       "a b c d e ",   "",     5,      { "a", "b", "c", "d", "e" },
+       "a b\tc d e f", "",     6,      { "a", "b", "c", "d", "e f" },
+       " a b c d e f ",        "",     6,      { "a", "b", "c", "d", "e f " },
+
+       NULL,           NULL,   0,      { NULL },
+};
+
+regress()
+{
+       char buf[512];
+       register int n;
+       char *fields[RNF+1];
+       register int nf;
+       register int i;
+       register int printit;
+       register char *f;
+
+       for (n = 0; tests[n].str != NULL; n++) {
+               (void) strcpy(buf, tests[n].str);
+               fields[RNF] = NULL;
+               nf = split(buf, fields, RNF, tests[n].seps);
+               printit = 0;
+               if (nf != tests[n].nf) {
+                       printf("split `%s' by `%s' gave %d fields, not %d\n",
+                               tests[n].str, tests[n].seps, nf, tests[n].nf);
+                       printit = 1;
+               } else if (fields[RNF] != NULL) {
+                       printf("split() went beyond array end\n");
+                       printit = 1;
+               } else {
+                       for (i = 0; i < nf && i < RNF; i++) {
+                               f = fields[i];
+                               if (f == NULL)
+                                       f = "(NULL)";
+                               if (strcmp(f, tests[n].fi[i]) != 0) {
+                                       printf("split `%s' by `%s', field %d is `%s', not `%s'\n",
+                                               tests[n].str, tests[n].seps,
+                                               i, fields[i], tests[n].fi[i]);
+                                       printit = 1;
+                               }
+                       }
+               }
+               if (printit)
+                       print(nf, RNF, fields);
+       }
+}
+#endif
diff --git a/vcnet/regex/tests b/vcnet/regex/tests
new file mode 100644 (file)
index 0000000..e4d928d
--- /dev/null
@@ -0,0 +1,477 @@
+# regular expression test set
+# Lines are at least three fields, separated by one or more tabs.  "" stands
+# for an empty field.  First field is an RE.  Second field is flags.  If
+# C flag given, regcomp() is expected to fail, and the third field is the
+# error name (minus the leading REG_).
+#
+# Otherwise it is expected to succeed, and the third field is the string to
+# try matching it against.  If there is no fourth field, the match is
+# expected to fail.  If there is a fourth field, it is the substring that
+# the RE is expected to match.  If there is a fifth field, it is a comma-
+# separated list of what the subexpressions should match, with - indicating
+# no match for that one.  In both the fourth and fifth fields, a (sub)field
+# starting with @ indicates that the (sub)expression is expected to match
+# a null string followed by the stuff after the @; this provides a way to
+# test where null strings match.  The character `N' in REs and strings
+# is newline, `S' is space, `T' is tab, `Z' is NUL.
+#
+# The full list of flags:
+#      -       placeholder, does nothing
+#      b       RE is a BRE, not an ERE
+#      &       try it as both an ERE and a BRE
+#      C       regcomp() error expected, third field is error name
+#      i       REG_ICASE
+#      m       ("mundane") REG_NOSPEC
+#      s       REG_NOSUB (not really testable)
+#      n       REG_NEWLINE
+#      ^       REG_NOTBOL
+#      $       REG_NOTEOL
+#      #       REG_STARTEND (see below)
+#      p       REG_PEND
+#
+# For REG_STARTEND, the start/end offsets are those of the substring
+# enclosed in ().
+
+# basics
+a              &       a       a
+abc            &       abc     abc
+abc|de         -       abc     abc
+a|b|c          -       abc     a
+
+# parentheses and perversions thereof
+a(b)c          -       abc     abc
+a\(b\)c                b       abc     abc
+a(             C       EPAREN
+a(             b       a(      a(
+a\(            -       a(      a(
+a\(            bC      EPAREN
+a\(b           bC      EPAREN
+a(b            C       EPAREN
+a(b            b       a(b     a(b
+# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
+a)             -       a)      a)
+)              -       )       )
+# end gagging (in a just world, those *should* give EPAREN)
+a)             b       a)      a)
+a\)            bC      EPAREN
+\)             bC      EPAREN
+a()b           -       ab      ab
+a\(\)b         b       ab      ab
+
+# anchoring and REG_NEWLINE
+^abc$          &       abc     abc
+a^b            -       a^b
+a^b            b       a^b     a^b
+a$b            -       a$b
+a$b            b       a$b     a$b
+^              &       abc     @abc
+$              &       abc     @
+^$             &       ""      @
+$^             -       ""      @
+\($\)\(^\)     b       ""      @
+# stop retching, those are legitimate (although disgusting)
+^^             -       ""      @
+$$             -       ""      @
+b$             &       abNc
+b$             &n      abNc    b
+^b$            &       aNbNc
+^b$            &n      aNbNc   b
+^$             &n      aNNb    @Nb
+^$             n       abc
+^$             n       abcN    @
+$^             n       aNNb    @Nb
+\($\)\(^\)     bn      aNNb    @Nb
+^^             n^      aNNb    @Nb
+$$             n       aNNb    @NN
+^a             ^       a
+a$             $       a
+^a             ^n      aNb
+^b             ^n      aNb     b
+a$             $n      bNa
+b$             $n      bNa     b
+a*(^b$)c*      -       b       b
+a*\(^b$\)c*    b       b       b
+
+# certain syntax errors and non-errors
+|              C       EMPTY
+|              b       |       |
+*              C       BADRPT
+*              b       *       *
++              C       BADRPT
+?              C       BADRPT
+""             &C      EMPTY
+()             -       abc     @abc
+\(\)           b       abc     @abc
+a||b           C       EMPTY
+|ab            C       EMPTY
+ab|            C       EMPTY
+(|a)b          C       EMPTY
+(a|)b          C       EMPTY
+(*a)           C       BADRPT
+(+a)           C       BADRPT
+(?a)           C       BADRPT
+({1}a)         C       BADRPT
+\(\{1\}a\)     bC      BADRPT
+(a|*b)         C       BADRPT
+(a|+b)         C       BADRPT
+(a|?b)         C       BADRPT
+(a|{1}b)       C       BADRPT
+^*             C       BADRPT
+^*             b       *       *
+^+             C       BADRPT
+^?             C       BADRPT
+^{1}           C       BADRPT
+^\{1\}         bC      BADRPT
+
+# metacharacters, backslashes
+a.c            &       abc     abc
+a[bc]d         &       abd     abd
+a\*c           &       a*c     a*c
+a\\b           &       a\b     a\b
+a\\\*b         &       a\*b    a\*b
+a\bc           &       abc     abc
+a\             &C      EESCAPE
+a\\bc          &       a\bc    a\bc
+\{             bC      BADRPT
+a\[b           &       a[b     a[b
+a[b            &C      EBRACK
+# trailing $ is a peculiar special case for the BRE code
+a$             &       a       a
+a$             &       a$
+a\$            &       a
+a\$            &       a$      a$
+a\\$           &       a
+a\\$           &       a$
+a\\$           &       a\$
+a\\$           &       a\      a\
+
+# back references, ugh
+a\(b\)\2c      bC      ESUBREG
+a\(b\1\)c      bC      ESUBREG
+a\(b*\)c\1d    b       abbcbbd abbcbbd bb
+a\(b*\)c\1d    b       abbcbd
+a\(b*\)c\1d    b       abbcbbbd
+^\(.\)\1       b       abc
+a\([bc]\)\1d   b       abcdabbd        abbd    b
+a\(\([bc]\)\2\)*d      b       abbccd  abbccd
+a\(\([bc]\)\2\)*d      b       abbcbd
+# actually, this next one probably ought to fail, but the spec is unclear
+a\(\(b\)*\2\)*d                b       abbbd   abbbd
+# here is a case that no NFA implementation does right
+\(ab*\)[ab]*\1 b       ababaaa ababaaa a
+# check out normal matching in the presence of back refs
+\(a\)\1bcd     b       aabcd   aabcd
+\(a\)\1bc*d    b       aabcd   aabcd
+\(a\)\1bc*d    b       aabd    aabd
+\(a\)\1bc*d    b       aabcccd aabcccd
+\(a\)\1bc*[ce]d        b       aabcccd aabcccd
+^\(a\)\1b\(c\)*cd$     b       aabcccd aabcccd
+
+# ordinary repetitions
+ab*c           &       abc     abc
+ab+c           -       abc     abc
+ab?c           -       abc     abc
+a\(*\)b                b       a*b     a*b
+a\(**\)b       b       ab      ab
+a\(***\)b      bC      BADRPT
+*a             b       *a      *a
+**a            b       a       a
+***a           bC      BADRPT
+
+# the dreaded bounded repetitions
+{              &       {       {
+{abc           &       {abc    {abc
+{1             C       BADRPT
+{1}            C       BADRPT
+a{b            &       a{b     a{b
+a{1}b          -       ab      ab
+a\{1\}b                b       ab      ab
+a{1,}b         -       ab      ab
+a\{1,\}b       b       ab      ab
+a{1,2}b                -       aab     aab
+a\{1,2\}b      b       aab     aab
+a{1            C       EBRACE
+a\{1           bC      EBRACE
+a{1a           C       EBRACE
+a\{1a          bC      EBRACE
+a{1a}          C       BADBR
+a\{1a\}                bC      BADBR
+a{,2}          -       a{,2}   a{,2}
+a\{,2\}                bC      BADBR
+a{,}           -       a{,}    a{,}
+a\{,\}         bC      BADBR
+a{1,x}         C       BADBR
+a\{1,x\}       bC      BADBR
+a{1,x          C       EBRACE
+a\{1,x         bC      EBRACE
+a{300}         C       BADBR
+a\{300\}       bC      BADBR
+a{1,0}         C       BADBR
+a\{1,0\}       bC      BADBR
+ab{0,0}c       -       abcac   ac
+ab\{0,0\}c     b       abcac   ac
+ab{0,1}c       -       abcac   abc
+ab\{0,1\}c     b       abcac   abc
+ab{0,3}c       -       abbcac  abbc
+ab\{0,3\}c     b       abbcac  abbc
+ab{1,1}c       -       acabc   abc
+ab\{1,1\}c     b       acabc   abc
+ab{1,3}c       -       acabc   abc
+ab\{1,3\}c     b       acabc   abc
+ab{2,2}c       -       abcabbc abbc
+ab\{2,2\}c     b       abcabbc abbc
+ab{2,4}c       -       abcabbc abbc
+ab\{2,4\}c     b       abcabbc abbc
+((a{1,10}){1,10}){1,10}        -       a       a       a,a
+
+# multiple repetitions
+a**            &C      BADRPT
+a++            C       BADRPT
+a??            C       BADRPT
+a*+            C       BADRPT
+a*?            C       BADRPT
+a+*            C       BADRPT
+a+?            C       BADRPT
+a?*            C       BADRPT
+a?+            C       BADRPT
+a{1}{1}                C       BADRPT
+a*{1}          C       BADRPT
+a+{1}          C       BADRPT
+a?{1}          C       BADRPT
+a{1}*          C       BADRPT
+a{1}+          C       BADRPT
+a{1}?          C       BADRPT
+a*{b}          -       a{b}    a{b}
+a\{1\}\{1\}    bC      BADRPT
+a*\{1\}                bC      BADRPT
+a\{1\}*                bC      BADRPT
+
+# brackets, and numerous perversions thereof
+a[b]c          &       abc     abc
+a[ab]c         &       abc     abc
+a[^ab]c                &       adc     adc
+a[]b]c         &       a]c     a]c
+a[[b]c         &       a[c     a[c
+a[-b]c         &       a-c     a-c
+a[^]b]c                &       adc     adc
+a[^-b]c                &       adc     adc
+a[b-]c         &       a-c     a-c
+a[b            &C      EBRACK
+a[]            &C      EBRACK
+a[1-3]c                &       a2c     a2c
+a[3-1]c                &C      ERANGE
+a[1-3-5]c      &C      ERANGE
+a[[.-.]--]c    &       a-c     a-c
+a[1-           &C      ERANGE
+a[[.           &C      EBRACK
+a[[.x          &C      EBRACK
+a[[.x.         &C      EBRACK
+a[[.x.]                &C      EBRACK
+a[[.x.]]       &       ax      ax
+a[[.x,.]]      &C      ECOLLATE
+a[[.one.]]b    &       a1b     a1b
+a[[.notdef.]]b &C      ECOLLATE
+a[[.].]]b      &       a]b     a]b
+a[[:alpha:]]c  &       abc     abc
+a[[:notdef:]]c &C      ECTYPE
+a[[:           &C      EBRACK
+a[[:alpha      &C      EBRACK
+a[[:alpha:]    &C      EBRACK
+a[[:alpha,:]   &C      ECTYPE
+a[[:]:]]b      &C      ECTYPE
+a[[:-:]]b      &C      ECTYPE
+a[[:alph:]]    &C      ECTYPE
+a[[:alphabet:]]        &C      ECTYPE
+[[:alnum:]]+   -       -%@a0X- a0X
+[[:alpha:]]+   -       -%@aX0- aX
+[[:blank:]]+   -       aSSTb   SST
+[[:cntrl:]]+   -       aNTb    NT
+[[:digit:]]+   -       a019b   019
+[[:graph:]]+   -       Sa%bS   a%b
+[[:lower:]]+   -       AabC    ab
+[[:print:]]+   -       NaSbN   aSb
+[[:punct:]]+   -       S%-&T   %-&
+[[:space:]]+   -       aSNTb   SNT
+[[:upper:]]+   -       aBCd    BC
+[[:xdigit:]]+  -       p0f3Cq  0f3C
+a[[=b=]]c      &       abc     abc
+a[[=           &C      EBRACK
+a[[=b          &C      EBRACK
+a[[=b=         &C      EBRACK
+a[[=b=]                &C      EBRACK
+a[[=b,=]]      &C      ECOLLATE
+a[[=one=]]b    &       a1b     a1b
+
+# complexities
+a(((b)))c      -       abc     abc
+a(b|(c))d      -       abd     abd
+a(b*|c)d       -       abbd    abbd
+# just gotta have one DFA-buster, of course
+a[ab]{20}      -       aaaaabaaaabaaaabaaaab   aaaaabaaaabaaaabaaaab
+# and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab]      -       aaaaabaaaabaaaabaaaab   aaaaabaaaabaaaabaaaab
+# and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night)     -       aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights
+# fish for anomalies as the number of states passes 32
+12345678901234567890123456789  -       a12345678901234567890123456789b 12345678901234567890123456789
+123456789012345678901234567890 -       a123456789012345678901234567890b        123456789012345678901234567890
+1234567890123456789012345678901        -       a1234567890123456789012345678901b       1234567890123456789012345678901
+12345678901234567890123456789012       -       a12345678901234567890123456789012b      12345678901234567890123456789012
+123456789012345678901234567890123      -       a123456789012345678901234567890123b     123456789012345678901234567890123
+# and one really big one, beyond any plausible word width
+1234567890123456789012345678901234567890123456789012345678901234567890 -       a1234567890123456789012345678901234567890123456789012345678901234567890b        1234567890123456789012345678901234567890123456789012345678901234567890
+# fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn]   -       xacegikmoq      acegikm
+[ab][cd][ef][gh][ij][kl][mn][op]       -       xacegikmoq      acegikmo
+[ab][cd][ef][gh][ij][kl][mn][op][qr]   -       xacegikmoqy     acegikmoq
+[ab][cd][ef][gh][ij][kl][mn][op][q]    -       xacegikmoqy     acegikmoq
+
+# subtleties of matching
+abc            &       xabcy   abc
+a\(b\)?c\1d    b       acd
+aBc            i       Abc     Abc
+a[Bc]*d                i       abBCcd  abBCcd
+0[[:upper:]]1  &i      0a1     0a1
+0[[:lower:]]1  &i      0A1     0A1
+a[^b]c         &i      abc
+a[^b]c         &i      aBc
+a[^b]c         &i      adc     adc
+[a]b[c]                -       abc     abc
+[a]b[a]                -       aba     aba
+[abc]b[abc]    -       abc     abc
+[abc]b[abd]    -       abd     abd
+a(b?c)+d       -       accd    accd
+(wee|week)(knights|night)      -       weeknights      weeknights
+(we|wee|week|frob)(knights|night|day)  -       weeknights      weeknights
+a[bc]d         -       xyzaaabcaababdacd       abd
+a[ab]c         -       aaabc   abc
+abc            s       abc     abc
+a*             &       b       @b
+
+# Let's have some fun -- try to match a C comment.
+# first the obvious, which looks okay at first glance...
+/\*.*\*/       -       /*x*/   /*x*/
+# but...
+/\*.*\*/       -       /*x*/y/*z*/     /*x*/y/*z*/
+# okay, we must not match */ inside; try to do that...
+/\*([^*]|\*[^/])*\*/   -       /*x*/   /*x*/
+/\*([^*]|\*[^/])*\*/   -       /*x*/y/*z*/     /*x*/
+# but...
+/\*([^*]|\*[^/])*\*/   -       /*x**/y/*z*/    /*x**/y/*z*/
+# and a still fancier version, which does it right (I think)...
+/\*([^*]|\*+[^*/])*\*+/        -       /*x*/   /*x*/
+/\*([^*]|\*+[^*/])*\*+/        -       /*x*/y/*z*/     /*x*/
+/\*([^*]|\*+[^*/])*\*+/        -       /*x**/y/*z*/    /*x**/
+/\*([^*]|\*+[^*/])*\*+/        -       /*x****/y/*z*/  /*x****/
+/\*([^*]|\*+[^*/])*\*+/        -       /*x**x*/y/*z*/  /*x**x*/
+/\*([^*]|\*+[^*/])*\*+/        -       /*x***x/y/*z*/  /*x***x/y/*z*/
+
+# subexpressions
+.*             -       abc     abc     -
+a(b)(c)d       -       abcd    abcd    b,c
+a(((b)))c      -       abc     abc     b,b,b
+a(b|(c))d      -       abd     abd     b,-
+a(b*|c|e)d     -       abbd    abbd    bb
+a(b*|c|e)d     -       acd     acd     c
+a(b*|c|e)d     -       ad      ad      @d
+a(b?)c         -       abc     abc     b
+a(b?)c         -       ac      ac      @c
+a(b+)c         -       abc     abc     b
+a(b+)c         -       abbbc   abbbc   bbb
+a(b*)c         -       ac      ac      @c
+(a|ab)(bc([de]+)f|cde) -       abcdef  abcdef  a,bcdef,de
+# the regression tester only asks for 9 subexpressions
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)k  -       abcdefghijk     abcdefghijk     b,c,d,e,f,g,h,i,j
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l       -       abcdefghijkl    abcdefghijkl    b,c,d,e,f,g,h,i,j,k
+a([bc]?)c      -       abc     abc     b
+a([bc]?)c      -       ac      ac      @c
+a([bc]+)c      -       abc     abc     b
+a([bc]+)c      -       abcc    abcc    bc
+a([bc]+)bc     -       abcbc   abcbc   bc
+a(bb+|b)b      -       abb     abb     b
+a(bbb+|bb+|b)b -       abb     abb     b
+a(bbb+|bb+|b)b -       abbb    abbb    bb
+a(bbb+|bb+|b)bb        -       abbb    abbb    b
+(.*).*         -       abcdef  abcdef  abcdef
+(a*)*          -       bc      @b      @b
+
+# do we get the right subexpression when it is used more than once?
+a(b|c)*d       -       ad      ad      -
+a(b|c)*d       -       abcd    abcd    c
+a(b|c)+d       -       abd     abd     b
+a(b|c)+d       -       abcd    abcd    c
+a(b|c?)+d      -       ad      ad      @d
+a(b|c?)+d      -       abcd    abcd    @d
+a(b|c){0,0}d   -       ad      ad      -
+a(b|c){0,1}d   -       ad      ad      -
+a(b|c){0,1}d   -       abd     abd     b
+a(b|c){0,2}d   -       ad      ad      -
+a(b|c){0,2}d   -       abcd    abcd    c
+a(b|c){0,}d    -       ad      ad      -
+a(b|c){0,}d    -       abcd    abcd    c
+a(b|c){1,1}d   -       abd     abd     b
+a(b|c){1,1}d   -       acd     acd     c
+a(b|c){1,2}d   -       abd     abd     b
+a(b|c){1,2}d   -       abcd    abcd    c
+a(b|c){1,}d    -       abd     abd     b
+a(b|c){1,}d    -       abcd    abcd    c
+a(b|c){2,2}d   -       acbd    acbd    b
+a(b|c){2,2}d   -       abcd    abcd    c
+a(b|c){2,4}d   -       abcd    abcd    c
+a(b|c){2,4}d   -       abcbd   abcbd   b
+a(b|c){2,4}d   -       abcbcd  abcbcd  c
+a(b|c){2,}d    -       abcd    abcd    c
+a(b|c){2,}d    -       abcbd   abcbd   b
+a(b+|((c)*))+d -       abd     abd     @d,@d,-
+a(b+|((c)*))+d -       abcd    abcd    @d,@d,-
+
+# check out the STARTEND option
+[abc]          &#      a(b)c   b
+[abc]          &#      a(d)c
+[abc]          &#      a(bc)d  b
+[abc]          &#      a(dc)d  c
+.              &#      a()c
+b.*c           &#      b(bc)c  bc
+b.*            &#      b(bc)c  bc
+.*c            &#      b(bc)c  bc
+
+# plain strings, with the NOSPEC flag
+abc            m       abc     abc
+abc            m       xabcy   abc
+abc            m       xyz
+a*b            m       aba*b   a*b
+a*b            m       ab
+""             mC      EMPTY
+
+# cases involving NULs
+aZb            &       a       a
+aZb            &p      a
+aZb            &p#     (aZb)   aZb
+aZ*b           &p#     (ab)    ab
+a.b            &#      (aZb)   aZb
+a.*            &#      (aZb)c  aZb
+
+# word boundaries (ick)
+[[:<:]]a       &       a       a
+[[:<:]]a       &       ba
+[[:<:]]a       &       -a      a
+a[[:>:]]       &       a       a
+a[[:>:]]       &       ab
+a[[:>:]]       &       a-      a
+[[:<:]]a.c[[:>:]]      &       axcd-dayc-dazce-abc     abc
+[[:<:]]a.c[[:>:]]      &       axcd-dayc-dazce-abc-q   abc
+[[:<:]]a.c[[:>:]]      &       axc-dayc-dazce-abc      axc
+[[:<:]]b.c[[:>:]]      &       a_bxc-byc_d-bzc-q       bzc
+[[:<:]].x..[[:>:]]     &       y_xa_-_xb_y-_xc_-axdc   _xc_
+[[:<:]]a_b[[:>:]]      &       x_a_b
+
+# past problems, and suspected problems
+(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A])  -       A1      A1
+abcdefghijklmnop       i       abcdefghijklmnop        abcdefghijklmnop
+abcdefghijklmnopqrstuv i       abcdefghijklmnopqrstuv  abcdefghijklmnopqrstuv
+(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN])    -       CC11    CC11
+CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a   -       CC11    CC11
+Char \([a-z0-9_]*\)\[.*        b       Char xyz[k      Char xyz[k      xyz
+a?b    -       ab      ab
+-\{0,1\}[0-9]*$        b       -5      -5
+a*a*a*a*a*a*a* &       aaaaaa  aaaaaa
diff --git a/vcnet/regex/utils.h b/vcnet/regex/utils.h
new file mode 100644 (file)
index 0000000..1a997ac
--- /dev/null
@@ -0,0 +1,22 @@
+/* utility definitions */
+#ifdef _POSIX2_RE_DUP_MAX
+#define        DUPMAX  _POSIX2_RE_DUP_MAX
+#else
+#define        DUPMAX  255
+#endif
+#define        INFINITY        (DUPMAX + 1)
+#define        NC              (CHAR_MAX - CHAR_MIN + 1)
+typedef unsigned char uch;
+
+/* switch off assertions (if not already off) if no REDEBUG */
+#ifndef REDEBUG
+#ifndef NDEBUG
+#define        NDEBUG  /* no assertions please */
+#endif
+#endif
+#include <assert.h>
+
+/* for old systems with bcopy() but no memmove() */
+#ifdef USEBCOPY
+#define        memmove(d, s, c)        bcopy(s, d, c)
+#endif