summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES-1.4.txt17
-rw-r--r--CHANGES.txt6
-rw-r--r--Makedefs.in5
-rw-r--r--Makefile10
-rw-r--r--backend/Dependencies8
-rw-r--r--backend/Makefile33
-rw-r--r--backend/ieee1284.c5
-rw-r--r--backend/scsi-irix.c241
-rw-r--r--backend/scsi-linux.c260
-rw-r--r--backend/scsi.c231
-rw-r--r--backend/socket.c10
-rw-r--r--backend/usb-libusb.c3
-rw-r--r--cgi-bin/Dependencies1
-rw-r--r--cgi-bin/Makefile26
-rw-r--r--cgi-bin/admin.c59
-rw-r--r--cgi-bin/cgi.h9
-rw-r--r--cgi-bin/libcupscgi.exp2
-rw-r--r--cgi-bin/template.c25
-rw-r--r--cgi-bin/var.c273
-rw-r--r--conf/mime.convs.in3
-rw-r--r--conf/mime.types10
-rw-r--r--config-scripts/cups-common.m48
-rw-r--r--config-scripts/cups-defaults.m49
-rw-r--r--config-scripts/cups-launchd.m45
-rw-r--r--config-scripts/cups-sharedlibs.m437
-rw-r--r--config-scripts/cups-ssl.m419
-rw-r--r--configure.in4
-rw-r--r--cups/Makefile98
-rw-r--r--cups/attr.c93
-rw-r--r--cups/debug.c2
-rw-r--r--cups/globals.c46
-rw-r--r--cups/globals.h2
-rw-r--r--cups/http.c56
-rw-r--r--cups/i18n.h8
-rw-r--r--cups/ipp-support.c2
-rw-r--r--cups/ipp.c37
-rw-r--r--cups/libcups.exp356
-rw-r--r--cups/libcups2.def8
-rw-r--r--cups/libcups_s.exp2
-rw-r--r--cups/options.c100
-rw-r--r--cups/page.c18
-rw-r--r--cups/ppd-private.h6
-rw-r--r--cups/tempfile.c4
-rw-r--r--data/HPGLprolog27
-rw-r--r--data/Makefile3
-rw-r--r--doc/help/ref-cupsd-conf.html.in19
-rw-r--r--doc/help/ref-page_log.html4
-rw-r--r--doc/help/spec-cmp.html77
-rw-r--r--driver/Dependencies2
-rw-r--r--driver/Makefile12
-rw-r--r--filter/Dependencies156
-rw-r--r--filter/Makefile32
-rw-r--r--filter/form-main.c53
-rw-r--r--filter/form-ps.c40
-rw-r--r--filter/form-tree.c615
-rw-r--r--filter/form.h168
-rw-r--r--filter/hpgl-attr.c479
-rw-r--r--filter/hpgl-char.c631
-rw-r--r--filter/hpgl-config.c636
-rw-r--r--filter/hpgl-input.c272
-rw-r--r--filter/hpgl-main.c269
-rw-r--r--filter/hpgl-polygon.c385
-rw-r--r--filter/hpgl-prolog.c369
-rw-r--r--filter/hpgl-vector.c773
-rw-r--r--filter/hpgltops.h240
-rw-r--r--man/Makefile4
-rw-r--r--man/cupsd.conf.man.in8
-rw-r--r--man/ipp.test.man450
-rw-r--r--man/ipptest.man89
-rw-r--r--packaging/cups.list.in69
-rw-r--r--packaging/cups.spec.in9
-rw-r--r--ppdc/Makefile20
-rw-r--r--scheduler/Dependencies3
-rw-r--r--scheduler/Makefile35
-rw-r--r--scheduler/cert.c19
-rw-r--r--scheduler/classes.c16
-rw-r--r--scheduler/classes.h6
-rw-r--r--scheduler/client.c15
-rw-r--r--scheduler/conf.c9
-rw-r--r--scheduler/conf.h7
-rw-r--r--scheduler/cups-driverd.cxx3
-rw-r--r--scheduler/ipp.c66
-rw-r--r--scheduler/job.c8
-rw-r--r--scheduler/listen.c3
-rw-r--r--scheduler/main.c2
-rw-r--r--scheduler/printers.c31
-rw-r--r--scheduler/printers.h2
-rw-r--r--standards/Makefile8
-rw-r--r--standards/rfc2046.txt2467
-rw-r--r--standards/rfc3282.txt451
-rw-r--r--standards/rfc4646.txt3307
-rw-r--r--systemv/Dependencies19
-rw-r--r--systemv/Makefile8
-rw-r--r--systemv/lppasswd.c31
-rw-r--r--systemv/lpstat.c24
-rw-r--r--templates/add-class.tmpl1
-rw-r--r--templates/add-printer.tmpl1
-rw-r--r--templates/add-rss-subscription.tmpl1
-rw-r--r--templates/admin.tmpl13
-rw-r--r--templates/choose-device.tmpl1
-rw-r--r--templates/choose-make.tmpl1
-rw-r--r--templates/choose-model.tmpl1
-rw-r--r--templates/choose-serial.tmpl1
-rw-r--r--templates/choose-uri.tmpl1
-rw-r--r--templates/class-confirm.tmpl2
-rw-r--r--templates/class.tmpl2
-rw-r--r--templates/de/add-class.tmpl1
-rw-r--r--templates/de/add-printer.tmpl1
-rw-r--r--templates/de/add-rss-subscription.tmpl1
-rw-r--r--templates/de/admin.tmpl15
-rw-r--r--templates/de/choose-device.tmpl1
-rw-r--r--templates/de/choose-make.tmpl1
-rw-r--r--templates/de/choose-model.tmpl3
-rw-r--r--templates/de/choose-serial.tmpl1
-rw-r--r--templates/de/choose-uri.tmpl1
-rw-r--r--templates/de/class-confirm.tmpl2
-rw-r--r--templates/de/class.tmpl2
-rw-r--r--templates/de/edit-config.tmpl2
-rw-r--r--templates/de/job-move.tmpl1
-rw-r--r--templates/de/jobs.tmpl10
-rw-r--r--templates/de/list-available-printers.tmpl2
-rw-r--r--templates/de/modify-class.tmpl1
-rw-r--r--templates/de/modify-printer.tmpl1
-rw-r--r--templates/de/printer-confirm.tmpl2
-rw-r--r--templates/de/printer.tmpl2
-rw-r--r--templates/de/samba-export.tmpl1
-rw-r--r--templates/de/set-printer-options-header.tmpl1
-rw-r--r--templates/de/users.tmpl1
-rw-r--r--templates/edit-config.tmpl2
-rw-r--r--templates/es/add-class.tmpl1
-rw-r--r--templates/es/add-printer.tmpl1
-rw-r--r--templates/es/add-rss-subscription.tmpl1
-rw-r--r--templates/es/admin.tmpl15
-rw-r--r--templates/es/choose-device.tmpl1
-rw-r--r--templates/es/choose-make.tmpl1
-rw-r--r--templates/es/choose-model.tmpl1
-rw-r--r--templates/es/choose-serial.tmpl1
-rw-r--r--templates/es/choose-uri.tmpl1
-rw-r--r--templates/es/class-confirm.tmpl2
-rw-r--r--templates/es/class.tmpl2
-rw-r--r--templates/es/edit-config.tmpl2
-rw-r--r--templates/es/job-move.tmpl1
-rw-r--r--templates/es/jobs.tmpl10
-rw-r--r--templates/es/list-available-printers.tmpl2
-rw-r--r--templates/es/modify-class.tmpl1
-rw-r--r--templates/es/modify-printer.tmpl1
-rw-r--r--templates/es/printer-confirm.tmpl2
-rw-r--r--templates/es/printer.tmpl2
-rw-r--r--templates/es/samba-export.tmpl1
-rw-r--r--templates/es/set-printer-options-header.tmpl1
-rw-r--r--templates/es/users.tmpl1
-rw-r--r--templates/eu/add-class.tmpl1
-rw-r--r--templates/eu/add-printer.tmpl1
-rw-r--r--templates/eu/add-rss-subscription.tmpl1
-rw-r--r--templates/eu/admin.tmpl15
-rw-r--r--templates/eu/choose-device.tmpl1
-rw-r--r--templates/eu/choose-make.tmpl1
-rw-r--r--templates/eu/choose-model.tmpl1
-rw-r--r--templates/eu/choose-serial.tmpl1
-rw-r--r--templates/eu/choose-uri.tmpl1
-rw-r--r--templates/eu/class-confirm.tmpl2
-rw-r--r--templates/eu/class.tmpl2
-rw-r--r--templates/eu/edit-config.tmpl2
-rw-r--r--templates/eu/job-move.tmpl1
-rw-r--r--templates/eu/jobs.tmpl10
-rw-r--r--templates/eu/list-available-printers.tmpl2
-rw-r--r--templates/eu/modify-class.tmpl1
-rw-r--r--templates/eu/modify-printer.tmpl1
-rw-r--r--templates/eu/printer-confirm.tmpl2
-rw-r--r--templates/eu/printer.tmpl2
-rw-r--r--templates/eu/samba-export.tmpl1
-rw-r--r--templates/eu/set-printer-options-header.tmpl1
-rw-r--r--templates/eu/users.tmpl1
-rw-r--r--templates/id/add-class.tmpl1
-rw-r--r--templates/id/add-printer.tmpl1
-rw-r--r--templates/id/add-rss-subscription.tmpl1
-rw-r--r--templates/id/admin.tmpl15
-rw-r--r--templates/id/choose-device.tmpl1
-rw-r--r--templates/id/choose-make.tmpl1
-rw-r--r--templates/id/choose-model.tmpl1
-rw-r--r--templates/id/choose-serial.tmpl1
-rw-r--r--templates/id/choose-uri.tmpl1
-rw-r--r--templates/id/class-confirm.tmpl2
-rw-r--r--templates/id/class.tmpl2
-rw-r--r--templates/id/edit-config.tmpl2
-rw-r--r--templates/id/job-move.tmpl1
-rw-r--r--templates/id/jobs.tmpl11
-rw-r--r--templates/id/list-available-printers.tmpl2
-rw-r--r--templates/id/modify-class.tmpl1
-rw-r--r--templates/id/modify-printer.tmpl1
-rw-r--r--templates/id/printer-confirm.tmpl2
-rw-r--r--templates/id/printer.tmpl2
-rw-r--r--templates/id/samba-export.tmpl1
-rw-r--r--templates/id/set-printer-options-header.tmpl1
-rw-r--r--templates/id/users.tmpl1
-rw-r--r--templates/it/add-class.tmpl1
-rw-r--r--templates/it/add-printer.tmpl1
-rw-r--r--templates/it/add-rss-subscription.tmpl1
-rw-r--r--templates/it/admin.tmpl15
-rw-r--r--templates/it/choose-device.tmpl1
-rw-r--r--templates/it/choose-make.tmpl1
-rw-r--r--templates/it/choose-model.tmpl1
-rw-r--r--templates/it/choose-serial.tmpl1
-rw-r--r--templates/it/choose-uri.tmpl1
-rw-r--r--templates/it/class-confirm.tmpl2
-rw-r--r--templates/it/class.tmpl2
-rw-r--r--templates/it/edit-config.tmpl2
-rw-r--r--templates/it/job-move.tmpl1
-rw-r--r--templates/it/jobs.tmpl10
-rw-r--r--templates/it/list-available-printers.tmpl2
-rw-r--r--templates/it/modify-class.tmpl1
-rw-r--r--templates/it/modify-printer.tmpl1
-rw-r--r--templates/it/printer-confirm.tmpl2
-rw-r--r--templates/it/printer.tmpl2
-rw-r--r--templates/it/samba-export.tmpl1
-rw-r--r--templates/it/set-printer-options-header.tmpl1
-rw-r--r--templates/it/users.tmpl1
-rw-r--r--templates/ja/add-class.tmpl1
-rw-r--r--templates/ja/add-printer.tmpl1
-rw-r--r--templates/ja/add-rss-subscription.tmpl1
-rw-r--r--templates/ja/admin.tmpl15
-rw-r--r--templates/ja/choose-device.tmpl1
-rw-r--r--templates/ja/choose-make.tmpl1
-rw-r--r--templates/ja/choose-model.tmpl1
-rw-r--r--templates/ja/choose-serial.tmpl1
-rw-r--r--templates/ja/choose-uri.tmpl1
-rw-r--r--templates/ja/class-confirm.tmpl2
-rw-r--r--templates/ja/class.tmpl2
-rw-r--r--templates/ja/edit-config.tmpl2
-rw-r--r--templates/ja/job-move.tmpl1
-rw-r--r--templates/ja/jobs.tmpl10
-rw-r--r--templates/ja/list-available-printers.tmpl2
-rw-r--r--templates/ja/modify-class.tmpl1
-rw-r--r--templates/ja/modify-printer.tmpl1
-rw-r--r--templates/ja/printer-confirm.tmpl2
-rw-r--r--templates/ja/printer.tmpl2
-rw-r--r--templates/ja/samba-export.tmpl1
-rw-r--r--templates/ja/set-printer-options-header.tmpl1
-rw-r--r--templates/ja/users.tmpl1
-rw-r--r--templates/job-move.tmpl1
-rw-r--r--templates/jobs.tmpl11
-rw-r--r--templates/list-available-printers.tmpl2
-rw-r--r--templates/modify-class.tmpl1
-rw-r--r--templates/modify-printer.tmpl1
-rw-r--r--templates/pl/add-class.tmpl1
-rw-r--r--templates/pl/add-printer.tmpl1
-rw-r--r--templates/pl/add-rss-subscription.tmpl1
-rw-r--r--templates/pl/admin.tmpl15
-rw-r--r--templates/pl/choose-device.tmpl1
-rw-r--r--templates/pl/choose-make.tmpl1
-rw-r--r--templates/pl/choose-model.tmpl1
-rw-r--r--templates/pl/choose-serial.tmpl1
-rw-r--r--templates/pl/choose-uri.tmpl1
-rw-r--r--templates/pl/class-confirm.tmpl2
-rw-r--r--templates/pl/class.tmpl2
-rw-r--r--templates/pl/edit-config.tmpl2
-rw-r--r--templates/pl/job-move.tmpl1
-rw-r--r--templates/pl/jobs.tmpl10
-rw-r--r--templates/pl/list-available-printers.tmpl2
-rw-r--r--templates/pl/modify-class.tmpl1
-rw-r--r--templates/pl/modify-printer.tmpl1
-rw-r--r--templates/pl/printer-confirm.tmpl2
-rw-r--r--templates/pl/printer.tmpl2
-rw-r--r--templates/pl/samba-export.tmpl1
-rw-r--r--templates/pl/set-printer-options-header.tmpl1
-rw-r--r--templates/pl/users.tmpl1
-rw-r--r--templates/printer-confirm.tmpl2
-rw-r--r--templates/printer.tmpl2
-rw-r--r--templates/ru/add-class.tmpl1
-rw-r--r--templates/ru/add-printer.tmpl1
-rw-r--r--templates/ru/add-rss-subscription.tmpl1
-rw-r--r--templates/ru/admin.tmpl15
-rw-r--r--templates/ru/choose-device.tmpl1
-rw-r--r--templates/ru/choose-make.tmpl1
-rw-r--r--templates/ru/choose-model.tmpl1
-rw-r--r--templates/ru/choose-serial.tmpl1
-rw-r--r--templates/ru/choose-uri.tmpl1
-rw-r--r--templates/ru/class-confirm.tmpl2
-rw-r--r--templates/ru/class.tmpl2
-rw-r--r--templates/ru/edit-config.tmpl2
-rw-r--r--templates/ru/job-move.tmpl1
-rw-r--r--templates/ru/jobs.tmpl10
-rw-r--r--templates/ru/list-available-printers.tmpl2
-rw-r--r--templates/ru/modify-class.tmpl1
-rw-r--r--templates/ru/modify-printer.tmpl1
-rw-r--r--templates/ru/printer-confirm.tmpl2
-rw-r--r--templates/ru/printer.tmpl2
-rw-r--r--templates/ru/samba-export.tmpl1
-rw-r--r--templates/ru/set-printer-options-header.tmpl1
-rw-r--r--templates/ru/users.tmpl1
-rw-r--r--templates/samba-export.tmpl1
-rw-r--r--templates/set-printer-options-header.tmpl1
-rw-r--r--templates/users.tmpl1
-rw-r--r--test/Dependencies9
-rw-r--r--test/Makefile47
-rw-r--r--test/ipp-1.1.test742
-rw-r--r--test/ipp-2.0.test107
-rw-r--r--test/ipp-2.1.test105
-rw-r--r--test/ipptest.c3387
-rw-r--r--test/print-job-media-col.test39
-rw-r--r--test/str-header.html13
-rw-r--r--vc2005/ipptest.vcproj199
-rw-r--r--vcnet/config.h29
-rw-r--r--vcnet/cups.sln27
-rw-r--r--vcnet/ipptest.vcproj230
-rw-r--r--vcnet/regex/COPYRIGHT20
-rw-r--r--vcnet/regex/Makefile130
-rw-r--r--vcnet/regex/README32
-rw-r--r--vcnet/regex/WHATSNEW108
-rw-r--r--vcnet/regex/cclass.h31
-rw-r--r--vcnet/regex/cname.h102
-rw-r--r--vcnet/regex/debug.c242
-rw-r--r--vcnet/regex/debug.ih14
-rw-r--r--vcnet/regex/engine.c1019
-rw-r--r--vcnet/regex/engine.ih35
-rw-r--r--vcnet/regex/main.c510
-rw-r--r--vcnet/regex/main.ih19
-rw-r--r--vcnet/regex/mkh76
-rw-r--r--vcnet/regex/regcomp.c1603
-rw-r--r--vcnet/regex/regcomp.ih51
-rw-r--r--vcnet/regex/regerror.c126
-rw-r--r--vcnet/regex/regerror.ih12
-rw-r--r--vcnet/regex/regex.3509
-rw-r--r--vcnet/regex/regex.7235
-rw-r--r--vcnet/regex/regex.h74
-rw-r--r--vcnet/regex/regex2.h134
-rw-r--r--vcnet/regex/regexec.c138
-rw-r--r--vcnet/regex/regfree.c37
-rw-r--r--vcnet/regex/split.c316
-rw-r--r--vcnet/regex/tests477
-rw-r--r--vcnet/regex/utils.h22
331 files changed, 18670 insertions, 7405 deletions
diff --git a/CHANGES-1.4.txt b/CHANGES-1.4.txt
index 2cdd32e73..ba74e6465 100644
--- a/CHANGES-1.4.txt
+++ b/CHANGES-1.4.txt
@@ -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
diff --git a/CHANGES.txt b/CHANGES.txt
index b8f215201..ee9680d74 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -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)
diff --git a/Makedefs.in b/Makedefs.in
index e557871d2..d173cb7be 100644
--- a/Makedefs.in
+++ b/Makedefs.in
@@ -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@
diff --git a/Makefile b/Makefile
index 9ccc12992..82c29d66c 100644
--- 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)
diff --git a/backend/Dependencies b/backend/Dependencies
index 9051be05c..429398ab1 100644
--- a/backend/Dependencies
+++ b/backend/Dependencies
@@ -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
diff --git a/backend/Makefile b/backend/Makefile
index 807b4c4e6..6b217462f 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -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
@@ -17,12 +17,16 @@
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)
@@ -222,17 +226,6 @@ parallel: parallel.o ../cups/$(LIBCUPS) libbackend.a
#
-# 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
#
diff --git a/backend/ieee1284.c b/backend/ieee1284.c
index 6b2d010f0..434db8739 100644
--- a/backend/ieee1284.c
+++ b/backend/ieee1284.c
@@ -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
index f4a60101c..000000000
--- a/backend/scsi-irix.c
+++ /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
index 934a626ec..000000000
--- a/backend/scsi-linux.c
+++ /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
index 7040d4bda..000000000
--- a/backend/scsi.c
+++ /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 $".
- */
diff --git a/backend/socket.c b/backend/socket.c
index 46d7f5eda..53f8dc0b5 100644
--- a/backend/socket.c
+++ b/backend/socket.c
@@ -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)
{
diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c
index 2efece7ef..e46e6ea9d 100644
--- a/backend/usb-libusb.c
+++ b/backend/usb-libusb.c
@@ -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)
diff --git a/cgi-bin/Dependencies b/cgi-bin/Dependencies
index f018cd0a0..83c8d7e09 100644
--- a/cgi-bin/Dependencies
+++ b/cgi-bin/Dependencies
@@ -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
diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile
index 7b1abb6f9..f967f46aa 100644
--- a/cgi-bin/Makefile
+++ b/cgi-bin/Makefile
@@ -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)
diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c
index ccf10de57..5617be224 100644
--- a/cgi-bin/admin.c
+++ b/cgi-bin/admin.c
@@ -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
@@ -49,6 +49,13 @@
/*
+ * 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,
@@ -978,20 +999,6 @@ do_am_printer(http_t *http, /* I - HTTP connection */
}
/*
- * 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);
diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h
index 52368ee35..bceb5f519 100644
--- a/cgi-bin/cgi.h
+++ b/cgi-bin/cgi.h
@@ -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);
diff --git a/cgi-bin/libcupscgi.exp b/cgi-bin/libcupscgi.exp
index 1997cdb10..3a26229d7 100644
--- a/cgi-bin/libcupscgi.exp
+++ b/cgi-bin/libcupscgi.exp
@@ -10,6 +10,7 @@ _cgiFormEncode
_cgiFreeSearch
_cgiGetArray
_cgiGetAttributes
+_cgiGetCookie
_cgiGetFile
_cgiGetIPPObjects
_cgiGetSize
@@ -24,6 +25,7 @@ _cgiRewriteURL
_cgiSetArray
_cgiSetIPPObjectVars
_cgiSetIPPVars
+_cgiSetCookie
_cgiSetServerVersion
_cgiSetSize
_cgiSetVariable
diff --git a/cgi-bin/template.c b/cgi-bin/template.c
index 6e9cc5ec6..8ec653878 100644
--- a/cgi-bin/template.c
+++ b/cgi-bin/template.c
@@ -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
diff --git a/cgi-bin/var.c b/cgi-bin/var.c
index 1467bd878..d376d1009 100644
--- a/cgi-bin/var.c
+++ b/cgi-bin/var.c
@@ -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
@@ -14,25 +14,34 @@
*
* 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.
*/
@@ -40,6 +49,15 @@
/*#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 */
@@ -182,6 +204,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 */
/*
@@ -268,6 +303,20 @@ cgiInitialize(void)
#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);
@@ -371,6 +438,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 */
@@ -534,6 +633,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 */
/*
@@ -1015,6 +1200,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.
*/
diff --git a/conf/mime.convs.in b/conf/mime.convs.in
index a141b5c09..9e6796ad4 100644
--- a/conf/mime.convs.in
+++ b/conf/mime.convs.in
@@ -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
diff --git a/conf/mime.types b/conf/mime.types
index 8ef1c06a9..dd28daaf6 100644
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -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")))
########################################################################
#
diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4
index d47f14278..361661981 100644
--- a/config-scripts/cups-common.m4
+++ b/config-scripts/cups-common.m4
@@ -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
diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4
index 4f455a823..2864cbad4 100644
--- a/config-scripts/cups-defaults.m4
+++ b/config-scripts/cups-defaults.m4
@@ -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
diff --git a/config-scripts/cups-launchd.m4 b/config-scripts/cups-launchd.m4
index a6a893235..23a229516 100644
--- a/config-scripts/cups-launchd.m4
+++ b/config-scripts/cups-launchd.m4
@@ -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)
diff --git a/config-scripts/cups-sharedlibs.m4 b/config-scripts/cups-sharedlibs.m4
index 09c55f897..4363bfce2 100644
--- a/config-scripts/cups-sharedlibs.m4
+++ b/config-scripts/cups-sharedlibs.m4
@@ -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
diff --git a/config-scripts/cups-ssl.m4 b/config-scripts/cups-ssl.m4
index 7e20ecd90..b0139c78c 100644
--- a/config-scripts/cups-ssl.m4
+++ b/config-scripts/cups-ssl.m4
@@ -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
diff --git a/configure.in b/configure.in
index 91f193d1d..34198e412 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/cups/Makefile b/cups/Makefile
index 088611143..b7e9a8d8a 100644
--- a/cups/Makefile
+++ b/cups/Makefile
@@ -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
@@ -376,36 +380,12 @@ libcups.a: $(LIBOBJS)
#
-# 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)
diff --git a/cups/attr.c b/cups/attr.c
index c2c6eb512..2cae04f3d 100644
--- a/cups/attr.c
+++ b/cups/attr.c
@@ -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.
*/
/*
@@ -141,89 +141,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.
*
* This function tries to undo the mistakes made by many printer manufacturers
diff --git a/cups/debug.c b/cups/debug.c
index f3d2f1c5b..137edffc4 100644
--- a/cups/debug.c
+++ b/cups/debug.c
@@ -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 */
diff --git a/cups/globals.c b/cups/globals.c
index 4e49109fc..8207312ce 100644
--- a/cups/globals.c
+++ b/cups/globals.c
@@ -38,6 +38,51 @@
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 */
}
diff --git a/cups/globals.h b/cups/globals.h
index fecbeb3d7..1e07daac6 100644
--- a/cups/globals.h
+++ b/cups/globals.h
@@ -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);
diff --git a/cups/http.c b/cups/http.c
index abd241305..084e88e9b 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -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 */
diff --git a/cups/i18n.h b/cups/i18n.h
index c61be42c4..bc6e779b0 100644
--- a/cups/i18n.h
+++ b/cups/i18n.h
@@ -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);
diff --git a/cups/ipp-support.c b/cups/ipp-support.c
index 82200ae7d..663ba3ed7 100644
--- a/cups/ipp-support.c
+++ b/cups/ipp-support.c
@@ -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 */
diff --git a/cups/ipp.c b/cups/ipp.c
index 70fb41f38..2f12f85b4 100644
--- a/cups/ipp.c
+++ b/cups/ipp.c
@@ -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]);
+
}
}
diff --git a/cups/libcups.exp b/cups/libcups.exp
index 16fa94d1d..e69de29bb 100644
--- a/cups/libcups.exp
+++ b/cups/libcups.exp
@@ -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
diff --git a/cups/libcups2.def b/cups/libcups2.def
index 1f99d8888..65f59bd1c 100644
--- a/cups/libcups2.def
+++ b/cups/libcups2.def
@@ -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
diff --git a/cups/libcups_s.exp b/cups/libcups_s.exp
index 1b45a396a..1ad3017fe 100644
--- a/cups/libcups_s.exp
+++ b/cups/libcups_s.exp
@@ -5,6 +5,7 @@ _cupsCharmapFlush
_cupsCharmapFree
_cupsCharmapGet
_cupsEncodingName
+_cupsGet1284Values
_cupsGetPassword
_cupsGlobals
_cupsLangPrintf
@@ -53,7 +54,6 @@ _httpResolveURI
_ippAddAttr
_ippFreeAttr
_ppdFreeLanguages
-_ppdGet1284Values
_ppdGetEncoding
_ppdGetLanguages
_ppdHashName
diff --git a/cups/options.c b/cups/options.c
index 23e4dff1c..0c9069c09 100644
--- a/cups/options.c
+++ b/cups/options.c
@@ -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
@@ -16,11 +16,14 @@
*
* 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.
*/
/*
@@ -501,6 +504,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.
*/
diff --git a/cups/page.c b/cups/page.c
index 34f0a02d7..71817b613 100644
--- a/cups/page.c
+++ b/cups/page.c
@@ -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;
diff --git a/cups/ppd-private.h b/cups/ppd-private.h
index fa33e96c6..7b647b511 100644
--- a/cups/ppd-private.h
+++ b/cups/ppd-private.h
@@ -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);
diff --git a/cups/tempfile.c b/cups/tempfile.c
index 6a781bb71..1503b4f7d 100644
--- a/cups/tempfile.c
+++ b/cups/tempfile.c
@@ -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
index 2ebf98574..000000000
--- a/data/HPGLprolog
+++ /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
diff --git a/data/Makefile b/data/Makefile
index e518c8f01..504d2e5fd 100644
--- a/data/Makefile
+++ b/data/Makefile
@@ -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
diff --git a/doc/help/ref-cupsd-conf.html.in b/doc/help/ref-cupsd-conf.html.in
index 6b3384bbc..4f1089a17 100644
--- a/doc/help/ref-cupsd-conf.html.in
+++ b/doc/help/ref-cupsd-conf.html.in
@@ -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>
diff --git a/doc/help/ref-page_log.html b/doc/help/ref-page_log.html
index a0ec7a0e2..076cc4b9c 100644
--- a/doc/help/ref-page_log.html
+++ b/doc/help/ref-page_log.html
@@ -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
diff --git a/doc/help/spec-cmp.html b/doc/help/spec-cmp.html
index 23e229407..ab9a1329c 100644
--- a/doc/help/spec-cmp.html
+++ b/doc/help/spec-cmp.html
@@ -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>
diff --git a/driver/Dependencies b/driver/Dependencies
index 2111f79f0..ed31ab6c7 100644
--- a/driver/Dependencies
+++ b/driver/Dependencies
@@ -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
diff --git a/driver/Makefile b/driver/Makefile
index dcfef5556..8f017ace1 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -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
diff --git a/filter/Dependencies b/filter/Dependencies
index a50962a1a..59fc5065d 100644
--- a/filter/Dependencies
+++ b/filter/Dependencies
@@ -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
diff --git a/filter/Makefile b/filter/Makefile
index 6e2e96bd1..184b3072d 100644
--- a/filter/Makefile
+++ b/filter/Makefile
@@ -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)
@@ -293,15 +293,6 @@ commandtops: commandtops.o ../cups/$(LIBCUPS)
#
-# formtops
-#
-
-formtops: $(FORMOBJS) common.o ../cups/$(LIBCUPS)
- echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ $(FORMOBJS) common.o $(LIBS) -lm
-
-
-#
# gziptoany
#
@@ -311,15 +302,6 @@ gziptoany: gziptoany.o ../Makedefs ../cups/$(LIBCUPS)
#
-# 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
index 0f4ff1b61..000000000
--- a/filter/form-main.c
+++ /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
index 6a1e1e327..000000000
--- a/filter/form-ps.c
+++ /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
index 337924d09..000000000
--- a/filter/form-tree.c
+++ /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
index 7b4598ef3..000000000
--- a/filter/form.h
+++ /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
index 7a93ad7d8..000000000
--- a/filter/hpgl-attr.c
+++ /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
index 031b938fd..000000000
--- a/filter/hpgl-char.c
+++ /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
index 180674d79..000000000
--- a/filter/hpgl-config.c
+++ /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
index 195094c75..000000000
--- a/filter/hpgl-input.c
+++ /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
index 953d44702..000000000
--- a/filter/hpgl-main.c
+++ /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
index 6f8df01c3..000000000
--- a/filter/hpgl-polygon.c
+++ /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
index 00e512b7a..000000000
--- a/filter/hpgl-prolog.c
+++ /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
index fdf8664a4..000000000
--- a/filter/hpgl-vector.c
+++ /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
index 4fe45d282..000000000
--- a/filter/hpgltops.h
+++ /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 $".
- */
diff --git a/man/Makefile b/man/Makefile
index b12c39a65..9e489b3a2 100644
--- a/man/Makefile
+++ b/man/Makefile
@@ -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) \
diff --git a/man/cupsd.conf.man.in b/man/cupsd.conf.man.in
index fc36f5db8..ad4d082b3 100644
--- a/man/cupsd.conf.man.in
+++ b/man/cupsd.conf.man.in
@@ -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
index 000000000..248719964
--- /dev/null
+++ b/man/ipp.test.man
@@ -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
index 000000000..2d1467652
--- /dev/null
+++ b/man/ipptest.man
@@ -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$".
+.\"
diff --git a/packaging/cups.list.in b/packaging/cups.list.in
index b6eb952b0..adad41785 100644
--- a/packaging/cups.list.in
+++ b/packaging/cups.list.in
@@ -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
diff --git a/packaging/cups.spec.in b/packaging/cups.spec.in
index 267cac94a..26d0ac8a1 100644
--- a/packaging/cups.spec.in
+++ b/packaging/cups.spec.in
@@ -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*
diff --git a/ppdc/Makefile b/ppdc/Makefile
index 524426541..f58b6f882 100644
--- a/ppdc/Makefile
+++ b/ppdc/Makefile
@@ -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)
diff --git a/scheduler/Dependencies b/scheduler/Dependencies
index 8a2a20cc7..1a8e7c325 100644
--- a/scheduler/Dependencies
+++ b/scheduler/Dependencies
@@ -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
diff --git a/scheduler/Makefile b/scheduler/Makefile
index fe8ee6b1d..15292b9c6 100644
--- a/scheduler/Makefile
+++ b/scheduler/Makefile
@@ -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)
diff --git a/scheduler/cert.c b/scheduler/cert.c
index 94449eb46..c34efac0c 100644
--- a/scheduler/cert.c
+++ b/scheduler/cert.c
@@ -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...
diff --git a/scheduler/classes.c b/scheduler/classes.c
index 77214aba6..fca0d18b1 100644
--- a/scheduler/classes.c
+++ b/scheduler/classes.c
@@ -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);
}
diff --git a/scheduler/classes.h b/scheduler/classes.h
index 68288f69b..e9940ce2b 100644
--- a/scheduler/classes.h
+++ b/scheduler/classes.h
@@ -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);
diff --git a/scheduler/client.c b/scheduler/client.c
index 93fbf3419..2400b57fe 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -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)
{
diff --git a/scheduler/conf.c b/scheduler/conf.c
index abcb0f183..bc83cc11c 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -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...
diff --git a/scheduler/conf.h b/scheduler/conf.h
index c30f97a5e..1084bc2af 100644
--- a/scheduler/conf.h
+++ b/scheduler/conf.h
@@ -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__
diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx
index 0d776a637..b34f6616f 100644
--- a/scheduler/cups-driverd.cxx
+++ b/scheduler/cups-driverd.cxx
@@ -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"))
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index a2595d90e..ced835f29 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -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)
diff --git a/scheduler/job.c b/scheduler/job.c
index 4442cacc7..91a017b75 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -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)
{
diff --git a/scheduler/listen.c b/scheduler/listen.c
index 2b4f9e0fd..85c807166 100644
--- a/scheduler/listen.c
+++ b/scheduler/listen.c
@@ -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);
diff --git a/scheduler/main.c b/scheduler/main.c
index 60e97d095..9dfb38966 100644
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -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 */
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 1e615ebe0..876231d45 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -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...
diff --git a/scheduler/printers.h b/scheduler/printers.h
index 713539941..327909240 100644
--- a/scheduler/printers.h
+++ b/scheduler/printers.h
@@ -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,
diff --git a/standards/Makefile b/standards/Makefile
index 53b2c1f98..d6ddb8353 100644
--- a/standards/Makefile
+++ b/standards/Makefile
@@ -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
index 000000000..84d90c109
--- /dev/null
+++ b/standards/rfc2046.txt
@@ -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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
diff --git a/standards/rfc3282.txt b/standards/rfc3282.txt
new file mode 100644
index 000000000..bf5b868b1
--- /dev/null
+++ b/standards/rfc3282.txt
@@ -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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
diff --git a/standards/rfc4646.txt b/standards/rfc4646.txt
new file mode 100644
index 000000000..466d54744
--- /dev/null
+++ b/standards/rfc4646.txt
@@ -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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
+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]
+
diff --git a/systemv/Dependencies b/systemv/Dependencies
index f0b180813..32aa60e0e 100644
--- a/systemv/Dependencies
+++ b/systemv/Dependencies
@@ -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
diff --git a/systemv/Makefile b/systemv/Makefile
index 0df674a0f..ae5f5a063 100644
--- a/systemv/Makefile
+++ b/systemv/Makefile
@@ -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)
#
diff --git a/systemv/lppasswd.c b/systemv/lppasswd.c
index 5dfeb48a3..cd51014b5 100644
--- a/systemv/lppasswd.c
+++ b/systemv/lppasswd.c
@@ -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)
diff --git a/systemv/lpstat.c b/systemv/lpstat.c
index e98aaa70d..5f4e0b47a 100644
--- a/systemv/lpstat.c
+++ b/systemv/lpstat.c
@@ -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
@@ -34,10 +34,7 @@
#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"));
diff --git a/templates/add-class.tmpl b/templates/add-class.tmpl
index 0bb15f18d..eaf52d73d 100644
--- a/templates/add-class.tmpl
+++ b/templates/add-class.tmpl
@@ -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>
diff --git a/templates/add-printer.tmpl b/templates/add-printer.tmpl
index 7f375078a..361958b67 100644
--- a/templates/add-printer.tmpl
+++ b/templates/add-printer.tmpl
@@ -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}">
diff --git a/templates/add-rss-subscription.tmpl b/templates/add-rss-subscription.tmpl
index 810fb3a50..e0727835b 100644
--- a/templates/add-rss-subscription.tmpl
+++ b/templates/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/admin.tmpl b/templates/admin.tmpl
index bbf9db7cd..da89d54e2 100644
--- a/templates/admin.tmpl
+++ b/templates/admin.tmpl
@@ -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>
diff --git a/templates/choose-device.tmpl b/templates/choose-device.tmpl
index a4877ca63..c5ab251b5 100644
--- a/templates/choose-device.tmpl
+++ b/templates/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/choose-make.tmpl b/templates/choose-make.tmpl
index e2731dea3..65096ad9a 100644
--- a/templates/choose-make.tmpl
+++ b/templates/choose-make.tmpl
@@ -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}">
diff --git a/templates/choose-model.tmpl b/templates/choose-model.tmpl
index 33282fb15..992cd01fd 100644
--- a/templates/choose-model.tmpl
+++ b/templates/choose-model.tmpl
@@ -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}">
diff --git a/templates/choose-serial.tmpl b/templates/choose-serial.tmpl
index d714779b3..56a14a4cb 100644
--- a/templates/choose-serial.tmpl
+++ b/templates/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/choose-uri.tmpl b/templates/choose-uri.tmpl
index 907c02aca..e62ea1e13 100644
--- a/templates/choose-uri.tmpl
+++ b/templates/choose-uri.tmpl
@@ -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}">
diff --git a/templates/class-confirm.tmpl b/templates/class-confirm.tmpl
index c14d35482..5f0277cb5 100644
--- a/templates/class-confirm.tmpl
+++ b/templates/class-confirm.tmpl
@@ -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>
diff --git a/templates/class.tmpl b/templates/class.tmpl
index 535af64a6..9987062d2 100644
--- a/templates/class.tmpl
+++ b/templates/class.tmpl
@@ -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>
diff --git a/templates/de/add-class.tmpl b/templates/de/add-class.tmpl
index 019bdf2b2..264a019bf 100644
--- a/templates/de/add-class.tmpl
+++ b/templates/de/add-class.tmpl
@@ -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>
diff --git a/templates/de/add-printer.tmpl b/templates/de/add-printer.tmpl
index 42d18fe0e..15380b97b 100644
--- a/templates/de/add-printer.tmpl
+++ b/templates/de/add-printer.tmpl
@@ -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}">
diff --git a/templates/de/add-rss-subscription.tmpl b/templates/de/add-rss-subscription.tmpl
index 264457de0..cef109ca9 100644
--- a/templates/de/add-rss-subscription.tmpl
+++ b/templates/de/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/de/admin.tmpl b/templates/de/admin.tmpl
index a3445479c..1ad132691 100644
--- a/templates/de/admin.tmpl
+++ b/templates/de/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/de/choose-device.tmpl b/templates/de/choose-device.tmpl
index c292f0a37..3be8a350c 100644
--- a/templates/de/choose-device.tmpl
+++ b/templates/de/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/de/choose-make.tmpl b/templates/de/choose-make.tmpl
index 96b32e309..6d572a6b2 100644
--- a/templates/de/choose-make.tmpl
+++ b/templates/de/choose-make.tmpl
@@ -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}">
diff --git a/templates/de/choose-model.tmpl b/templates/de/choose-model.tmpl
index 0b651fcbb..2f5bb18d8 100644
--- a/templates/de/choose-model.tmpl
+++ b/templates/de/choose-model.tmpl
@@ -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>
diff --git a/templates/de/choose-serial.tmpl b/templates/de/choose-serial.tmpl
index 7fab7ca94..a6f0044b5 100644
--- a/templates/de/choose-serial.tmpl
+++ b/templates/de/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/de/choose-uri.tmpl b/templates/de/choose-uri.tmpl
index 6d2244f58..073b0d824 100644
--- a/templates/de/choose-uri.tmpl
+++ b/templates/de/choose-uri.tmpl
@@ -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}">
diff --git a/templates/de/class-confirm.tmpl b/templates/de/class-confirm.tmpl
index 20cd6db2d..5e0223cff 100644
--- a/templates/de/class-confirm.tmpl
+++ b/templates/de/class-confirm.tmpl
@@ -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>
diff --git a/templates/de/class.tmpl b/templates/de/class.tmpl
index da72bc44c..a64a2daef 100644
--- a/templates/de/class.tmpl
+++ b/templates/de/class.tmpl
@@ -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>
diff --git a/templates/de/edit-config.tmpl b/templates/de/edit-config.tmpl
index 7439c9884..f2913138b 100644
--- a/templates/de/edit-config.tmpl
+++ b/templates/de/edit-config.tmpl
@@ -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>
diff --git a/templates/de/job-move.tmpl b/templates/de/job-move.tmpl
index 90cc98e7a..67c57dd31 100644
--- a/templates/de/job-move.tmpl
+++ b/templates/de/job-move.tmpl
@@ -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}">:}
diff --git a/templates/de/jobs.tmpl b/templates/de/jobs.tmpl
index 3a524bb58..94a60b0aa 100644
--- a/templates/de/jobs.tmpl
+++ b/templates/de/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/de/list-available-printers.tmpl b/templates/de/list-available-printers.tmpl
index 9ca2b5377..08a04522a 100644
--- a/templates/de/list-available-printers.tmpl
+++ b/templates/de/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/de/modify-class.tmpl b/templates/de/modify-class.tmpl
index 1db4a3fd5..2e0bae80d 100644
--- a/templates/de/modify-class.tmpl
+++ b/templates/de/modify-class.tmpl
@@ -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}">
diff --git a/templates/de/modify-printer.tmpl b/templates/de/modify-printer.tmpl
index a44da2bea..d128471d7 100644
--- a/templates/de/modify-printer.tmpl
+++ b/templates/de/modify-printer.tmpl
@@ -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}">
diff --git a/templates/de/printer-confirm.tmpl b/templates/de/printer-confirm.tmpl
index 3bbe1fb34..030f6524a 100644
--- a/templates/de/printer-confirm.tmpl
+++ b/templates/de/printer-confirm.tmpl
@@ -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>
diff --git a/templates/de/printer.tmpl b/templates/de/printer.tmpl
index e3e1ebc4a..ffc58e919 100644
--- a/templates/de/printer.tmpl
+++ b/templates/de/printer.tmpl
@@ -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>
diff --git a/templates/de/samba-export.tmpl b/templates/de/samba-export.tmpl
index 1cb202b90..ab2b0c60c 100644
--- a/templates/de/samba-export.tmpl
+++ b/templates/de/samba-export.tmpl
@@ -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>
diff --git a/templates/de/set-printer-options-header.tmpl b/templates/de/set-printer-options-header.tmpl
index b4187e321..75f9f4ff2 100644
--- a/templates/de/set-printer-options-header.tmpl
+++ b/templates/de/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/de/users.tmpl b/templates/de/users.tmpl
index acb889272..0704e8754 100644
--- a/templates/de/users.tmpl
+++ b/templates/de/users.tmpl
@@ -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}">:}
diff --git a/templates/edit-config.tmpl b/templates/edit-config.tmpl
index ea45d81f5..8947382b1 100644
--- a/templates/edit-config.tmpl
+++ b/templates/edit-config.tmpl
@@ -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>
diff --git a/templates/es/add-class.tmpl b/templates/es/add-class.tmpl
index bc2db61ed..f7e79fa89 100644
--- a/templates/es/add-class.tmpl
+++ b/templates/es/add-class.tmpl
@@ -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>
diff --git a/templates/es/add-printer.tmpl b/templates/es/add-printer.tmpl
index 9e65a93b9..eedc3db40 100644
--- a/templates/es/add-printer.tmpl
+++ b/templates/es/add-printer.tmpl
@@ -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}">
diff --git a/templates/es/add-rss-subscription.tmpl b/templates/es/add-rss-subscription.tmpl
index 89d77ced6..8fb7f3da0 100644
--- a/templates/es/add-rss-subscription.tmpl
+++ b/templates/es/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/es/admin.tmpl b/templates/es/admin.tmpl
index 81a92ba18..53e5d34d8 100644
--- a/templates/es/admin.tmpl
+++ b/templates/es/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/es/choose-device.tmpl b/templates/es/choose-device.tmpl
index 79ac4942d..9f314fdf6 100644
--- a/templates/es/choose-device.tmpl
+++ b/templates/es/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/es/choose-make.tmpl b/templates/es/choose-make.tmpl
index 370db237d..c846de4df 100644
--- a/templates/es/choose-make.tmpl
+++ b/templates/es/choose-make.tmpl
@@ -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}">
diff --git a/templates/es/choose-model.tmpl b/templates/es/choose-model.tmpl
index 8338da27d..497d4b1d1 100644
--- a/templates/es/choose-model.tmpl
+++ b/templates/es/choose-model.tmpl
@@ -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}">
diff --git a/templates/es/choose-serial.tmpl b/templates/es/choose-serial.tmpl
index 513d0a20d..e296fb95f 100644
--- a/templates/es/choose-serial.tmpl
+++ b/templates/es/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/es/choose-uri.tmpl b/templates/es/choose-uri.tmpl
index a7ff12d2c..c02577395 100644
--- a/templates/es/choose-uri.tmpl
+++ b/templates/es/choose-uri.tmpl
@@ -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}">
diff --git a/templates/es/class-confirm.tmpl b/templates/es/class-confirm.tmpl
index f55f1c64b..a30ff726f 100644
--- a/templates/es/class-confirm.tmpl
+++ b/templates/es/class-confirm.tmpl
@@ -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>
diff --git a/templates/es/class.tmpl b/templates/es/class.tmpl
index 9b511ae87..f3704380b 100644
--- a/templates/es/class.tmpl
+++ b/templates/es/class.tmpl
@@ -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>
diff --git a/templates/es/edit-config.tmpl b/templates/es/edit-config.tmpl
index cfa4ac99e..a0c663436 100644
--- a/templates/es/edit-config.tmpl
+++ b/templates/es/edit-config.tmpl
@@ -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>
diff --git a/templates/es/job-move.tmpl b/templates/es/job-move.tmpl
index 30919df5d..e6aac39a5 100644
--- a/templates/es/job-move.tmpl
+++ b/templates/es/job-move.tmpl
@@ -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}">:}
diff --git a/templates/es/jobs.tmpl b/templates/es/jobs.tmpl
index 26d1e7adf..e1bc195b5 100644
--- a/templates/es/jobs.tmpl
+++ b/templates/es/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/es/list-available-printers.tmpl b/templates/es/list-available-printers.tmpl
index b4ea626ad..51e0eb982 100644
--- a/templates/es/list-available-printers.tmpl
+++ b/templates/es/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/es/modify-class.tmpl b/templates/es/modify-class.tmpl
index 0dfb4736e..a50b2bb72 100644
--- a/templates/es/modify-class.tmpl
+++ b/templates/es/modify-class.tmpl
@@ -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}">
diff --git a/templates/es/modify-printer.tmpl b/templates/es/modify-printer.tmpl
index 944a087bc..3c09da09e 100644
--- a/templates/es/modify-printer.tmpl
+++ b/templates/es/modify-printer.tmpl
@@ -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}">
diff --git a/templates/es/printer-confirm.tmpl b/templates/es/printer-confirm.tmpl
index bd97f50d9..1de104a63 100644
--- a/templates/es/printer-confirm.tmpl
+++ b/templates/es/printer-confirm.tmpl
@@ -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>
diff --git a/templates/es/printer.tmpl b/templates/es/printer.tmpl
index 2a1ad0955..f7642ac0c 100644
--- a/templates/es/printer.tmpl
+++ b/templates/es/printer.tmpl
@@ -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>
diff --git a/templates/es/samba-export.tmpl b/templates/es/samba-export.tmpl
index 8898f6e4f..0036372ed 100644
--- a/templates/es/samba-export.tmpl
+++ b/templates/es/samba-export.tmpl
@@ -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>
diff --git a/templates/es/set-printer-options-header.tmpl b/templates/es/set-printer-options-header.tmpl
index fed45926d..8a2740b3b 100644
--- a/templates/es/set-printer-options-header.tmpl
+++ b/templates/es/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/es/users.tmpl b/templates/es/users.tmpl
index 1b3084278..a8a645e6f 100644
--- a/templates/es/users.tmpl
+++ b/templates/es/users.tmpl
@@ -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}">:}
diff --git a/templates/eu/add-class.tmpl b/templates/eu/add-class.tmpl
index a17ce9852..bd7436ae2 100644
--- a/templates/eu/add-class.tmpl
+++ b/templates/eu/add-class.tmpl
@@ -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>
diff --git a/templates/eu/add-printer.tmpl b/templates/eu/add-printer.tmpl
index 853d052ff..312da1e6e 100644
--- a/templates/eu/add-printer.tmpl
+++ b/templates/eu/add-printer.tmpl
@@ -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}">
diff --git a/templates/eu/add-rss-subscription.tmpl b/templates/eu/add-rss-subscription.tmpl
index 01421c455..b81b5b22f 100644
--- a/templates/eu/add-rss-subscription.tmpl
+++ b/templates/eu/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/eu/admin.tmpl b/templates/eu/admin.tmpl
index 5f13fe21e..8b5ecddcb 100644
--- a/templates/eu/admin.tmpl
+++ b/templates/eu/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/eu/choose-device.tmpl b/templates/eu/choose-device.tmpl
index e2e9b26b1..36b7b86b7 100644
--- a/templates/eu/choose-device.tmpl
+++ b/templates/eu/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/eu/choose-make.tmpl b/templates/eu/choose-make.tmpl
index 4e61c1577..9fb389764 100644
--- a/templates/eu/choose-make.tmpl
+++ b/templates/eu/choose-make.tmpl
@@ -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}">
diff --git a/templates/eu/choose-model.tmpl b/templates/eu/choose-model.tmpl
index d89fe8eab..5824932b7 100644
--- a/templates/eu/choose-model.tmpl
+++ b/templates/eu/choose-model.tmpl
@@ -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}">
diff --git a/templates/eu/choose-serial.tmpl b/templates/eu/choose-serial.tmpl
index 1cea7c0b8..a4dbba2e5 100644
--- a/templates/eu/choose-serial.tmpl
+++ b/templates/eu/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/eu/choose-uri.tmpl b/templates/eu/choose-uri.tmpl
index dfecf4f71..2c7d0f270 100644
--- a/templates/eu/choose-uri.tmpl
+++ b/templates/eu/choose-uri.tmpl
@@ -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}">
diff --git a/templates/eu/class-confirm.tmpl b/templates/eu/class-confirm.tmpl
index 30e9be0c8..f4a1a6f40 100644
--- a/templates/eu/class-confirm.tmpl
+++ b/templates/eu/class-confirm.tmpl
@@ -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>
diff --git a/templates/eu/class.tmpl b/templates/eu/class.tmpl
index d569f2049..17e8c2694 100644
--- a/templates/eu/class.tmpl
+++ b/templates/eu/class.tmpl
@@ -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>
diff --git a/templates/eu/edit-config.tmpl b/templates/eu/edit-config.tmpl
index b6760b4c0..4b2ba7bca 100644
--- a/templates/eu/edit-config.tmpl
+++ b/templates/eu/edit-config.tmpl
@@ -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>
diff --git a/templates/eu/job-move.tmpl b/templates/eu/job-move.tmpl
index d1cb5e7f9..f337353b2 100644
--- a/templates/eu/job-move.tmpl
+++ b/templates/eu/job-move.tmpl
@@ -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}">:}
diff --git a/templates/eu/jobs.tmpl b/templates/eu/jobs.tmpl
index 9aabce2d2..3071f6d40 100644
--- a/templates/eu/jobs.tmpl
+++ b/templates/eu/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/eu/list-available-printers.tmpl b/templates/eu/list-available-printers.tmpl
index 0431c8ac1..c8a397f3e 100644
--- a/templates/eu/list-available-printers.tmpl
+++ b/templates/eu/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/eu/modify-class.tmpl b/templates/eu/modify-class.tmpl
index dfd1322ea..bce650341 100644
--- a/templates/eu/modify-class.tmpl
+++ b/templates/eu/modify-class.tmpl
@@ -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}">
diff --git a/templates/eu/modify-printer.tmpl b/templates/eu/modify-printer.tmpl
index 23f308b66..9b0417a54 100644
--- a/templates/eu/modify-printer.tmpl
+++ b/templates/eu/modify-printer.tmpl
@@ -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}">
diff --git a/templates/eu/printer-confirm.tmpl b/templates/eu/printer-confirm.tmpl
index 29ff12bcc..d72d24010 100644
--- a/templates/eu/printer-confirm.tmpl
+++ b/templates/eu/printer-confirm.tmpl
@@ -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>
diff --git a/templates/eu/printer.tmpl b/templates/eu/printer.tmpl
index e1ec7c7c9..ac984ebd0 100644
--- a/templates/eu/printer.tmpl
+++ b/templates/eu/printer.tmpl
@@ -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>
diff --git a/templates/eu/samba-export.tmpl b/templates/eu/samba-export.tmpl
index 6368c53f9..b6851f86b 100644
--- a/templates/eu/samba-export.tmpl
+++ b/templates/eu/samba-export.tmpl
@@ -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>
diff --git a/templates/eu/set-printer-options-header.tmpl b/templates/eu/set-printer-options-header.tmpl
index d84e91c2d..89b548b2f 100644
--- a/templates/eu/set-printer-options-header.tmpl
+++ b/templates/eu/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/eu/users.tmpl b/templates/eu/users.tmpl
index fb4ef638d..ba0ee968b 100644
--- a/templates/eu/users.tmpl
+++ b/templates/eu/users.tmpl
@@ -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}">:}
diff --git a/templates/id/add-class.tmpl b/templates/id/add-class.tmpl
index b64af5d6c..55f90ad2e 100644
--- a/templates/id/add-class.tmpl
+++ b/templates/id/add-class.tmpl
@@ -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>
diff --git a/templates/id/add-printer.tmpl b/templates/id/add-printer.tmpl
index 92529565c..5c7c7ccdd 100644
--- a/templates/id/add-printer.tmpl
+++ b/templates/id/add-printer.tmpl
@@ -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}">:}
diff --git a/templates/id/add-rss-subscription.tmpl b/templates/id/add-rss-subscription.tmpl
index ac9e3d403..3d5ae7d70 100644
--- a/templates/id/add-rss-subscription.tmpl
+++ b/templates/id/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/id/admin.tmpl b/templates/id/admin.tmpl
index d7ea6a623..9106d6518 100644
--- a/templates/id/admin.tmpl
+++ b/templates/id/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/id/choose-device.tmpl b/templates/id/choose-device.tmpl
index 6bd91bd14..8f812a5e4 100644
--- a/templates/id/choose-device.tmpl
+++ b/templates/id/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/id/choose-make.tmpl b/templates/id/choose-make.tmpl
index 3362738de..d04338fcc 100644
--- a/templates/id/choose-make.tmpl
+++ b/templates/id/choose-make.tmpl
@@ -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}">
diff --git a/templates/id/choose-model.tmpl b/templates/id/choose-model.tmpl
index d294a3b25..c4cfdb9d0 100644
--- a/templates/id/choose-model.tmpl
+++ b/templates/id/choose-model.tmpl
@@ -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}">
diff --git a/templates/id/choose-serial.tmpl b/templates/id/choose-serial.tmpl
index ceb291f8f..19de16c4f 100644
--- a/templates/id/choose-serial.tmpl
+++ b/templates/id/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/id/choose-uri.tmpl b/templates/id/choose-uri.tmpl
index 57380f6c4..61dfdfe62 100644
--- a/templates/id/choose-uri.tmpl
+++ b/templates/id/choose-uri.tmpl
@@ -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}">
diff --git a/templates/id/class-confirm.tmpl b/templates/id/class-confirm.tmpl
index 23bec54ff..3805b9177 100644
--- a/templates/id/class-confirm.tmpl
+++ b/templates/id/class-confirm.tmpl
@@ -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>
diff --git a/templates/id/class.tmpl b/templates/id/class.tmpl
index ab85b1f88..6cb78c99a 100644
--- a/templates/id/class.tmpl
+++ b/templates/id/class.tmpl
@@ -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>
diff --git a/templates/id/edit-config.tmpl b/templates/id/edit-config.tmpl
index fde6c632f..6701f84ac 100644
--- a/templates/id/edit-config.tmpl
+++ b/templates/id/edit-config.tmpl
@@ -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>
diff --git a/templates/id/job-move.tmpl b/templates/id/job-move.tmpl
index 91fdbc421..9ec881a04 100644
--- a/templates/id/job-move.tmpl
+++ b/templates/id/job-move.tmpl
@@ -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}">:}
diff --git a/templates/id/jobs.tmpl b/templates/id/jobs.tmpl
index 5670d6d22..1cd13a0ec 100644
--- a/templates/id/jobs.tmpl
+++ b/templates/id/jobs.tmpl
@@ -17,18 +17,17 @@
<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>
}
diff --git a/templates/id/list-available-printers.tmpl b/templates/id/list-available-printers.tmpl
index 3c8884c2b..f3ca39fd9 100644
--- a/templates/id/list-available-printers.tmpl
+++ b/templates/id/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/id/modify-class.tmpl b/templates/id/modify-class.tmpl
index ad8f3113a..db2d65e26 100644
--- a/templates/id/modify-class.tmpl
+++ b/templates/id/modify-class.tmpl
@@ -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}">
diff --git a/templates/id/modify-printer.tmpl b/templates/id/modify-printer.tmpl
index ffe1203df..9bdb0c4f1 100644
--- a/templates/id/modify-printer.tmpl
+++ b/templates/id/modify-printer.tmpl
@@ -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}">
diff --git a/templates/id/printer-confirm.tmpl b/templates/id/printer-confirm.tmpl
index de668e741..e6d89d616 100644
--- a/templates/id/printer-confirm.tmpl
+++ b/templates/id/printer-confirm.tmpl
@@ -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>
diff --git a/templates/id/printer.tmpl b/templates/id/printer.tmpl
index 68e0a3981..4c56b6761 100644
--- a/templates/id/printer.tmpl
+++ b/templates/id/printer.tmpl
@@ -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>
diff --git a/templates/id/samba-export.tmpl b/templates/id/samba-export.tmpl
index c42f7b6a3..4d9e17519 100644
--- a/templates/id/samba-export.tmpl
+++ b/templates/id/samba-export.tmpl
@@ -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>
diff --git a/templates/id/set-printer-options-header.tmpl b/templates/id/set-printer-options-header.tmpl
index 12386dc29..017e2c475 100644
--- a/templates/id/set-printer-options-header.tmpl
+++ b/templates/id/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/id/users.tmpl b/templates/id/users.tmpl
index 3795d694a..fe9107050 100644
--- a/templates/id/users.tmpl
+++ b/templates/id/users.tmpl
@@ -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}">:}
diff --git a/templates/it/add-class.tmpl b/templates/it/add-class.tmpl
index 91130b02a..cff0d45bc 100644
--- a/templates/it/add-class.tmpl
+++ b/templates/it/add-class.tmpl
@@ -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>
diff --git a/templates/it/add-printer.tmpl b/templates/it/add-printer.tmpl
index bfd208020..3bf0906fa 100644
--- a/templates/it/add-printer.tmpl
+++ b/templates/it/add-printer.tmpl
@@ -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}">:}
diff --git a/templates/it/add-rss-subscription.tmpl b/templates/it/add-rss-subscription.tmpl
index 69f658b15..ba33c14fd 100644
--- a/templates/it/add-rss-subscription.tmpl
+++ b/templates/it/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/it/admin.tmpl b/templates/it/admin.tmpl
index 5ffa0019d..355c51fcc 100644
--- a/templates/it/admin.tmpl
+++ b/templates/it/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/it/choose-device.tmpl b/templates/it/choose-device.tmpl
index f02a680fb..3420fdfe1 100644
--- a/templates/it/choose-device.tmpl
+++ b/templates/it/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/it/choose-make.tmpl b/templates/it/choose-make.tmpl
index 12c596176..3bb4c78c4 100644
--- a/templates/it/choose-make.tmpl
+++ b/templates/it/choose-make.tmpl
@@ -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}">
diff --git a/templates/it/choose-model.tmpl b/templates/it/choose-model.tmpl
index aa9e0efea..d7e935769 100644
--- a/templates/it/choose-model.tmpl
+++ b/templates/it/choose-model.tmpl
@@ -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}">
diff --git a/templates/it/choose-serial.tmpl b/templates/it/choose-serial.tmpl
index a17eb0574..106393adb 100644
--- a/templates/it/choose-serial.tmpl
+++ b/templates/it/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/it/choose-uri.tmpl b/templates/it/choose-uri.tmpl
index fe4f8c325..8a4b68584 100644
--- a/templates/it/choose-uri.tmpl
+++ b/templates/it/choose-uri.tmpl
@@ -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}">
diff --git a/templates/it/class-confirm.tmpl b/templates/it/class-confirm.tmpl
index f05657f13..4e99f4574 100644
--- a/templates/it/class-confirm.tmpl
+++ b/templates/it/class-confirm.tmpl
@@ -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>
diff --git a/templates/it/class.tmpl b/templates/it/class.tmpl
index fd5b3e83b..06a768acf 100644
--- a/templates/it/class.tmpl
+++ b/templates/it/class.tmpl
@@ -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>
diff --git a/templates/it/edit-config.tmpl b/templates/it/edit-config.tmpl
index 9568843db..c8d8ea8a9 100644
--- a/templates/it/edit-config.tmpl
+++ b/templates/it/edit-config.tmpl
@@ -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>
diff --git a/templates/it/job-move.tmpl b/templates/it/job-move.tmpl
index 2ddc44a90..0a52ba2f2 100644
--- a/templates/it/job-move.tmpl
+++ b/templates/it/job-move.tmpl
@@ -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}">:}
diff --git a/templates/it/jobs.tmpl b/templates/it/jobs.tmpl
index 4c0ac244d..494c1eebd 100644
--- a/templates/it/jobs.tmpl
+++ b/templates/it/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/it/list-available-printers.tmpl b/templates/it/list-available-printers.tmpl
index 3245f5909..147d6103c 100644
--- a/templates/it/list-available-printers.tmpl
+++ b/templates/it/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/it/modify-class.tmpl b/templates/it/modify-class.tmpl
index f62169545..065f2b91a 100644
--- a/templates/it/modify-class.tmpl
+++ b/templates/it/modify-class.tmpl
@@ -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}">
diff --git a/templates/it/modify-printer.tmpl b/templates/it/modify-printer.tmpl
index 4d1c97b7f..a6303f298 100644
--- a/templates/it/modify-printer.tmpl
+++ b/templates/it/modify-printer.tmpl
@@ -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}">
diff --git a/templates/it/printer-confirm.tmpl b/templates/it/printer-confirm.tmpl
index b9c009d80..e23071c9f 100644
--- a/templates/it/printer-confirm.tmpl
+++ b/templates/it/printer-confirm.tmpl
@@ -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>
diff --git a/templates/it/printer.tmpl b/templates/it/printer.tmpl
index b7a38278e..78fc08bea 100644
--- a/templates/it/printer.tmpl
+++ b/templates/it/printer.tmpl
@@ -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>
diff --git a/templates/it/samba-export.tmpl b/templates/it/samba-export.tmpl
index 5ac76dded..bce7469d0 100644
--- a/templates/it/samba-export.tmpl
+++ b/templates/it/samba-export.tmpl
@@ -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>
diff --git a/templates/it/set-printer-options-header.tmpl b/templates/it/set-printer-options-header.tmpl
index 735341c16..b0867cedb 100644
--- a/templates/it/set-printer-options-header.tmpl
+++ b/templates/it/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/it/users.tmpl b/templates/it/users.tmpl
index f547e414a..34d8adb10 100644
--- a/templates/it/users.tmpl
+++ b/templates/it/users.tmpl
@@ -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}">:}
diff --git a/templates/ja/add-class.tmpl b/templates/ja/add-class.tmpl
index b40954fa4..11108ccfe 100644
--- a/templates/ja/add-class.tmpl
+++ b/templates/ja/add-class.tmpl
@@ -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>
diff --git a/templates/ja/add-printer.tmpl b/templates/ja/add-printer.tmpl
index c98424679..f054254aa 100644
--- a/templates/ja/add-printer.tmpl
+++ b/templates/ja/add-printer.tmpl
@@ -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}">
diff --git a/templates/ja/add-rss-subscription.tmpl b/templates/ja/add-rss-subscription.tmpl
index a2ba7538b..70203c1f9 100644
--- a/templates/ja/add-rss-subscription.tmpl
+++ b/templates/ja/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/ja/admin.tmpl b/templates/ja/admin.tmpl
index f2904cb44..e1e022951 100644
--- a/templates/ja/admin.tmpl
+++ b/templates/ja/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/ja/choose-device.tmpl b/templates/ja/choose-device.tmpl
index a4a8efa51..05700c3c7 100644
--- a/templates/ja/choose-device.tmpl
+++ b/templates/ja/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/ja/choose-make.tmpl b/templates/ja/choose-make.tmpl
index 0a1eb79bc..c800d9818 100644
--- a/templates/ja/choose-make.tmpl
+++ b/templates/ja/choose-make.tmpl
@@ -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}">
diff --git a/templates/ja/choose-model.tmpl b/templates/ja/choose-model.tmpl
index 90d5cf45b..20011b4d5 100644
--- a/templates/ja/choose-model.tmpl
+++ b/templates/ja/choose-model.tmpl
@@ -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}">
diff --git a/templates/ja/choose-serial.tmpl b/templates/ja/choose-serial.tmpl
index c8c4542f4..924b84a74 100644
--- a/templates/ja/choose-serial.tmpl
+++ b/templates/ja/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/ja/choose-uri.tmpl b/templates/ja/choose-uri.tmpl
index 893da3ec1..bc8c0bc03 100644
--- a/templates/ja/choose-uri.tmpl
+++ b/templates/ja/choose-uri.tmpl
@@ -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}">
diff --git a/templates/ja/class-confirm.tmpl b/templates/ja/class-confirm.tmpl
index 20ff73f38..e50b6a90a 100644
--- a/templates/ja/class-confirm.tmpl
+++ b/templates/ja/class-confirm.tmpl
@@ -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>
diff --git a/templates/ja/class.tmpl b/templates/ja/class.tmpl
index 82b753d32..2ee45eea1 100644
--- a/templates/ja/class.tmpl
+++ b/templates/ja/class.tmpl
@@ -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>
diff --git a/templates/ja/edit-config.tmpl b/templates/ja/edit-config.tmpl
index 45d4eb407..a05a55479 100644
--- a/templates/ja/edit-config.tmpl
+++ b/templates/ja/edit-config.tmpl
@@ -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>
diff --git a/templates/ja/job-move.tmpl b/templates/ja/job-move.tmpl
index 2acd2c51f..54da7e038 100644
--- a/templates/ja/job-move.tmpl
+++ b/templates/ja/job-move.tmpl
@@ -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}">:}
diff --git a/templates/ja/jobs.tmpl b/templates/ja/jobs.tmpl
index e0d917c25..bff543aea 100644
--- a/templates/ja/jobs.tmpl
+++ b/templates/ja/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/ja/list-available-printers.tmpl b/templates/ja/list-available-printers.tmpl
index 554270ad6..f70b5aac0 100644
--- a/templates/ja/list-available-printers.tmpl
+++ b/templates/ja/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/ja/modify-class.tmpl b/templates/ja/modify-class.tmpl
index c5fe07d5e..a41010f3f 100644
--- a/templates/ja/modify-class.tmpl
+++ b/templates/ja/modify-class.tmpl
@@ -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}">
diff --git a/templates/ja/modify-printer.tmpl b/templates/ja/modify-printer.tmpl
index ff14b400b..d8ef5f04b 100644
--- a/templates/ja/modify-printer.tmpl
+++ b/templates/ja/modify-printer.tmpl
@@ -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}">
diff --git a/templates/ja/printer-confirm.tmpl b/templates/ja/printer-confirm.tmpl
index e6430b2cb..6fdb52cab 100644
--- a/templates/ja/printer-confirm.tmpl
+++ b/templates/ja/printer-confirm.tmpl
@@ -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>
diff --git a/templates/ja/printer.tmpl b/templates/ja/printer.tmpl
index 209abaa3c..fbd9c5ad0 100644
--- a/templates/ja/printer.tmpl
+++ b/templates/ja/printer.tmpl
@@ -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>
diff --git a/templates/ja/samba-export.tmpl b/templates/ja/samba-export.tmpl
index 2ecd36594..74b7991e3 100644
--- a/templates/ja/samba-export.tmpl
+++ b/templates/ja/samba-export.tmpl
@@ -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>
diff --git a/templates/ja/set-printer-options-header.tmpl b/templates/ja/set-printer-options-header.tmpl
index dd8746104..b5896f071 100644
--- a/templates/ja/set-printer-options-header.tmpl
+++ b/templates/ja/set-printer-options-header.tmpl
@@ -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="プリンターにデフォルトオプションを問い合わせる">:}
diff --git a/templates/ja/users.tmpl b/templates/ja/users.tmpl
index 8097cdc7a..b998c6b2b 100644
--- a/templates/ja/users.tmpl
+++ b/templates/ja/users.tmpl
@@ -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}">:}
diff --git a/templates/job-move.tmpl b/templates/job-move.tmpl
index 96b309006..6ef0ff12e 100644
--- a/templates/job-move.tmpl
+++ b/templates/job-move.tmpl
@@ -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}">:}
diff --git a/templates/jobs.tmpl b/templates/jobs.tmpl
index 9e77556bf..9c56b3f94 100644
--- a/templates/jobs.tmpl
+++ b/templates/jobs.tmpl
@@ -17,18 +17,17 @@
<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>
}
diff --git a/templates/list-available-printers.tmpl b/templates/list-available-printers.tmpl
index 8b325fdac..a594439ee 100644
--- a/templates/list-available-printers.tmpl
+++ b/templates/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/modify-class.tmpl b/templates/modify-class.tmpl
index 6d2655463..31f7b9ce3 100644
--- a/templates/modify-class.tmpl
+++ b/templates/modify-class.tmpl
@@ -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}">
diff --git a/templates/modify-printer.tmpl b/templates/modify-printer.tmpl
index f0a8ea874..bdf3df604 100644
--- a/templates/modify-printer.tmpl
+++ b/templates/modify-printer.tmpl
@@ -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}">
diff --git a/templates/pl/add-class.tmpl b/templates/pl/add-class.tmpl
index af5c69ff1..d1f4b66bf 100644
--- a/templates/pl/add-class.tmpl
+++ b/templates/pl/add-class.tmpl
@@ -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>
diff --git a/templates/pl/add-printer.tmpl b/templates/pl/add-printer.tmpl
index 9fa76ca62..45b50a0d4 100644
--- a/templates/pl/add-printer.tmpl
+++ b/templates/pl/add-printer.tmpl
@@ -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}">
diff --git a/templates/pl/add-rss-subscription.tmpl b/templates/pl/add-rss-subscription.tmpl
index 0523454b6..bff170705 100644
--- a/templates/pl/add-rss-subscription.tmpl
+++ b/templates/pl/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/pl/admin.tmpl b/templates/pl/admin.tmpl
index 387f05360..16840361f 100644
--- a/templates/pl/admin.tmpl
+++ b/templates/pl/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/pl/choose-device.tmpl b/templates/pl/choose-device.tmpl
index 7fc06ded4..445745624 100644
--- a/templates/pl/choose-device.tmpl
+++ b/templates/pl/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/pl/choose-make.tmpl b/templates/pl/choose-make.tmpl
index d632619d0..c0ec622a7 100644
--- a/templates/pl/choose-make.tmpl
+++ b/templates/pl/choose-make.tmpl
@@ -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}">
diff --git a/templates/pl/choose-model.tmpl b/templates/pl/choose-model.tmpl
index 6a7cbb672..9438cee56 100644
--- a/templates/pl/choose-model.tmpl
+++ b/templates/pl/choose-model.tmpl
@@ -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}">
diff --git a/templates/pl/choose-serial.tmpl b/templates/pl/choose-serial.tmpl
index 5c42b2434..8bbf8c8c2 100644
--- a/templates/pl/choose-serial.tmpl
+++ b/templates/pl/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/pl/choose-uri.tmpl b/templates/pl/choose-uri.tmpl
index 5c87dbbb2..8d06e103a 100644
--- a/templates/pl/choose-uri.tmpl
+++ b/templates/pl/choose-uri.tmpl
@@ -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}">
diff --git a/templates/pl/class-confirm.tmpl b/templates/pl/class-confirm.tmpl
index 7c38b894b..55cb5ed4e 100644
--- a/templates/pl/class-confirm.tmpl
+++ b/templates/pl/class-confirm.tmpl
@@ -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>
diff --git a/templates/pl/class.tmpl b/templates/pl/class.tmpl
index 9ba9ff431..6d83981d0 100644
--- a/templates/pl/class.tmpl
+++ b/templates/pl/class.tmpl
@@ -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>
diff --git a/templates/pl/edit-config.tmpl b/templates/pl/edit-config.tmpl
index 84c4359bd..3688ee24c 100644
--- a/templates/pl/edit-config.tmpl
+++ b/templates/pl/edit-config.tmpl
@@ -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>
diff --git a/templates/pl/job-move.tmpl b/templates/pl/job-move.tmpl
index 666a1509a..bd77beeb2 100644
--- a/templates/pl/job-move.tmpl
+++ b/templates/pl/job-move.tmpl
@@ -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}">:}
diff --git a/templates/pl/jobs.tmpl b/templates/pl/jobs.tmpl
index dbb7fd9bb..665bdffbd 100644
--- a/templates/pl/jobs.tmpl
+++ b/templates/pl/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/pl/list-available-printers.tmpl b/templates/pl/list-available-printers.tmpl
index d5ba1aa13..aad6a49fa 100644
--- a/templates/pl/list-available-printers.tmpl
+++ b/templates/pl/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/pl/modify-class.tmpl b/templates/pl/modify-class.tmpl
index 483cd0603..b8a213076 100644
--- a/templates/pl/modify-class.tmpl
+++ b/templates/pl/modify-class.tmpl
@@ -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}">
diff --git a/templates/pl/modify-printer.tmpl b/templates/pl/modify-printer.tmpl
index 30b2c14ec..a63f4781c 100644
--- a/templates/pl/modify-printer.tmpl
+++ b/templates/pl/modify-printer.tmpl
@@ -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}">
diff --git a/templates/pl/printer-confirm.tmpl b/templates/pl/printer-confirm.tmpl
index 2e9ab7e41..73f860128 100644
--- a/templates/pl/printer-confirm.tmpl
+++ b/templates/pl/printer-confirm.tmpl
@@ -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>
diff --git a/templates/pl/printer.tmpl b/templates/pl/printer.tmpl
index 43d18ef2d..c62b857a0 100644
--- a/templates/pl/printer.tmpl
+++ b/templates/pl/printer.tmpl
@@ -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>
diff --git a/templates/pl/samba-export.tmpl b/templates/pl/samba-export.tmpl
index c927c3bb5..691a30bb0 100644
--- a/templates/pl/samba-export.tmpl
+++ b/templates/pl/samba-export.tmpl
@@ -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>
diff --git a/templates/pl/set-printer-options-header.tmpl b/templates/pl/set-printer-options-header.tmpl
index 206a5bbe7..d128d7d50 100644
--- a/templates/pl/set-printer-options-header.tmpl
+++ b/templates/pl/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/pl/users.tmpl b/templates/pl/users.tmpl
index 7907c7abb..5cb754952 100644
--- a/templates/pl/users.tmpl
+++ b/templates/pl/users.tmpl
@@ -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}">:}
diff --git a/templates/printer-confirm.tmpl b/templates/printer-confirm.tmpl
index db16d691b..fce9e3494 100644
--- a/templates/printer-confirm.tmpl
+++ b/templates/printer-confirm.tmpl
@@ -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>
diff --git a/templates/printer.tmpl b/templates/printer.tmpl
index b7a38278e..78fc08bea 100644
--- a/templates/printer.tmpl
+++ b/templates/printer.tmpl
@@ -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>
diff --git a/templates/ru/add-class.tmpl b/templates/ru/add-class.tmpl
index e0cadc4e0..41a7f9868 100644
--- a/templates/ru/add-class.tmpl
+++ b/templates/ru/add-class.tmpl
@@ -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>
diff --git a/templates/ru/add-printer.tmpl b/templates/ru/add-printer.tmpl
index 59d6e2193..2d040189c 100644
--- a/templates/ru/add-printer.tmpl
+++ b/templates/ru/add-printer.tmpl
@@ -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}">
diff --git a/templates/ru/add-rss-subscription.tmpl b/templates/ru/add-rss-subscription.tmpl
index 90e2c80ec..4c9925fb7 100644
--- a/templates/ru/add-rss-subscription.tmpl
+++ b/templates/ru/add-rss-subscription.tmpl
@@ -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>
diff --git a/templates/ru/admin.tmpl b/templates/ru/admin.tmpl
index 9362f428c..22d9de064 100644
--- a/templates/ru/admin.tmpl
+++ b/templates/ru/admin.tmpl
@@ -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>
@@ -104,6 +105,6 @@
<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>:}
diff --git a/templates/ru/choose-device.tmpl b/templates/ru/choose-device.tmpl
index 0aee24f1d..3df36db86 100644
--- a/templates/ru/choose-device.tmpl
+++ b/templates/ru/choose-device.tmpl
@@ -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}">:}
diff --git a/templates/ru/choose-make.tmpl b/templates/ru/choose-make.tmpl
index d400356f0..a87d6bf27 100644
--- a/templates/ru/choose-make.tmpl
+++ b/templates/ru/choose-make.tmpl
@@ -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}">
diff --git a/templates/ru/choose-model.tmpl b/templates/ru/choose-model.tmpl
index a6e2e0ef6..9d434f1c3 100644
--- a/templates/ru/choose-model.tmpl
+++ b/templates/ru/choose-model.tmpl
@@ -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}">
diff --git a/templates/ru/choose-serial.tmpl b/templates/ru/choose-serial.tmpl
index cba02600a..21e4bf87f 100644
--- a/templates/ru/choose-serial.tmpl
+++ b/templates/ru/choose-serial.tmpl
@@ -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}">:}
diff --git a/templates/ru/choose-uri.tmpl b/templates/ru/choose-uri.tmpl
index 3672f4428..812f2db88 100644
--- a/templates/ru/choose-uri.tmpl
+++ b/templates/ru/choose-uri.tmpl
@@ -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}">
diff --git a/templates/ru/class-confirm.tmpl b/templates/ru/class-confirm.tmpl
index c4337ecdc..5bef5bf07 100644
--- a/templates/ru/class-confirm.tmpl
+++ b/templates/ru/class-confirm.tmpl
@@ -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>
diff --git a/templates/ru/class.tmpl b/templates/ru/class.tmpl
index 36e674a68..d486b43e2 100644
--- a/templates/ru/class.tmpl
+++ b/templates/ru/class.tmpl
@@ -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>
diff --git a/templates/ru/edit-config.tmpl b/templates/ru/edit-config.tmpl
index f96d32f22..d194059d8 100644
--- a/templates/ru/edit-config.tmpl
+++ b/templates/ru/edit-config.tmpl
@@ -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>
diff --git a/templates/ru/job-move.tmpl b/templates/ru/job-move.tmpl
index 69bfdeb5a..598e4db74 100644
--- a/templates/ru/job-move.tmpl
+++ b/templates/ru/job-move.tmpl
@@ -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}">:}
diff --git a/templates/ru/jobs.tmpl b/templates/ru/jobs.tmpl
index a94b1429f..c2226f67e 100644
--- a/templates/ru/jobs.tmpl
+++ b/templates/ru/jobs.tmpl
@@ -17,18 +17,18 @@
<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>
}
diff --git a/templates/ru/list-available-printers.tmpl b/templates/ru/list-available-printers.tmpl
index 72b6d445a..161562845 100644
--- a/templates/ru/list-available-printers.tmpl
+++ b/templates/ru/list-available-printers.tmpl
@@ -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>}
diff --git a/templates/ru/modify-class.tmpl b/templates/ru/modify-class.tmpl
index d596c9b3f..a85698a52 100644
--- a/templates/ru/modify-class.tmpl
+++ b/templates/ru/modify-class.tmpl
@@ -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}">
diff --git a/templates/ru/modify-printer.tmpl b/templates/ru/modify-printer.tmpl
index 74ea27c3b..6277b5d6f 100644
--- a/templates/ru/modify-printer.tmpl
+++ b/templates/ru/modify-printer.tmpl
@@ -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}">
diff --git a/templates/ru/printer-confirm.tmpl b/templates/ru/printer-confirm.tmpl
index 6776a5742..c57356d07 100644
--- a/templates/ru/printer-confirm.tmpl
+++ b/templates/ru/printer-confirm.tmpl
@@ -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>
diff --git a/templates/ru/printer.tmpl b/templates/ru/printer.tmpl
index da4a0898d..5128d004c 100644
--- a/templates/ru/printer.tmpl
+++ b/templates/ru/printer.tmpl
@@ -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>
diff --git a/templates/ru/samba-export.tmpl b/templates/ru/samba-export.tmpl
index e39b75c0f..22a3acb15 100644
--- a/templates/ru/samba-export.tmpl
+++ b/templates/ru/samba-export.tmpl
@@ -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>
diff --git a/templates/ru/set-printer-options-header.tmpl b/templates/ru/set-printer-options-header.tmpl
index a250a9f52..e5c79dd44 100644
--- a/templates/ru/set-printer-options-header.tmpl
+++ b/templates/ru/set-printer-options-header.tmpl
@@ -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="Запрос принтера для параметров по умолчанию">:}
diff --git a/templates/ru/users.tmpl b/templates/ru/users.tmpl
index 12672a250..c5b357501 100644
--- a/templates/ru/users.tmpl
+++ b/templates/ru/users.tmpl
@@ -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}">:}
diff --git a/templates/samba-export.tmpl b/templates/samba-export.tmpl
index 92a291f1e..6515a4d3a 100644
--- a/templates/samba-export.tmpl
+++ b/templates/samba-export.tmpl
@@ -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>
diff --git a/templates/set-printer-options-header.tmpl b/templates/set-printer-options-header.tmpl
index 462bccf20..3e7db4669 100644
--- a/templates/set-printer-options-header.tmpl
+++ b/templates/set-printer-options-header.tmpl
@@ -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">:}
diff --git a/templates/users.tmpl b/templates/users.tmpl
index 5f9f71f8d..0889f3f31 100644
--- a/templates/users.tmpl
+++ b/templates/users.tmpl
@@ -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}">:}
diff --git a/test/Dependencies b/test/Dependencies
index a395277e9..266f7f2fe 100644
--- a/test/Dependencies
+++ b/test/Dependencies
@@ -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
diff --git a/test/Makefile b/test/Makefile
index dfb008801..60d72fcd5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -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
@@ -17,10 +17,24 @@ 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
index 000000000..bdc1fd610
--- /dev/null
+++ b/test/ipp-1.1.test
@@ -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
index 000000000..0c6778804
--- /dev/null
+++ b/test/ipp-2.0.test
@@ -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
index 000000000..d35eab0aa
--- /dev/null
+++ b/test/ipp-2.1.test
@@ -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$".
+#
diff --git a/test/ipptest.c b/test/ipptest.c
index 28404388d..e94f06f36 100644
--- a/test/ipptest.c
+++ b/test/ipptest.c
@@ -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
@@ -14,13 +14,28 @@
*
* 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.
*/
/*
@@ -29,13 +44,11 @@
#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 */
@@ -45,35 +58,122 @@
* 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"))
{
- printf("Unexpected token %s seen on line %d - aborting test!\n", token,
- linenum);
- httpClose(http);
- return (0);
+ /*
+ * 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, "{"))
+ {
+ 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);
-
- token[sizeof(token) - 1] = '\0';
+ if (!get_token(fp, token, sizeof(token), &linenum))
+ {
+ print_fatal_error("Missing ATTR value tag on line %d.", linenum);
+ goto test_error;
+ }
- for (tempptr = temp, tokenptr = token;
- *tempptr && tokenptr < (token + sizeof(token) - 1);)
- if (*tempptr == '$')
- {
- /*
- * Substitute a string/number...
- */
+ if ((value = ippTagValue(token)) < 0)
+ {
+ print_fatal_error("Bad ATTR value tag \"%s\" on line %d.", token,
+ linenum);
+ goto test_error;
+ }
- 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] */
+ printf("%d: value=%s\n", linenum, ippTagString(value));
+ if (!get_token(fp, attr, sizeof(attr), &linenum))
+ {
+ print_fatal_error("Missing ATTR name 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';
- }
+ if (!get_token(fp, temp, sizeof(temp), &linenum))
+ {
+ print_fatal_error("Missing ATTR value on line %d.", linenum);
+ goto test_error;
+ }
- 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
{
- fprintf(stderr,
- "ipptest: IF-DEFINED without a preceding EXPECT on line %d\n",
- linenum);
- httpClose(http);
- ippDelete(request);
- return (0);
+ print_fatal_error("IF-DEFINED without a preceding EXPECT or STATUS "
+ "on line %d.", linenum);
+ goto test_error;
}
}
- else if (!strcasecmp(token, "DISPLAY") &&
- num_displayed < (int)(sizeof(displayed) / sizeof(displayed[0])))
+ 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
+ {
+ print_fatal_error("WITH-VALUE without a preceding EXPECT on line %d.",
+ linenum);
+ goto test_error;
+ }
+ }
+ 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));
- printf(" %-60.60s [", name);
- fflush(stdout);
+ for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
+ print_attr(attrptr);
+ }
- if (Chunking)
+ printf(" %-69.69s [", name);
+ fflush(stdout);
+ }
+
+ 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,107 +1557,285 @@ do_tests(const char *uri, /* I - URI to connect on */
}
}
}
+ }
- if (pass)
+ 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 (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 ((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));
- if (http->version != HTTP_1_1)
- printf(" BAD HTTP VERSION (%d.%d)\n", http->version / 100,
- http->version % 100);
+ 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 ++)
{
free(expect->name);
@@ -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,6 +1864,149 @@ do_tests(const char *uri, /* I - URI to connect on */
httpClose(http);
return (pass);
+
+ /*
+ * If we get here there was a fatal test error...
+ */
+
+ 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';
}
@@ -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,8 +2065,8 @@ expect_matches(
* Restore the separator if we have one...
*/
- if (next)
- *next++ = '|';
+ if (sep)
+ *next++ = sep;
}
return (match);
@@ -983,6 +2074,291 @@ expect_matches(
/*
+ * '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,8 +2457,11 @@ get_token(FILE *fp, /* I - File to read from */
if (ch == '#')
ungetc(ch, fp);
-
+ else if (ch == '\n')
+ (*linenum) ++;
+
*bufptr = '\0';
+
return (buf);
}
}
@@ -1075,59 +2469,142 @@ get_token(FILE *fp, /* I - File to read from */
/*
+ * '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.
*/
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");
+ 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 :
@@ -1137,31 +2614,66 @@ print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
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)
@@ -1253,26 +2765,1089 @@ 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.
*/
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
index 000000000..6c271979b
--- /dev/null
+++ b/test/print-job-media-col.test
@@ -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
+}
diff --git a/test/str-header.html b/test/str-header.html
index a584063e8..84f0d9b73 100644
--- a/test/str-header.html
+++ b/test/str-header.html
@@ -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%;
@@ -14,11 +14,10 @@
</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
index 000000000..d01d7effc
--- /dev/null
+++ b/vc2005/ipptest.vcproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="cupstestppd"
+ ProjectGUID="{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"
+ RootNamespace="ipptest"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\vcnet;.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="1"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\vcnet;.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="1"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\test\ipptest.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/vcnet/config.h b/vcnet/config.h
index d482aecaf..ab2d920e9 100644
--- a/vcnet/config.h
+++ b/vcnet/config.h
@@ -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"
/*
@@ -208,6 +208,13 @@
/*
+ * Do we have <scsi/sg.h>?
+ */
+
+/* #undef HAVE_SCSI_SG_H */
+
+
+/*
* Use <string.h>, <strings.h>, and/or <bstring.h>?
*/
@@ -574,7 +581,7 @@
* Default GSS service name...
*/
-#define CUPS_DEFAULT_GSSSERVICENAME "ipp"
+#define CUPS_DEFAULT_GSSSERVICENAME "host"
/*
@@ -625,10 +632,24 @@
* 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?
diff --git a/vcnet/cups.sln b/vcnet/cups.sln
index ccf6cbf65..0e950a33b 100644
--- a/vcnet/cups.sln
+++ b/vcnet/cups.sln
@@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
+# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcups2", "libcups2.vcproj", "{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testfile", "testfile.vcproj", "{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}"
@@ -17,6 +17,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cupstestppd", "cupstestppd.
{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipptest", "ipptest.vcproj", "{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -29,24 +34,24 @@ Global
{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|Win32.Build.0 = Debug|Win32
{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|x64.ActiveCfg = Debug|x64
{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|x64.Build.0 = Debug|x64
- {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.ActiveCfg = Debug|Win32
- {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.Build.0 = Debug|Win32
+ {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.ActiveCfg = Release|Win32
+ {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|Win32.Build.0 = Release|Win32
{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|x64.ActiveCfg = Debug|x64
{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|x64.Build.0 = Debug|x64
{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|Win32.ActiveCfg = Debug|Win32
{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|Win32.Build.0 = Debug|Win32
{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|x64.ActiveCfg = Debug|x64
{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|x64.Build.0 = Debug|x64
- {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.ActiveCfg = Debug|Win32
- {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.Build.0 = Debug|Win32
+ {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.ActiveCfg = Release|Win32
+ {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|Win32.Build.0 = Release|Win32
{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|x64.ActiveCfg = Debug|x64
{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|x64.Build.0 = Debug|x64
{90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|Win32.ActiveCfg = Debug|Win32
{90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|Win32.Build.0 = Debug|Win32
{90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|x64.ActiveCfg = Debug|x64
{90B0058C-8393-411F-BD3B-E2C831D4E883}.Debug|x64.Build.0 = Debug|x64
- {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.ActiveCfg = Debug|Win32
- {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.Build.0 = Debug|Win32
+ {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.ActiveCfg = Release|Win32
+ {90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|Win32.Build.0 = Release|Win32
{90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|x64.ActiveCfg = Debug|x64
{90B0058C-8393-411F-BD3B-E2C831D4E883}.Release|x64.Build.0 = Debug|x64
{6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -55,6 +60,14 @@ Global
{6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|Win32.ActiveCfg = Release|Win32
{6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|Win32.Build.0 = Release|Win32
{6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|x64.ActiveCfg = Release|Win32
+ {6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}.Release|x64.Build.0 = Release|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Debug|Win32.Build.0 = Debug|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Debug|x64.ActiveCfg = Debug|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|Win32.ActiveCfg = Release|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|Win32.Build.0 = Release|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.ActiveCfg = Release|Win32
+ {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/vcnet/ipptest.vcproj b/vcnet/ipptest.vcproj
new file mode 100644
index 000000000..9de93f372
--- /dev/null
+++ b/vcnet/ipptest.vcproj
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="ipptest"
+ ProjectGUID="{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"
+ RootNamespace="ipptest"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\vcnet;..;..\vcnet\regex"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="1"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\vcnet;..;..\vcnet\regex"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="1"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\regex\debug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\test\ipptest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\regex\regcomp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\regex\regerror.c"
+ >
+ </File>
+ <File
+ RelativePath=".\regex\regexec.c"
+ >
+ </File>
+ <File
+ RelativePath=".\regex\regfree.c"
+ >
+ </File>
+ <File
+ RelativePath=".\regex\split.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\regex\regex.h"
+ >
+ </File>
+ <File
+ RelativePath=".\regex\regex2.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/vcnet/regex/COPYRIGHT b/vcnet/regex/COPYRIGHT
new file mode 100644
index 000000000..30c1f7a48
--- /dev/null
+++ b/vcnet/regex/COPYRIGHT
@@ -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
index 000000000..3882b3786
--- /dev/null
+++ b/vcnet/regex/Makefile
@@ -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
index 000000000..e6ce37344
--- /dev/null
+++ b/vcnet/regex/README
@@ -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
index 000000000..12953433d
--- /dev/null
+++ b/vcnet/regex/WHATSNEW
@@ -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
index 000000000..0c293028e
--- /dev/null
+++ b/vcnet/regex/cclass.h
@@ -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
index 000000000..02e86e912
--- /dev/null
+++ b/vcnet/regex/cname.h
@@ -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
index 000000000..99ce7da6d
--- /dev/null
+++ b/vcnet/regex/debug.c
@@ -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
index 000000000..5f40ff791
--- /dev/null
+++ b/vcnet/regex/debug.ih
@@ -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
index 000000000..919fe3f64
--- /dev/null
+++ b/vcnet/regex/engine.c
@@ -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
index 000000000..cc98334e7
--- /dev/null
+++ b/vcnet/regex/engine.ih
@@ -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
index 000000000..0221e7713
--- /dev/null
+++ b/vcnet/regex/main.c
@@ -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
index 000000000..5a0118ac4
--- /dev/null
+++ b/vcnet/regex/main.ih
@@ -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
index 000000000..252b246c7
--- /dev/null
+++ b/vcnet/regex/mkh
@@ -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
index 000000000..dc4860110
--- /dev/null
+++ b/vcnet/regex/regcomp.c
@@ -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
index 000000000..0776e7185
--- /dev/null
+++ b/vcnet/regex/regcomp.ih
@@ -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
index 000000000..9ddd25ca9
--- /dev/null
+++ b/vcnet/regex/regerror.c
@@ -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
index 000000000..2cb668c24
--- /dev/null
+++ b/vcnet/regex/regerror.ih
@@ -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
index 000000000..bc747096d
--- /dev/null
+++ b/vcnet/regex/regex.3
@@ -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
index 000000000..0fa180269
--- /dev/null
+++ b/vcnet/regex/regex.7
@@ -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
index 000000000..6918a5521
--- /dev/null
+++ b/vcnet/regex/regex.h
@@ -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
index 000000000..58fd8d8a4
--- /dev/null
+++ b/vcnet/regex/regex2.h
@@ -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
index 000000000..dcb11b285
--- /dev/null
+++ b/vcnet/regex/regexec.c
@@ -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
index 000000000..9a6acf173
--- /dev/null
+++ b/vcnet/regex/regfree.c
@@ -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
index 000000000..188bdb775
--- /dev/null
+++ b/vcnet/regex/split.c
@@ -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
index 000000000..e4d928dad
--- /dev/null
+++ b/vcnet/regex/tests
@@ -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
index 000000000..1a997ac8f
--- /dev/null
+++ b/vcnet/regex/utils.h
@@ -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